Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 750   Methods: 31
NCLOC: 245   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
TreeBasedTask.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 package org.apache.tools.ant.taskdefs.optional.starteam;
 55   
 
 56   
 import com.starbase.starteam.Folder;
 57   
 import com.starbase.starteam.Item;
 58   
 import com.starbase.starteam.Label;
 59   
 import com.starbase.starteam.StarTeamFinder;
 60   
 import com.starbase.starteam.View;
 61   
 import java.util.Enumeration;
 62   
 import java.util.Hashtable;
 63   
 import java.util.StringTokenizer;
 64   
 import org.apache.tools.ant.BuildException;
 65   
 import org.apache.tools.ant.DirectoryScanner;
 66   
 import org.apache.tools.ant.Project;
 67   
 import org.apache.tools.ant.ProjectComponent;
 68   
 
 69   
 /**
 70   
  * FileBasedTask.java
 71   
  * This abstract class is the base for any tasks that are tree-based, that
 72   
  * is, for tasks which iterate over a tree of folders in StarTeam which
 73   
  * is reflected in a tree of folder the local machine.
 74   
  *
 75   
  * This class provides the tree-iteration functionality.  Derived classes
 76   
  * will implement their specific task functionality by the visitor pattern,
 77   
  * specifically by implementing the method
 78   
  * <code>visit(Folder rootStarteamFolder, java.io.File rootLocalFolder)</code>
 79   
  *
 80   
  * Created: Sat Dec 15 16:55:19 2001
 81   
  *
 82   
  * @author <a href="mailto:stevec@ignitesports.com">Steve Cohen</a>
 83   
  * @version 1.0
 84   
  * @see <A HREF="http://www.starbase.com/">StarBase Web Site</A>
 85   
  */
 86   
 
 87   
 public abstract class TreeBasedTask extends StarTeamTask {
 88   
 
 89   
 
 90   
     ///////////////////////////////////////////////////////////////
 91   
     // default values for attributes.
 92   
     ///////////////////////////////////////////////////////////////
 93   
     /**
 94   
      * This constant sets the filter to include all files. This default has
 95   
      * the same result as <CODE>setIncludes("*")</CODE>.
 96   
      *
 97   
      * @see #getIncludes()
 98   
      * @see #setIncludes(String includes)
 99   
      */
 100   
     public static final String DEFAULT_INCLUDESETTING = "*";
 101   
 
 102   
     /**
 103   
      * This disables the exclude filter by default. In other words, no files
 104   
      * are excluded. This setting is equivalent to
 105   
      * <CODE>setExcludes(null)</CODE>.
 106   
      *
 107   
      * @see #getExcludes()
 108   
      * @see #setExcludes(String excludes)
 109   
      */
 110   
     public static final String DEFAULT_EXCLUDESETTING = null;
 111   
 
 112   
     //ATTRIBUTES settable from ant.
 113   
 
 114   
     /**
 115   
      * The root folder of the operation in StarTeam.
 116   
      */
 117   
     private String rootStarteamFolder = "/";
 118   
 
 119   
     /**
 120   
      * The local folder corresponding to starteamFolder.  If not specified
 121   
      * the Star Team default folder will be used.
 122   
      */
 123   
     private String rootLocalFolder = null;
 124   
 
 125   
     /**
 126   
      * All files that fit this pattern are checked out.
 127   
      */
 128   
     private String includes = DEFAULT_INCLUDESETTING;
 129   
 
 130   
     /**
 131   
      * All files fitting this pattern are ignored.
 132   
      */
 133   
     private String excludes = DEFAULT_EXCLUDESETTING;
 134   
 
 135   
     /**
 136   
      * StarTeam label on which to perform task.
 137   
      */
 138   
     private String label = null;
 139   
 
 140   
     /**
 141   
      * Set recursion to false to check out files in only the given folder
 142   
      * and not in its subfolders.
 143   
      */
 144   
     private boolean recursive = true;
 145   
 
 146   
     /**
 147   
      * If forced set to true, files in the target directory will
 148   
      * be processed regardless of status in the repository.
 149   
      * Usually this should be  true if rootlocalfolder is set
 150   
      * because status will be relative to the default folder, not
 151   
      * to the one being processed.
 152   
      */
 153   
     private boolean forced = false;
 154   
 
 155   
     private Label labelInUse = null;
 156   
 
 157   
     ///////////////////////////////////////////////////////////////
 158   
     // GET/SET methods.
 159   
     // Setters, of course are where ant user passes in values.
 160   
     ///////////////////////////////////////////////////////////////
 161   
 
 162   
     /**
 163   
      * Set the root of the subtree in the StarTeam repository from which to 
 164   
      * work; optional.  Defaults to the root folder of the view ('/').
 165   
      * @param rootStarteamFolder the root folder
 166   
      */
 167  0
     public void setRootStarteamFolder(String rootStarteamFolder) {
 168  0
         this.rootStarteamFolder = rootStarteamFolder;
 169   
     }
 170   
 
 171   
     /**
 172   
      * returns the root folder in the Starteam repository
 173   
      * used for this operation
 174   
      * @return the root folder in use
 175   
      */
 176  0
     public String getRootStarteamFolder() {
 177  0
         return this.rootStarteamFolder;
 178   
     }
 179   
 
 180   
     /**
 181   
      * Set the local folder that will be the root of the tree
 182   
      * to which files are checked out; optional.
 183   
      * If this is not supplied, then the StarTeam "default folder"
 184   
      * associated with <tt>rootstarteamfolder</tt> is used.
 185   
      * 
 186   
      * @param rootLocalFolder
 187   
      *               the local folder that will mirror
 188   
      *               this.rootStarteamFolder
 189   
      * 
 190   
      * @see rootLocalFolder
 191   
      */
 192  0
     public void setRootLocalFolder(String rootLocalFolder) {
 193  0
         this.rootLocalFolder = rootLocalFolder;
 194   
     }
 195   
 
 196   
 
 197   
 
 198   
     /**
 199   
      * Returns the local folder specified by the user,
 200   
      * corresponding to the starteam folder for this operation
 201   
      * or null if not specified.
 202   
      * 
 203   
      * @return the local folder that mirrors this.rootStarteamFolder
 204   
      * @see rootLocalFolder
 205   
      */
 206  0
     public String getRootLocalFolder() {
 207  0
         return this.rootLocalFolder;
 208   
     }
 209   
 
 210   
 
 211   
     /**
 212   
      * Declare files to include using standard <tt>includes</tt> patterns; optional. 
 213   
      * @param includes A string of filter patterns to include. Separate the
 214   
      *                 patterns by spaces.
 215   
      * @see #getIncludes()
 216   
      * @see #setExcludes(String excludes)
 217   
      * @see #getExcludes()
 218   
      */
 219  0
     public void setIncludes(String includes) {
 220  0
         this.includes = includes;
 221   
     }
 222   
 
 223   
     /**
 224   
      * Gets the patterns from the include filter. Rather that duplicate the
 225   
      * details of AntStarTeamCheckOut's filtering here, refer to these
 226   
      * links:
 227   
      *
 228   
      * @return A string of filter patterns separated by spaces.
 229   
      * @see #setIncludes(String includes)
 230   
      * @see #setExcludes(String excludes)
 231   
      * @see #getExcludes()
 232   
      */
 233  0
     public String getIncludes() {
 234  0
         return includes;
 235   
     }
 236   
 
 237   
     /**
 238   
      * if excludes have been specified, emit the list to the log
 239   
      */
 240  0
     protected void logIncludes() {
 241  0
         if (this.DEFAULT_INCLUDESETTING != this.includes) {
 242  0
             log("  Includes specified: "+ this.includes);
 243   
         }
 244   
     }
 245   
 
 246   
     /**
 247   
      * Declare files to exclude using standard <tt>excludes</tt> patterns; optional. 
 248   
      * When filtering files, AntStarTeamCheckOut
 249   
      * uses an unmodified version of <CODE>DirectoryScanner</CODE>'s
 250   
      * <CODE>match</CODE> method, so here are the patterns straight from the
 251   
      * Ant source code:
 252   
      * <BR><BR>
 253   
      * Matches a string against a pattern. The pattern contains two special
 254   
      * characters:
 255   
      * <BR>'*' which means zero or more characters,
 256   
      * <BR>'?' which means one and only one character.
 257   
      * <BR><BR>
 258   
      *  For example, if you want to check out all files except .XML and
 259   
      * .HTML files, you would put the following line in your program:
 260   
      * <CODE>setExcludes("*.XML,*.HTML");</CODE>
 261   
      * Finally, note that filters have no effect on the <B>directories</B>
 262   
      * that are scanned; you could not skip over all files in directories
 263   
      * whose names begin with "project," for instance.
 264   
      * <BR><BR>
 265   
      * Treatment of overlapping inlcudes and excludes: To give a simplistic
 266   
      * example suppose that you set your include filter to "*.htm *.html"
 267   
      * and your exclude filter to "index.*". What happens to index.html?
 268   
      * AntStarTeamCheckOut will not check out index.html, as it matches an
 269   
      * exclude filter ("index.*"), even though it matches the include
 270   
      * filter, as well.
 271   
      * <BR><BR>
 272   
      * Please also read the following sections before using filters:
 273   
      *
 274   
      * @param excludes A string of filter patterns to exclude. Separate the
 275   
      *                 patterns by spaces.
 276   
      * @see #setIncludes(String includes)
 277   
      * @see #getIncludes()
 278   
      * @see #getExcludes()
 279   
      */
 280  0
     public void setExcludes(String excludes) {
 281  0
         this.excludes = excludes;
 282   
     }
 283   
 
 284   
     /**
 285   
      * Gets the patterns from the exclude filter. Rather that duplicate the
 286   
      * details of AntStarTeanCheckOut's filtering here, refer to these
 287   
      * links:
 288   
      *
 289   
      * @return A string of filter patterns separated by spaces.
 290   
      * @see #setExcludes(String excludes)
 291   
      * @see #setIncludes(String includes)
 292   
      * @see #getIncludes()
 293   
      */
 294  0
     public String getExcludes() {
 295  0
         return excludes;
 296   
     }
 297   
 
 298   
     /**
 299   
      * if excludes have been specified, emit the list to the log
 300   
      */
 301  0
     protected void logExcludes() {
 302  0
         if (this.DEFAULT_EXCLUDESETTING != this.excludes) {
 303  0
             log("  Excludes specified: "+ this.excludes);
 304   
         }
 305   
     }
 306   
 
 307   
 
 308   
     /**
 309   
      * protected function to allow subclasses to set the label (or not).
 310   
      * sets the StarTeam label
 311   
      *
 312   
      * @param label name of the StarTeam label to be set
 313   
      */
 314  0
     protected void _setLabel(String label) {
 315  0
         if (null != label) {
 316  0
             label = label.trim();
 317  0
             if (label.length() > 0) {
 318  0
                 this.label = label;
 319   
             }
 320   
         }
 321   
     }
 322   
 
 323  0
     protected String getLabel() {
 324  0
         return this.label;
 325   
     }
 326   
 
 327   
     /**
 328   
      * Get the value of recursive.
 329   
      * @return value of recursive.
 330   
      */
 331  0
     public boolean isRecursive() {
 332  0
         return this.recursive;
 333   
     }
 334   
 
 335   
     /**
 336   
      * Flag to set to include files in subfolders in the operation; optional,
 337   
      * default true.
 338   
      * @param v  Value to assign to recursive.
 339   
      */
 340  0
     public void setRecursive(boolean v) {
 341  0
         this.recursive = v;
 342   
     }
 343   
 
 344   
     /**
 345   
      * Get the value of forced.
 346   
      * @return value of forced.
 347   
      */
 348  0
     public boolean isForced() {
 349  0
         return this.forced;
 350   
     }
 351   
 
 352   
     /**
 353   
      * Flag to force actions regardless of the status 
 354   
      * that StarTeam is maintaining for the file; optional, default false.  
 355   
      * If <tt>rootlocalfolder</tt> is set then 
 356   
      * this should be set "true" as otherwise the checkout will be based on statuses 
 357   
      * which do not relate to the target folder.  
 358   
      * @param v  Value to assign to forced.
 359   
      */
 360  0
     public void setForced(boolean v) {
 361  0
         this.forced = v;
 362   
     }
 363   
 
 364   
     /**
 365   
      *  returns true if a label has been specified and it is a view label.
 366   
      * 
 367   
      * @return  true if a label has been specified and it is a view label
 368   
      */
 369  0
     protected boolean isUsingViewLabel() {
 370  0
         return null != this.labelInUse && 
 371   
             this.labelInUse.isViewLabel();
 372   
     }
 373   
     /**
 374   
      *  returns true if a label has been specified and it is a revision label.
 375   
      * 
 376   
      * @return  true if a label has been specified and it is a revision label
 377   
      */
 378  0
     protected boolean isUsingRevisionLabel() {
 379  0
         return null != this.labelInUse && 
 380   
             this.labelInUse.isRevisionLabel();
 381   
     }
 382   
 
 383   
     /**
 384   
      * returns the label being used
 385   
      * 
 386   
      * @return 
 387   
      */
 388  0
     protected Label getLabelInUse() {
 389  0
         return this.labelInUse;
 390   
     }
 391   
 
 392   
     /**
 393   
      * show the label in the log and its type.
 394   
      */
 395  0
     protected void logLabel() {
 396  0
         if (this.isUsingViewLabel()) {
 397  0
             log("  Using view label " + getLabel());
 398   
         }
 399  0
         else if (this.isUsingRevisionLabel()) {
 400  0
             log("  Using revision label " + getLabel());
 401   
         }
 402   
     }
 403   
 
 404   
 
 405   
 
 406   
 
 407   
     ///////////////////////////////////////////////////////////////
 408   
     // INCLUDE-EXCLUDE processing
 409   
     ///////////////////////////////////////////////////////////////
 410   
 
 411   
     /**
 412   
      * Look if the file should be processed by the task.
 413   
      * Don't process it if it fits no include filters or if
 414   
      * it fits an exclude filter.
 415   
      * 
 416   
      * @param pName  the item name to look for being included.
 417   
      * 
 418   
      * @return whether the file should be processed or not.
 419   
      */
 420  0
     protected boolean shouldProcess(String pName) {
 421  0
         boolean includeIt = matchPatterns(getIncludes(), pName);
 422  0
         boolean excludeIt = matchPatterns(getExcludes(), pName);
 423  0
         return (includeIt && !excludeIt);
 424   
     }
 425   
 
 426   
     /**
 427   
      * Convenience method to see if a string match a one pattern
 428   
      * in given set of space-separated patterns.
 429   
      * @param patterns the space-separated list of patterns.
 430   
      * @param pName the name to look for matching.
 431   
      * @return whether the name match at least one pattern.
 432   
      */
 433  0
     protected boolean matchPatterns(String patterns, String pName) {
 434  0
         if (patterns == null) {
 435  0
             return false;
 436   
         }
 437  0
         StringTokenizer exStr = new StringTokenizer(patterns, ",");
 438  0
         while (exStr.hasMoreTokens()) {
 439  0
             if (DirectoryScanner.match(exStr.nextToken(), pName)) {
 440  0
                 return true;
 441   
             }
 442   
         }
 443  0
         return false;
 444   
     }
 445   
 
 446   
     /**
 447   
      * Finds and opens the root starteam folder of the operation specified
 448   
      * by this task.  This will be one of the following cases:
 449   
      * 
 450   
      * @return Starteam's root folder for the operation.
 451   
      * @exception BuildException
 452   
      *                   if the root folder cannot be found in the repository
 453   
      */
 454  0
     private final Folder configureRootStarteamFolder() 
 455   
         throws BuildException 
 456   
     {
 457  0
         Folder starteamrootfolder = null;
 458  0
         try {
 459   
             // no root local mapping has been specified.
 460  0
             View snapshot = openView();
 461   
 
 462   
             // find the starteam folder specified to be the root of the
 463   
             // operation.  Throw if it can't be found.
 464   
 
 465  0
             starteamrootfolder =
 466   
                     StarTeamFinder.findFolder(snapshot.getRootFolder(),
 467   
                             this.rootStarteamFolder);
 468   
 
 469   
         } 
 470   
         catch (BuildException e) {
 471  0
             throw e;
 472   
         }
 473   
         catch (Exception e) {
 474  0
             throw new BuildException(
 475   
                 "Unable to find root folder " + this.rootStarteamFolder + 
 476   
                 " in repository at " + getURL(), e);
 477   
 
 478   
         }
 479   
 
 480  0
         if (null == starteamrootfolder) {
 481  0
             throw new BuildException(
 482   
                 "Unable to find root folder " + this.rootStarteamFolder + 
 483   
                 " in repository at " + getURL());
 484   
         }  
 485   
         
 486  0
         return starteamrootfolder;
 487   
     }
 488   
     
 489   
     /**
 490   
      * Returns the local folder mapped to the given StarTeam root folder
 491   
      * of the operation.  There are two cases here, depending on whether
 492   
      * <code>rootLocalFolder</code> is defined.  
 493   
      * If <code>rootLocalFolder</code> is defined, it will be used to 
 494   
      * establish a root mapping.  Otherwise, the repository's default root 
 495   
      * folder will be used.
 496   
      * 
 497   
      * @param starteamrootfolder
 498   
      *               root Starteam folder initialized for the operation
 499   
      * 
 500   
      * @return the local folder corresponding to the root Starteam folder.
 501   
      * @see findRootStarteamFolder
 502   
      */
 503  0
     private final java.io.File getLocalRootMapping(Folder starteamrootfolder) {
 504   
         // set the local folder.
 505  0
         String localrootfolder;
 506  0
         if (null != this.rootLocalFolder) {
 507  0
             localrootfolder = rootLocalFolder;
 508   
         }
 509   
         else  {
 510   
             // either use default path or root local mapping,
 511   
             // which is now embedded in the root folder
 512  0
             localrootfolder = starteamrootfolder.getPathFragment();
 513   
         }
 514   
 
 515  0
         return new java.io.File(localrootfolder);
 516   
         
 517   
     }
 518   
 
 519   
     /**
 520   
      * extenders should emit to the log an entry describing the parameters
 521   
      * that will be used by this operation.
 522   
      * 
 523   
      * @param starteamrootFolder
 524   
      *               root folder in StarTeam for the operation
 525   
      * @param targetrootFolder
 526   
      *               root local folder for the operation (whether specified by the user or not.
 527   
      */
 528   
     protected abstract void logOperationDescription( 
 529   
         Folder starteamrootFolder, java.io.File targetrootFolder);
 530   
 
 531   
     /**
 532   
      * This method does the work of opening the supplied  Starteam view and
 533   
      * calling the <code>visit()</code> method to perform the task.
 534   
      * Derived classes can customize the called methods 
 535   
      * <code>testPreconditions()</code> and <code>visit()</code>.
 536   
      *
 537   
      * @exception BuildException if any error occurs in the processing
 538   
      * @see <code>testPreconditions()</code>
 539   
      * @see <code>visit()</code>
 540   
      */
 541   
 
 542  0
     public final void execute() throws BuildException {
 543  0
         try {
 544   
 
 545  0
             Folder starteamrootfolder = configureRootStarteamFolder();
 546   
 
 547   
             // set the local folder.
 548  0
             java.io.File localrootfolder = 
 549   
                 getLocalRootMapping(starteamrootfolder);
 550   
 
 551  0
             testPreconditions();
 552   
             
 553   
             // Tell user what he is doing
 554  0
             logOperationDescription(starteamrootfolder, localrootfolder);
 555   
             
 556   
             // Inspect everything in the root folder and then recursively
 557  0
             visit(starteamrootfolder, localrootfolder);
 558   
 
 559   
         } catch (Exception e) {
 560  0
             throw new BuildException(e);
 561   
         }
 562   
     }
 563   
 
 564  0
     private void findLabel(View v) throws BuildException {
 565  0
         Label[] allLabels = v.getLabels();
 566  0
         for (int i = 0; i < allLabels.length; i++) {
 567  0
             Label stLabel = allLabels[i];
 568  0
             log("checking label " + stLabel.getName(), Project.MSG_DEBUG);
 569  0
             if (stLabel != null && !stLabel.isDeleted() && stLabel.getName().equals(this.label)) {
 570  0
                 if (!stLabel.isRevisionLabel() && !stLabel.isViewLabel()) {
 571  0
                     throw new BuildException("Unexpected label type.");
 572   
                 }
 573  0
                 log("using label " + stLabel.getName(), Project.MSG_DEBUG);
 574  0
                 this.labelInUse = stLabel;
 575  0
                 return;
 576   
             }
 577   
         }
 578  0
         throw new BuildException("Error: label "
 579   
                 + this.label
 580   
                 + " does not exist in view "
 581   
                 + v.getFullName());
 582   
 
 583   
     }
 584   
 
 585   
     /**
 586   
      * Helper method calls on the StarTeam API to retrieve an ID number
 587   
      * for the specified view, corresponding to this.label.
 588   
      * @param v the <code>View</code> in which to search for <code>this.label</code>
 589   
      * @return the ID number corresponding to <code>this.label</code> or -1 if
 590   
      *         no label was provided.
 591   
      * @exception BuildException if <code>this.label</code> does not correspond
 592   
      *                           to any label in the supplied view
 593   
      */
 594  0
     protected int getLabelID(View v) throws BuildException {
 595  0
         if (null != this.label) {
 596  0
             findLabel(v);
 597  0
             return this.labelInUse.getID();
 598   
         }
 599  0
         return -1;
 600   
     }
 601   
 
 602  0
     protected int getIDofLabelInUse() {
 603  0
         if (null != this.labelInUse) {
 604  0
             return this.labelInUse.getID();
 605   
         }
 606  0
         return -1;
 607   
     }
 608   
 
 609   
     /**
 610   
      * Derived classes must override this class to define actual processing
 611   
      * to be performed on each folder in the tree defined for the task
 612   
      * 
 613   
      * @param rootStarteamFolder
 614   
      *               the StarTeam folderto be visited
 615   
      * @param rootLocalFolder
 616   
      *               the local mapping of rootStarteamFolder
 617   
      * 
 618   
      * @exception BuildException
 619   
      */
 620   
     protected abstract void visit(Folder rootStarteamFolder,
 621   
                                   java.io.File rootLocalFolder)
 622   
             throws BuildException;
 623   
 
 624   
 
 625   
 
 626   
 
 627   
     /**
 628   
      * Derived classes must override this method to define tests for
 629   
      * any preconditons required by the task.  This method is called at
 630   
      * the beginning of the execute() method.
 631   
      *
 632   
      * @exception BuildException throw if any fatal error exists in the
 633   
      * parameters supplied.  If there is a non-fatal condition, just writing
 634   
      * to the log may be appropriate.
 635   
      * @see <code>execute()</code>
 636   
      */
 637   
     protected abstract void testPreconditions() throws BuildException;
 638   
 
 639   
 
 640   
     /**
 641   
      * Return the full repository path name of a file.  Surprisingly there's
 642   
      * no method in com.starbase.starteam.File to provide this.
 643   
      * 
 644   
      * @param remotefile the Star Team file whose path is to be returned
 645   
      * 
 646   
      * @return the full repository path name of a file.
 647   
      */
 648  0
     public static String getFullRepositoryPath(
 649   
         com.starbase.starteam.File remotefile)
 650   
     {
 651  0
         StringBuffer sb = new StringBuffer();
 652  0
         sb.append(remotefile.getParentFolderHierarchy())
 653   
           .append(remotefile.getName());
 654  0
         return sb.toString();
 655   
     }
 656   
 
 657   
     /**
 658   
      * This class implements a map of existing local files to possibly
 659   
      * existing repository files.  The map is created by a TreeBasedTask
 660   
      * upon recursing into a directory.  Each local item is mapped to an
 661   
      * unattached StarTeam object of the proper type, File->File and
 662   
      * Directory->Folder.
 663   
      * 
 664   
      * As the TreeBased does its work, it deletes from the map all items
 665   
      * it has processed.  
 666   
      * 
 667   
      * When the TreeBased task processes all the items from the repository,
 668   
      * whatever items left in the UnmatchedFileMap are uncontrolled items
 669   
      * and can be processed as appropriate to the task.  In the case of
 670   
      * Checkouts, they can be optionally deleted from the local tree.  In the 
 671   
      * case of Checkins they can optionally be added to the resository.
 672   
      */
 673   
     protected abstract class UnmatchedFileMap extends Hashtable {
 674   
     
 675   
         /**
 676   
          * initializes the UnmatchedFileMap with entries from the local folder
 677   
          * These will be mapped to the corresponding StarTeam entry even though
 678   
          * it will not, in fact, exist in the repository.  But through it, it 
 679   
          * can be added, listed, etc.
 680   
          * 
 681   
          * @param localFolder
 682   
          *        the local folder from which the mappings will be made.
 683   
          * @param remoteFolder
 684   
          *        the corresponding StarTeam folder which will be processed.
 685   
          */
 686  0
         UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) {
 687  0
             if (!localFolder.exists()) {
 688  0
                 return this;
 689   
             }
 690   
 
 691  0
             String[] localFiles = localFolder.list();
 692   
     
 693  0
             for (int i=0; i < localFiles.length; i++) {
 694  0
                 String fn = localFiles[i];
 695  0
                 java.io.File localFile = 
 696   
                     new java.io.File(localFolder, localFiles[i]).getAbsoluteFile();
 697   
                 
 698  0
                 log("adding " + localFile + " to UnmatchedFileMap",
 699   
                     Project.MSG_DEBUG);
 700   
     
 701  0
                 if (localFile.isDirectory()) {
 702  0
                     this.put(localFile, new Folder( remoteFolder, fn, fn));
 703   
                 } 
 704   
                 else {
 705  0
                     com.starbase.starteam.File remoteFile = 
 706   
                         new com.starbase.starteam.File(remoteFolder);
 707  0
                     remoteFile.setName(fn);
 708  0
                     this.put(localFile, remoteFile);
 709   
                 }
 710   
             }
 711  0
             return this;
 712   
         }
 713   
     
 714   
         /**
 715   
          * remove an item found to be controlled from the map.
 716   
          * 
 717   
          * @param localFile the local item found to be controlled.
 718   
          */
 719  0
         void removeControlledItem(java.io.File localFile) {
 720  0
             if (isActive()) {
 721  0
                 log("removing processed " + localFile.getAbsoluteFile() + 
 722   
                     " from UnmatchedFileMap", Project.MSG_DEBUG);
 723  0
                 this.remove(localFile.getAbsoluteFile());
 724   
             }
 725   
         }
 726   
         /**
 727   
          * override will perform the action appropriate for its task to perform
 728   
          * on items which are on the local tree but not in StarTeam.  It is 
 729   
          * assumed that this method will not be called until all the items in
 730   
          * the corresponding folder have been processed, and that the internal 
 731   
          * map * will contain only uncontrolled items.
 732   
          */
 733   
         abstract void processUncontrolledItems() throws BuildException;
 734   
     
 735   
         /**
 736   
          * overrides must define this to declare how this method knows if it 
 737   
          * is active.  This presents extra clock cycles when the functionality
 738   
          * is not called for.
 739   
          * 
 740   
          * @return True if this object is to perform its functionality.
 741   
          */
 742   
         abstract protected boolean isActive();
 743   
     
 744   
     }
 745   
 
 746   
 }
 747   
 
 748   
 
 749   
 
 750