001    package org.apache.maven.scm.provider.clearcase.command.changelog;
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    
022    import org.apache.maven.scm.ChangeFile;
023    import org.apache.maven.scm.ChangeSet;
024    import org.apache.maven.scm.log.ScmLogger;
025    import org.apache.maven.scm.util.AbstractConsumer;
026    
027    import java.util.ArrayList;
028    import java.util.List;
029    
030    /**
031     * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
032     * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
033     * @author Olivier Lamy
034     * @version $Id: ClearCaseChangeLogConsumer.java 1094193 2011-04-17 20:28:59Z olamy $
035     */
036    public class ClearCaseChangeLogConsumer
037        extends AbstractConsumer
038    {
039        /**
040         * Formatter used to parse Clearcase date/timestamp.
041         */
042        private static final String CLEARCASE_TIMESTAMP_PATTERN = "yyyyMMdd.HHmmss";
043    
044        private static final String NAME_TAG = "NAME:";
045    
046        private static final String USER_TAG = "USER:";
047    
048        private static final String DATE_TAG = "DATE:";
049    
050        private static final String COMMENT_TAG = "COMM:";
051    
052        private static final String REVISION_TAG = "REVI:";
053        
054        private List<ChangeSet> entries = new ArrayList<ChangeSet>();
055    
056        // state machine constants for reading clearcase lshistory command output
057    
058        /**
059         * expecting file information
060         */
061        private static final int GET_FILE = 1;
062    
063        /**
064         * expecting date
065         */
066        private static final int GET_DATE = 2;
067    
068        /**
069         * expecting comments
070         */
071        private static final int GET_COMMENT = 3;
072    
073        /**
074         * expecting revision
075         */
076        private static final int GET_REVISION = 4;
077    
078        /**
079         * current status of the parser
080         */
081        private int status = GET_FILE;
082    
083        /**
084         * the current log entry being processed by the parser
085         */
086        private ChangeSet currentChange = null;
087    
088        /**
089         * the current file being processed by the parser
090         */
091        private ChangeFile currentFile = null;
092    
093        private String userDatePattern;
094    
095        // ----------------------------------------------------------------------
096        //
097        // ----------------------------------------------------------------------
098    
099        public ClearCaseChangeLogConsumer( ScmLogger logger, String userDatePattern )
100        {
101            super( logger );
102    
103            this.userDatePattern = userDatePattern;
104        }
105    
106        // ----------------------------------------------------------------------
107        //
108        // ----------------------------------------------------------------------
109    
110        public List<ChangeSet> getModifications()
111        {
112            return entries;
113        }
114    
115        // ----------------------------------------------------------------------
116        // StreamConsumer Implementation
117        // ----------------------------------------------------------------------
118    
119        /** {@inheritDoc} */
120        public void consumeLine( String line )
121        {
122            switch ( getStatus() )
123            {
124                case GET_FILE:
125                    processGetFile( line );
126                    break;
127                case GET_DATE:
128                    processGetDate( line );
129                    break;
130                case GET_COMMENT:
131                    processGetCommentAndUser( line );
132                    break;
133                case GET_REVISION:
134                    processGetRevision( line );
135                    break;
136                default:
137                    if ( getLogger().isWarnEnabled() )
138                    {
139                        getLogger().warn( "Unknown state: " + status );
140                    }
141            }
142        }
143    
144        // ----------------------------------------------------------------------
145        //
146        // ----------------------------------------------------------------------
147    
148        /**
149         * Process the current input line in the Get File state.
150         *
151         * @param line a line of text from the clearcase log output
152         */
153        private void processGetFile( String line )
154        {
155            if ( line.startsWith( NAME_TAG ) )
156            {
157                setCurrentChange( new ChangeSet() );
158                setCurrentFile( new ChangeFile( line.substring( NAME_TAG.length(), line.length() ) ) );
159                setStatus( GET_DATE );
160            }
161        }
162    
163        /**
164         * Process the current input line in the Get Date state.
165         *
166         * @param line a line of text from the clearcase log output
167         */
168        private void processGetDate( String line )
169        {
170            if ( line.startsWith( DATE_TAG ) )
171            {
172                getCurrentChange().setDate(
173                    parseDate( line.substring( DATE_TAG.length() ), userDatePattern, CLEARCASE_TIMESTAMP_PATTERN ) );
174    
175                setStatus( GET_COMMENT );
176            }
177        }
178    
179        /**
180         * Process the current input line in the Get Comment state.
181         *
182         * @param line a line of text from the clearcase log output
183         */
184        private void processGetCommentAndUser( String line )
185        {
186            if ( line.startsWith( COMMENT_TAG ) )
187            {
188                String comm = line.substring( COMMENT_TAG.length() );
189    
190                getCurrentChange().setComment( getCurrentChange().getComment() + comm + "\n" );
191            }
192            else if ( line.startsWith( USER_TAG ) )
193            {
194                getCurrentChange().setAuthor( line.substring( USER_TAG.length() ) );
195    
196                // add entry, and set state to get file
197                getCurrentChange().addFile( getCurrentFile() );
198    
199                entries.add( getCurrentChange() );
200    
201                setStatus( GET_REVISION );
202            }
203            else
204            {
205                // keep gathering comments
206                getCurrentChange().setComment( getCurrentChange().getComment() + line + "\n" );
207            }
208        }
209        
210        /**
211         * Process the current input line in the Get Revision.
212         *
213         * @param line a line of text from the clearcase log output
214         */
215        private void processGetRevision( String line )
216        {
217            if ( line.startsWith( REVISION_TAG ) )
218            {
219                getCurrentChange().setRevision( line.substring( REVISION_TAG.length() ) );
220    
221                setStatus( GET_FILE );
222            }
223        }
224    
225        /**
226         * Getter for property currentFile.
227         *
228         * @return Value of property currentFile.
229         */
230        private ChangeFile getCurrentFile()
231        {
232            return currentFile;
233        }
234    
235        /**
236         * Setter for property currentFile.
237         *
238         * @param currentFile New value of property currentFile.
239         */
240        private void setCurrentFile( ChangeFile currentFile )
241        {
242            this.currentFile = currentFile;
243        }
244    
245        /**
246         * Getter for property currentChange.
247         *
248         * @return Value of property currentChange.
249         */
250        private ChangeSet getCurrentChange()
251        {
252            return currentChange;
253        }
254    
255        /**
256         * Setter for property currentLogEntry.
257         *
258         * @param currentChange New value of property currentLogEntry.
259         */
260        private void setCurrentChange( ChangeSet currentChange )
261        {
262            this.currentChange = currentChange;
263        }
264    
265        /**
266         * Getter for property status.
267         *
268         * @return Value of property status.
269         */
270        private int getStatus()
271        {
272            return status;
273        }
274    
275        /**
276         * Setter for property status.
277         *
278         * @param status New value of property status.
279         */
280        private void setStatus( int status )
281        {
282            this.status = status;
283        }
284    }