001package org.apache.maven.scm.provider.vss.commands.status;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.ArrayList;
023import java.util.List;
024
025import org.apache.maven.scm.ScmFile;
026import org.apache.maven.scm.ScmFileSet;
027import org.apache.maven.scm.ScmFileStatus;
028import org.apache.maven.scm.log.ScmLogger;
029import org.apache.maven.scm.provider.vss.repository.VssScmProviderRepository;
030import org.apache.maven.scm.util.AbstractConsumer;
031import org.codehaus.plexus.util.cli.StreamConsumer;
032
033/**
034 * @author <a href="mailto:triek@thrx.de">Thorsten Riek</a>
035 *
036 */
037public class VssStatusConsumer
038    extends AbstractConsumer
039    implements StreamConsumer
040{
041
042    /**
043     * expecting file information
044     */
045    private static final int DIFF_UNKNOWN = 0;
046
047    /**
048     * expecting files to checkin
049     */
050    private static final int DIFF_LOCAL_FILES_NOT_IN_PROJECT = 1;
051
052    /**
053     * expecting commit
054     */
055    private static final int DIFF_VSS_FILES_DIFFERENT_FROM_LOCAL_FILES = 2;
056
057    /**
058     * expecting update / checkout
059     */
060    private static final int DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER = 3;
061
062    /**
063     * expecting setting akt remote folder
064     */
065    private static final int DIFF_START_DIFFING_REMOTE = 4;
066
067    /**
068     * expecting setting akt local folder
069     */
070    private static final int DIFF_START_DIFFING_LOCAL = 5;
071
072    /**
073     * Marks Diffing remote project folder
074     */
075    private static final String START_DIFFING_REMOTE = "Diffing:";
076
077    /**
078     * Marks Diffing local project folder
079     */
080    private static final String START_DIFFING_LOCAL = "Against:";
081
082    /**
083     * Marks Local files not in the current project
084     */
085    private static final String LOCAL_FILES_NOT_IN_PROJECT = "Local files not in the current project:";
086
087    /**
088     * Marks SourceSafe files different from local files
089     */
090    private static final String VSS_FILES_DIFFERENT_FROM_LOCAL_FILES = "SourceSafe files different from local files:";
091
092    /**
093     * Marks SourceSafe files not in the current folder
094     */
095    private static final String VSS_FILES_NOT_IN_CURRENT_FOLDER = "SourceSafe files not in the current folder:";
096
097    private String remoteProjectFolder = "";
098
099    private String localFolder = "";
100
101    private int lastState = 0;
102
103    private List<ScmFile> updatedFiles = new ArrayList<ScmFile>();
104
105    @SuppressWarnings( "unused" )
106    private VssScmProviderRepository repo;
107
108    @SuppressWarnings( "unused" )
109    private ScmFileSet fileSet;
110
111    public VssStatusConsumer( VssScmProviderRepository repo, ScmLogger logger, ScmFileSet fileSet )
112    {
113        super( logger );
114        this.repo = repo;
115        this.fileSet = fileSet;
116    }
117
118    /** {@inheritDoc} */
119    public void consumeLine( String line )
120    {
121        if ( getLogger().isDebugEnabled() )
122        {
123            getLogger().debug( line );
124        }
125
126        switch ( getLineStatus( line ) )
127        {
128            case DIFF_LOCAL_FILES_NOT_IN_PROJECT:
129                lastState = DIFF_LOCAL_FILES_NOT_IN_PROJECT;
130                break;
131            case DIFF_VSS_FILES_DIFFERENT_FROM_LOCAL_FILES:
132                lastState = DIFF_VSS_FILES_DIFFERENT_FROM_LOCAL_FILES;
133                break;
134            case DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER:
135                lastState = DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER;
136                break;
137            case DIFF_START_DIFFING_LOCAL:
138                lastState = DIFF_START_DIFFING_LOCAL;
139                processLocalFolder( line );
140                break;
141            case DIFF_START_DIFFING_REMOTE:
142                lastState = DIFF_START_DIFFING_REMOTE;
143                processRemoteProjectFolder( line );
144                break;
145            default:
146                processLastStateFiles( line );
147                break;
148        }
149    }
150
151    /**
152     * Process the current input line in the Get File state.
153     * 
154     * @param line a line of text from the VSS log output
155     */
156    private void processLastStateFiles( String line )
157    {
158
159        if ( line != null && line.trim().length() > 0 )
160        {
161            if ( lastState == DIFF_START_DIFFING_LOCAL )
162            {
163                setLocalFolder( localFolder + line );
164                getLogger().debug( "Local folder: " + localFolder );
165            }
166            else if ( lastState == DIFF_START_DIFFING_REMOTE )
167            {
168                setRemoteProjectFolder( remoteProjectFolder + line );
169                getLogger().debug( "Remote folder: " + localFolder );
170            }
171
172            String[] fileLine = line.split( " " );
173            for ( int i = 0; i < fileLine.length; i++ )
174            {
175                if ( fileLine[i].trim().length() > 0 )
176                {
177                    if ( lastState == DIFF_LOCAL_FILES_NOT_IN_PROJECT )
178                    {
179                        updatedFiles.add( new ScmFile( localFolder + fileLine[i], ScmFileStatus.ADDED ) );
180                    }
181                    else if ( lastState == DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER )
182                    {
183                        updatedFiles.add( new ScmFile( localFolder + fileLine[i], ScmFileStatus.UPDATED ) );
184                    }
185                    else if ( lastState == DIFF_VSS_FILES_DIFFERENT_FROM_LOCAL_FILES )
186                    {
187                        updatedFiles.add( new ScmFile( localFolder + fileLine[i], ScmFileStatus.MODIFIED ) );
188                    }
189
190                    if ( getLogger().isDebugEnabled() )
191                    {
192                        getLogger().debug( localFolder + fileLine[i] );
193                    }
194                }
195            }
196        }
197        else
198        {
199            if ( getLogger().isDebugEnabled() )
200            {
201                getLogger().debug( "processLastStateFiles:  empty line" );
202            }
203        }
204
205    }
206
207    /**
208     * Process the current input line in the Get File Path state.
209     * 
210     * @param line a line of text from the VSS log output
211     */
212    private void processLocalFolder( String line )
213    {
214
215        setLocalFolder( line.substring( START_DIFFING_LOCAL.length() ).trim() );
216
217    }
218
219    /**
220     * Process the current input line in the Get File Path state.
221     * 
222     * @param line a line of text from the VSS log output
223     */
224    private void processRemoteProjectFolder( String line )
225    {
226
227        setRemoteProjectFolder( line.substring( START_DIFFING_REMOTE.length() ).trim() );
228
229    }
230
231    /**
232     * Identify the status of a vss get line
233     * 
234     * @param line The line to process
235     * @return status
236     */
237    private int getLineStatus( String line )
238    {
239        int argument = DIFF_UNKNOWN;
240        if ( line.startsWith( LOCAL_FILES_NOT_IN_PROJECT ) )
241        {
242            argument = DIFF_LOCAL_FILES_NOT_IN_PROJECT;
243        }
244        else if ( line.startsWith( VSS_FILES_DIFFERENT_FROM_LOCAL_FILES ) )
245        {
246            argument = DIFF_VSS_FILES_DIFFERENT_FROM_LOCAL_FILES;
247        }
248        else if ( line.startsWith( VSS_FILES_NOT_IN_CURRENT_FOLDER ) )
249        {
250            argument = DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER;
251        }
252        //        else if ( line.startsWith( VSS_FILES_NOT_IN_CURRENT_FOLDER ) )
253        //        {
254        //            Project $/com.fum/fum-utilities/src/main/java/com/fum/utilities/protocol has no
255        //            corresponding folder
256        //            argument = DIFF_VSS_FILES_NOT_IN_CURRENT_FOLDER;
257        //        }
258        else if ( line.startsWith( START_DIFFING_LOCAL ) )
259        {
260            argument = DIFF_START_DIFFING_LOCAL;
261        }
262        else if ( line.startsWith( START_DIFFING_REMOTE ) )
263        {
264            argument = DIFF_START_DIFFING_REMOTE;
265        }
266
267        return argument;
268    }
269
270    public List<ScmFile> getUpdatedFiles()
271    {
272        return updatedFiles;
273    }
274
275    private void setLocalFolder( String localFolder )
276    {
277        if ( localFolder != null && localFolder.trim().length() > 0 )
278        {
279            this.localFolder = localFolder.replace( java.io.File.separatorChar, '/' ) + "/";
280        }
281        else
282        {
283            this.localFolder = "";
284        }
285    }
286
287    private void setRemoteProjectFolder( String remoteProjectFolder )
288    {
289        this.remoteProjectFolder = remoteProjectFolder;
290    }
291
292}