Coverage Report - org.apache.maven.scm.provider.perforce.command.changelog.PerforceChangeLogConsumer
 
Classes in this File Line Coverage Branch Coverage Complexity
PerforceChangeLogConsumer
0 %
0/56
0 %
0/26
4,5
 
 1  
 package org.apache.maven.scm.provider.perforce.command.changelog;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  * http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.scm.ChangeFile;
 23  
 import org.apache.maven.scm.ChangeSet;
 24  
 import org.apache.maven.scm.ScmException;
 25  
 import org.apache.maven.scm.log.ScmLogger;
 26  
 import org.apache.maven.scm.util.AbstractConsumer;
 27  
 import org.apache.regexp.RE;
 28  
 import org.apache.regexp.RESyntaxException;
 29  
 
 30  
 import java.util.ArrayList;
 31  
 import java.util.Date;
 32  
 import java.util.LinkedHashMap;
 33  
 import java.util.List;
 34  
 import java.util.Map;
 35  
 
 36  
 /**
 37  
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
 38  
  * @version $Id: PerforceChangeLogConsumer.java 1057019 2011-01-09 20:13:07Z olamy $
 39  
  */
 40  
 public class PerforceChangeLogConsumer
 41  
     extends AbstractConsumer
 42  
 {
 43  
     /**
 44  
      * Date formatter for perforce timestamp
 45  
      */
 46  
     private static final String PERFORCE_TIMESTAMP_PATTERN = "yyyy/MM/dd HH:mm:ss";
 47  
 
 48  0
     private List<ChangeSet> entries = new ArrayList<ChangeSet>();
 49  
 
 50  
     /**
 51  
      * State machine constant: expecting revision and/or file information
 52  
      */
 53  
     private static final int GET_REVISION = 1;
 54  
 
 55  
     /**
 56  
      * State machine constant: eat the first blank line
 57  
      */
 58  
     private static final int GET_COMMENT_BEGIN = 2;
 59  
 
 60  
     /**
 61  
      * State machine constant: expecting comments
 62  
      */
 63  
     private static final int GET_COMMENT = 3;
 64  
 
 65  
     /**
 66  
      * The comment section ends with a blank line
 67  
      */
 68  
     private static final String COMMENT_DELIMITER = "";
 69  
 
 70  
     /**
 71  
      * A file line begins with two slashes
 72  
      */
 73  
     private static final String FILE_BEGIN_TOKEN = "//";
 74  
 
 75  
     /**
 76  
      * Current status of the parser
 77  
      */
 78  0
     private int status = GET_REVISION;
 79  
 
 80  
     /**
 81  
      * The current log entry being processed by the parser
 82  
      */
 83  
     private ChangeSet currentChange;
 84  
 
 85  
     /**
 86  
      * the current file being processed by the parser
 87  
      */
 88  
     private String currentFile;
 89  
 
 90  
     /**
 91  
      * The location of files within the Perforce depot that we are processing
 92  
      * e.g. //depot/projects/foo/bar
 93  
      */
 94  
     private String repoPath;
 95  
 
 96  
     /**
 97  
      * The regular expression used to match header lines
 98  
      */
 99  
     private RE revisionRegexp;
 100  
 
 101  
     private Date startDate;
 102  
 
 103  
     private Date endDate;
 104  
 
 105  
     private String userDatePattern;
 106  
 
 107  
     private static final String PATTERN = "^\\.\\.\\. #(\\d+) " + // revision number
 108  
         "change (\\d+) .* " + // changelist number
 109  
         "on (.*) " + // date
 110  
         "by (.*)@"; // author
 111  
 
 112  
     public PerforceChangeLogConsumer( String path, Date startDate, Date endDate, String userDatePattern,
 113  
                                       ScmLogger logger )
 114  
     {
 115  0
         super( logger );
 116  
 
 117  0
         this.startDate = startDate;
 118  0
         this.endDate = endDate;
 119  0
         this.userDatePattern = userDatePattern;
 120  0
         this.repoPath = path;
 121  
 
 122  
         try
 123  
         {
 124  0
             revisionRegexp = new RE( PATTERN );
 125  
         }
 126  0
         catch ( RESyntaxException ignored )
 127  
         {
 128  0
             if ( getLogger().isErrorEnabled() )
 129  
             {
 130  0
                 getLogger().error( "Could not create regexp to parse perforce log file", ignored );
 131  
             }
 132  0
         }
 133  0
     }
 134  
 
 135  
     // ----------------------------------------------------------------------
 136  
     //
 137  
     // ----------------------------------------------------------------------
 138  
 
 139  
     public List<ChangeSet> getModifications() throws ScmException
 140  
     {
 141  
             
 142  
             // Here there are one entry for each couple (changelist,file). We merge
 143  
             // entries to have only one entry per changelist
 144  
             
 145  
             // Date > ChangeSet
 146  0
         Map<Date,ChangeSet> groupedEntries = new LinkedHashMap<Date,ChangeSet>();
 147  0
         for ( int i = 0; i < entries.size(); i++ )
 148  
         {
 149  0
             ChangeSet cs = (ChangeSet) entries.get( i );
 150  0
             ChangeSet hit = (ChangeSet) groupedEntries.get( cs.getDate() );
 151  0
             if ( hit != null )
 152  
             {
 153  0
                 if ( cs.getFiles().size() != 1 )
 154  
                 {
 155  0
                     throw new ScmException( "Merge of entries failed. Bad entry size: " + cs.getFiles().size() );
 156  
                 }
 157  0
                 hit.addFile( (ChangeFile) cs.getFiles().get( 0 ) );
 158  
             }
 159  
             else
 160  
             {
 161  0
                 groupedEntries.put( cs.getDate(), cs );
 162  
             }
 163  
         }
 164  
 
 165  0
         List<ChangeSet> result = new ArrayList<ChangeSet>();
 166  0
         result.addAll( groupedEntries.values() );
 167  
 
 168  0
         return result;
 169  
             
 170  
     }
 171  
 
 172  
     // ----------------------------------------------------------------------
 173  
     // StreamConsumer Implementation
 174  
     // ----------------------------------------------------------------------
 175  
 
 176  
     /** {@inheritDoc} */
 177  
     public void consumeLine( String line )
 178  
     {
 179  0
         switch ( status )
 180  
         {
 181  
             case GET_REVISION:
 182  0
                 processGetRevision( line );
 183  0
                 break;
 184  
             case GET_COMMENT_BEGIN:
 185  0
                 status = GET_COMMENT;
 186  0
                 break;
 187  
             case GET_COMMENT:
 188  0
                 processGetComment( line );
 189  0
                 break;
 190  
             default:
 191  0
                 throw new IllegalStateException( "Unknown state: " + status );
 192  
         }
 193  0
     }
 194  
 
 195  
     // ----------------------------------------------------------------------
 196  
     //
 197  
     // ----------------------------------------------------------------------
 198  
 
 199  
     /**
 200  
      * Add a change log entry to the list (if it's not already there)
 201  
      * with the given file.
 202  
      *
 203  
      * @param entry a {@link ChangeSet} to be added to the list if another
 204  
      *              with the same key (p4 change number) doesn't exist already.
 205  
      * @param file  a {@link ChangeFile} to be added to the entry
 206  
      */
 207  
     private void addEntry( ChangeSet entry, ChangeFile file )
 208  
     {
 209  
         // ----------------------------------------------------------------------
 210  
         // Check that we are inside the requested date range
 211  
         // ----------------------------------------------------------------------
 212  
 
 213  0
         if ( startDate != null && entry.getDate().before( startDate ) )
 214  
         {
 215  0
             return;
 216  
         }
 217  
 
 218  0
         if ( endDate != null && entry.getDate().after( endDate ) )
 219  
         {
 220  0
             return;
 221  
         }
 222  
 
 223  
         // ----------------------------------------------------------------------
 224  
         //
 225  
         // ----------------------------------------------------------------------
 226  
 
 227  0
         entry.addFile( file );
 228  
 
 229  0
         entries.add( entry );
 230  0
     }
 231  
 
 232  
     /**
 233  
      * Most of the relevant info is on the revision line matching the
 234  
      * 'pattern' string.
 235  
      *
 236  
      * @param line A line of text from the perforce log output
 237  
      */
 238  
     private void processGetRevision( String line )
 239  
     {
 240  0
         if ( line.startsWith( FILE_BEGIN_TOKEN ) )
 241  
         {
 242  0
             currentFile = line.substring( repoPath.length() + 1 );
 243  0
             return;
 244  
         }
 245  
 
 246  0
         if ( !revisionRegexp.match( line ) )
 247  
         {
 248  0
             return;
 249  
         }
 250  
 
 251  0
         currentChange = new ChangeSet();
 252  0
         currentChange.setDate( parseDate( revisionRegexp.getParen( 3 ), userDatePattern, PERFORCE_TIMESTAMP_PATTERN ) );
 253  0
         currentChange.setAuthor( revisionRegexp.getParen( 4 ) );
 254  
 
 255  0
         status = GET_COMMENT_BEGIN;
 256  0
     }
 257  
 
 258  
     /**
 259  
      * Process the current input line in the GET_COMMENT state.  This
 260  
      * state gathers all of the comments that are part of a log entry.
 261  
      *
 262  
      * @param line a line of text from the perforce log output
 263  
      */
 264  
     private void processGetComment( String line )
 265  
     {
 266  0
         if ( line.equals( COMMENT_DELIMITER ) )
 267  
         {
 268  0
             addEntry( currentChange, new ChangeFile( currentFile, revisionRegexp.getParen( 1 ) ) );
 269  
 
 270  0
             status = GET_REVISION;
 271  
         }
 272  
         else
 273  
         {
 274  0
             currentChange.setComment( currentChange.getComment() + line + "\n" );
 275  
         }
 276  0
     }
 277  
 }