1 package org.apache.maven.clearcaselib;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import java.io.BufferedReader;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25
26 import java.text.ParseException;
27 import java.text.SimpleDateFormat;
28
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Map;
32 import java.util.TreeMap;
33
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.maven.changelog.ChangeLog;
38 import org.apache.maven.changelog.ChangeLogEntry;
39 import org.apache.maven.changelog.ChangeLogFile;
40 import org.apache.maven.changelog.ChangeLogParser;
41
42
43 /**
44 * Clearcase specific implementation of ChangeLogParser interface.
45 *
46 * @author <a href="mailto:aldarion@virgilio.it">Simone Zorzetti</a>
47 */
48 public class ClearcaseChangeLogParser implements ChangeLogParser
49 {
50 /** Log */
51 private static final Log LOG =
52 LogFactory.getLog( ClearcaseChangeLogParser.class );
53
54 /**
55 * Formatter used to parse Clearcase date/timestamp.
56 */
57 private static final SimpleDateFormat CLEARCASE_TIMESTAMP_FORMAT =
58 new SimpleDateFormat( "yyyyMMdd.HHmmss" );
59 private static final String NAME_TAG = "NAME:";
60 private static final String USER_TAG = "USER:";
61 private static final String DATE_TAG = "DATE:";
62 private static final String COMMENT_TAG = "COMM:";
63
64 /**
65 * Custom date/time formatter. Rounds ChangeLogEntry times to the nearest
66 * minute.
67 */
68 private static final SimpleDateFormat ENTRY_KEY_TIMESTAMP_FORMAT =
69 new SimpleDateFormat( "yyyyMMddHHmm" );
70
71 /**
72 * Custom date/time formatter. Rounds ChangeLogEntry to date
73 */
74 private static final SimpleDateFormat GROUPED_ENTRY_KEY_TIMESTAMP_FORMAT =
75 new SimpleDateFormat( "yyyyMMdd" );
76
77
78
79 /** expecting file information */
80 private static final int GET_FILE = 1;
81
82 /** expecting date */
83 private static final int GET_DATE = 2;
84
85 /** expecting comments */
86 private static final int GET_COMMENT = 3;
87
88 /**
89 * rcs entries, in reverse (date, time, author, comment) order
90 */
91 private Map entries = new TreeMap( Collections.reverseOrder() );
92
93 /** current status of the parser */
94 private int status = GET_FILE;
95
96 /** the current log entry being processed by the parser*/
97 private ChangeLogEntry currentLogEntry = null;
98
99 /** the current file being processed by the parser */
100 private ChangeLogFile currentFile = null;
101
102 /**
103 * Create a new ChangeLogParser.
104 */
105 public ClearcaseChangeLogParser()
106 {
107 }
108
109 /**
110 * initialize the parser from the change log
111 * @param changeLog the controlling task
112 * @see ChangeLogParser#init(ChangeLog)
113 */
114 public void init( ChangeLog changeLog )
115 {
116 }
117
118 /**
119 * Clean up any parser resources
120 * @see ChangeLogParser#cleanup()
121 */
122 public void cleanup()
123 {
124 }
125
126 /**
127 * Parse the input stream into a collection.
128 * @param anInputStream an input stream containing clearcase log output
129 * @return a collection of ChangeLogEntry's
130 * @throws IOException when there are errors reading the provided stream
131 */
132 public Collection parse( InputStream anInputStream )
133 throws IOException
134 {
135 BufferedReader stream =
136 new BufferedReader( new InputStreamReader( anInputStream ) );
137
138
139
140
141
142
143
144 String line = null;
145
146 while ( ( line = stream.readLine() ) != null )
147 {
148 switch ( getStatus() )
149 {
150 case GET_FILE :
151 processGetFile( line );
152
153 break;
154
155 case GET_DATE :
156 processGetDate( line );
157
158 break;
159
160 case GET_COMMENT :
161 processGetCommentAndUser( line );
162
163 break;
164
165 default :
166 throw new IllegalStateException( "Unknown state: " + status );
167 }
168 }
169
170 return entries.values();
171 }
172
173 /**
174 * Add a change log entry to the list (if it's not already there)
175 * with the given file.
176 * @param entry a {@link ChangeLogEntry} to be added to the list if another
177 * with the same key doesn't exist already. If the entry's author
178 * is null, the entry wont be added
179 * @param file a {@link ChangeLogFile} to be added to the entry
180 */
181 private void addEntry( ChangeLogEntry entry, ChangeLogFile file )
182 {
183
184 if ( entry.getAuthor() == null )
185 {
186 return;
187 }
188
189
190 if ( entry.getComment().indexOf( "checkin " ) == -1 )
191 {
192 return;
193 }
194
195 String key =
196 ENTRY_KEY_TIMESTAMP_FORMAT.format( entry.getDate() )
197 + entry.getAuthor() + entry.getComment();
198
199 file.setRevision( "" );
200
201 if ( !entries.containsKey( key ) )
202 {
203 entry.addFile( file );
204 entries.put( key, entry );
205 }
206 else
207 {
208 ChangeLogEntry existingEntry = (ChangeLogEntry) entries.get( key );
209
210 existingEntry.addFile( file );
211 }
212 }
213
214 /**
215 * Process the current input line in the Get File state.
216 * @param line a line of text from the clearcase log output
217 */
218 private void processGetFile( String line )
219 {
220 if ( line.startsWith( NAME_TAG ) )
221 {
222 setCurrentLogEntry( new ChangeLogEntry() );
223 setCurrentFile( new ChangeLogFile( line.substring(
224 NAME_TAG.length(), line.length() ) ) );
225 setStatus( GET_DATE );
226 }
227 }
228
229 /**
230 * Process the current input line in the Get Date state.
231 * @param line a line of text from the clearcase log output
232 */
233 private void processGetDate( String line )
234 {
235 if ( line.startsWith( DATE_TAG ) )
236 {
237 try
238 {
239 getCurrentLogEntry().setDate( CLEARCASE_TIMESTAMP_FORMAT
240 .parse( line.substring( DATE_TAG.length() ) ) );
241 }
242 catch ( ParseException e )
243 {
244
245 e.printStackTrace();
246 }
247
248 setStatus( GET_COMMENT );
249 }
250 }
251
252 /**
253 * Process the current input line in the Get Comment state.
254 * @param line a line of text from the clearcase log output
255 */
256 private void processGetCommentAndUser( String line )
257 {
258 if ( line.startsWith( COMMENT_TAG ) )
259 {
260 String comm = line.substring( COMMENT_TAG.length() );
261
262 getCurrentLogEntry().setComment( getCurrentLogEntry()
263 .getComment() + comm
264 + "\n" );
265 }
266 else if ( line.startsWith( USER_TAG ) )
267 {
268 getCurrentLogEntry().setAuthor( line.substring(
269 USER_TAG.length() ).trim() );
270
271
272 addEntry( getCurrentLogEntry(), getCurrentFile() );
273 setStatus( GET_FILE );
274 }
275 else
276 {
277
278 getCurrentLogEntry().setComment( getCurrentLogEntry()
279 .getComment() + line
280 + "\n" );
281 }
282 }
283
284 /**
285 * Getter for property currentFile.
286 * @return Value of property currentFile.
287 */
288 private ChangeLogFile getCurrentFile()
289 {
290 return currentFile;
291 }
292
293 /**
294 * Setter for property currentFile.
295 * @param currentFile New value of property currentFile.
296 */
297 private void setCurrentFile( ChangeLogFile currentFile )
298 {
299 this.currentFile = currentFile;
300 }
301
302 /**
303 * Getter for property currentLogEntry.
304 * @return Value of property currentLogEntry.
305 */
306 private ChangeLogEntry getCurrentLogEntry()
307 {
308 return currentLogEntry;
309 }
310
311 /**
312 * Setter for property currentLogEntry.
313 * @param currentLogEntry New value of property currentLogEntry.
314 */
315 private void setCurrentLogEntry( ChangeLogEntry currentLogEntry )
316 {
317 this.currentLogEntry = currentLogEntry;
318 }
319
320 /**
321 * Getter for property status.
322 * @return Value of property status.
323 */
324 private int getStatus()
325 {
326 return status;
327 }
328
329 /**
330 * Setter for property status.
331 * @param status New value of property status.
332 */
333 private void setStatus( int status )
334 {
335 this.status = status;
336 }
337
338 public void setDateFormatInFile( String dateFormat )
339 {
340 }
341 }