Clover coverage report - XJavaDoc - 1.1
Coverage timestamp: Mon Oct 4 2004 23:49:51 BST
file stats: LOC: 905   Methods: 32
NCLOC: 494   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
XDoc.java 62.1% 71.7% 65.6% 68.1%
coverage coverage
 1   
 /*
 2   
  * Copyright (c) 2001-2003 The XDoclet team
 3   
  * All rights reserved.
 4   
  */
 5   
 package xjavadoc;
 6   
 
 7   
 import java.io.BufferedReader;
 8   
 import java.io.IOException;
 9   
 import java.io.StringReader;
 10   
 import java.util.*;
 11   
 import xjavadoc.event.XDocListener;
 12   
 import xjavadoc.event.XDocEvent;
 13   
 import xjavadoc.event.XTagListener;
 14   
 import xjavadoc.event.XTagEvent;
 15   
 
 16   
 /**
 17   
  * Represents documentation
 18   
  *
 19   
  * @author    Aslak Hellesøy
 20   
  * @created   20. mars 2003
 21   
  */
 22   
 public final class XDoc implements XTagListener
 23   
 {
 24   
     public static int  instanceCount = 0;
 25   
 
 26   
     /**
 27   
      * Platform specific NEWLINE. Javadoc will use this as new line.
 28   
      */
 29   
     private final static String NEWLINE = System.getProperty( "line.separator" );
 30   
 
 31   
     /**
 32   
      * Default comment
 33   
      */
 34   
     private final static String EMPTY_COMMENT = "/**\n */";
 35   
 
 36   
     /**
 37   
      * Maps tag name to List. The Collection contains XTag instances whose name =
 38   
      * name (the map key). The tags in the Lists are ordered by occurrance
 39   
      */
 40   
     private Map        _tagMap;
 41   
 
 42   
     /**
 43   
      * Token (which is linked in the AST) that holds the string representation of
 44   
      * the doc. Needed for printing out the class.
 45   
      */
 46   
     private Token      _javadocToken;
 47   
 
 48   
     private XProgramElement _owner;
 49   
 
 50   
     /**
 51   
      * Contains all the tags in the doc, in order of occurrence.
 52   
      */
 53   
     private List _tags;
 54   
     /**
 55   
      * description of program element
 56   
      */
 57   
     private String     _commentText = "";
 58   
     /**
 59   
      * first sentence of comment text
 60   
      */
 61   
     private String     _firstSentence;
 62   
 
 63   
     private boolean    _dirty = true;
 64   
 
 65   
     private Set        _docListeners = new HashSet();
 66   
 
 67   
     private final XTagFactory _tagFactory;
 68   
 
 69   
     /**
 70   
      * Describe what the XDoc constructor does
 71   
      *
 72   
      * @param javadocToken  Describe what the parameter does
 73   
      * @param owner         Describe what the parameter does
 74   
      * @param tagFactory    Describe what the parameter does
 75   
      */
 76  349
     public XDoc( Token javadocToken, XProgramElement owner, XTagFactory tagFactory )
 77   
     {
 78  349
         instanceCount++;
 79  349
         if( javadocToken == null )
 80   
         {
 81  0
             _javadocToken = Token.newToken( NodeParserConstants.FORMAL_COMMENT );
 82   
         }
 83   
         else
 84   
         {
 85  349
             _javadocToken = javadocToken;
 86   
         }
 87  349
         _owner = owner;
 88  349
         _tagFactory = tagFactory;
 89  349
         if( _javadocToken.image == null )
 90   
         {
 91   
             // the passed token was not from source code, but was created because no javadoc existed.
 92  0
             _javadocToken.image = EMPTY_COMMENT;
 93   
         }
 94   
     }
 95   
 
 96   
     /**
 97   
      * Convert a tag name from the old colon-separated form to the new preferred dot-separated form.
 98   
      *
 99   
      * @param tagName  The name of the tag
 100   
      * @return         Preferred form of the tag
 101   
      */
 102  2814
     public static String dotted( final String tagName )
 103   
     {
 104  2814
         return tagName.replace( ':', '.' );
 105   
     }
 106   
 
 107  565
     private final static String tokenizeAndTrim( final String s )
 108   
     {
 109  565
         StringBuffer sb = new StringBuffer();
 110  565
         StringTokenizer st = new StringTokenizer( s );
 111   
 
 112  565
         while( st.hasMoreTokens() )
 113   
         {
 114  4374
             sb.append( st.nextToken() ).append( " " );
 115   
         }
 116  565
         return sb.toString().trim();
 117   
     }
 118   
 
 119   
     /**
 120   
      * Gets the Owner attribute of the XDoc object
 121   
      *
 122   
      * @return   The Owner value
 123   
      */
 124  355
     public XProgramElement getOwner()
 125   
     {
 126  355
         return _owner;
 127   
     }
 128   
 
 129   
     /**
 130   
      * Returns all the tags in this doc with the specified tagName (not
 131   
      * superclasses). If No tags are found, an empty Collection is returned.
 132   
      *
 133   
      * @param tagName  the name of the tags to return (without the 'at')
 134   
      * @return         A Collection of XTag
 135   
      */
 136  4
     public List getTags( String tagName )
 137   
     {
 138  4
         return getTags( tagName, false );
 139   
     }
 140   
 
 141   
     /**
 142   
      * Returns all the tags with the specified tagName. If No tags are found, an
 143   
      * empty Collection is returned.
 144   
      *
 145   
      * @param tagName       the name of the tags to return (without the 'at')
 146   
      * @param superclasses  if this is true, return tags from superclasses too.
 147   
      * @return              A Collection of XTag
 148   
      */
 149  348
     public List getTags( String tagName, boolean superclasses )
 150   
     {
 151   
 
 152  348
         tagName = dotted( tagName );
 153  348
         if( _dirty )
 154   
         {
 155  342
             parse();
 156   
         }
 157   
 
 158  348
         ensureTagMapInitialised();
 159   
 
 160  348
         List tags = ( List ) _tagMap.get( tagName );
 161   
 
 162  348
         if( !superclasses )
 163   
         {
 164  86
             if( tags == null )
 165   
             {
 166  64
                 tags = AbstractProgramElement.EMPTY_LIST;
 167   
             }
 168  86
             return Collections.unmodifiableList( tags );
 169   
         }
 170   
         else
 171   
         {
 172   
             // Make a new Collection where we append all tags from this and super
 173  262
             LinkedList superTags = new LinkedList();
 174   
 
 175   
             // Add tags from this doc if any.
 176  262
             if( tags != null )
 177   
             {
 178  93
                 superTags.addAll( tags );
 179   
             }
 180   
 
 181   
             // Now add tags from super
 182  262
             XDoc superDoc = getSuperDoc();
 183   
 
 184  262
             if( superDoc != null )
 185   
             {
 186  9
                 superTags.addAll( superDoc.getTags( tagName, true ) );
 187   
             }
 188   
 
 189   
             // Now add tags from implemented interfaces
 190   
             // TODO: How are we going to ensure uniqueness ...
 191   
             // we could get to the same interface tag twice
 192  262
             Iterator docs = getAllSuperDocs().iterator();
 193  262
             while ( docs.hasNext() )
 194   
             {
 195  80
                 XDoc interfaceDoc = (XDoc) docs.next();
 196   
                 // Perhaps the last argument to getTagAttributeValue() should be true
 197  80
                 List interfaceTags = interfaceDoc.getTags( tagName, false );
 198  80
                 superTags.addAll( interfaceTags );
 199   
             }
 200   
 
 201  262
             return Collections.unmodifiableList( superTags );
 202   
         }
 203   
     }
 204   
 
 205   
     /**
 206   
      * Returns all the tags in this doc (not superclasses). If No tags are found,
 207   
      * an empty Collection is returned.
 208   
      *
 209   
      * @return   A Collection of XTag
 210   
      */
 211  9
     public List getTags()
 212   
     {
 213  9
         return getTags( false );
 214   
     }
 215   
 
 216   
     /**
 217   
      * Returns all the tags. If no tags are found, an
 218   
      * empty List is returned.
 219   
      *
 220   
      * @param superclasses  if this is true, return tags from superclasses too.
 221   
      * @return              A List of XTag
 222   
      */
 223  11
     public List getTags( boolean superclasses )
 224   
     {
 225   
 
 226  11
         if( _dirty )
 227   
         {
 228  4
             parse();
 229   
         }
 230  11
         if( !superclasses )
 231   
         {
 232  9
             if( _tags == null )
 233   
             {
 234  0
                 return AbstractProgramElement.EMPTY_LIST;
 235   
             }
 236   
             else
 237   
             {
 238  9
                 return _tags;
 239   
             }
 240   
         }
 241   
         else
 242   
         {
 243   
             // Make a new Collection where we append all tags from this and super
 244  2
             LinkedList tags = new LinkedList();
 245   
 
 246   
             // Add tags from this doc if any.
 247  2
             if( _tags != null )
 248   
             {
 249  2
                 tags.addAll( _tags );
 250   
             }
 251   
 
 252   
             // Now add tags from super
 253  2
             XDoc superDoc = getSuperDoc();
 254   
 
 255  2
             if( superDoc != null )
 256   
             {
 257  1
                 tags.addAll( superDoc.getTags( true ) );
 258   
             }
 259   
 
 260   
             // Now add tags from implemented interfaces
 261   
             // TODO: How are we going to ensure uniqueness ...
 262   
             // we could get to the same interface tag twice
 263  2
             Iterator docs = getAllSuperDocs().iterator();
 264  2
             while ( docs.hasNext() )
 265   
             {
 266  0
                 XDoc interfaceDoc = (XDoc) docs.next();
 267   
                 // Perhaps the last argument to getTagAttributeValue() should be true
 268  0
                 List interfaceTags = interfaceDoc.getTags( false );
 269  0
                 tags.addAll( interfaceTags );
 270   
             }
 271   
 
 272  2
             return Collections.unmodifiableList( tags );
 273   
         }
 274   
     }
 275   
 
 276   
     /**
 277   
      * Get the first tag of name tagName from this doc.  Superclasses are not searched.
 278   
      *
 279   
      * @param tagName  the name of the tag
 280   
      * @return         the tag
 281   
      */
 282  2
     public XTag getTag( String tagName )
 283   
     {
 284  2
         return getTag( tagName, false );
 285   
     }
 286   
 
 287   
     /**
 288   
      * Get the first tag of name tagName.
 289   
      *
 290   
      * @param tagName       the name of the tag to get (without the 'at')
 291   
      * @param superclasses  if this is true, return tags from superclasses too.
 292   
      * @return              the first XTag with name equal to tagName
 293   
      */
 294  2
     public XTag getTag( String tagName, boolean superclasses )
 295   
     {
 296  2
         tagName = dotted( tagName );
 297   
 
 298  2
         Collection tags = getTags( tagName, superclasses );
 299   
 
 300  2
         if( tags.size() == 0 )
 301   
         {
 302  0
             return null;
 303   
         }
 304   
         else
 305   
         {
 306  2
             return ( XTag ) tags.iterator().next();
 307   
         }
 308   
     }
 309   
 
 310   
     /**
 311   
      * Returns the tag attribute value. Does not look in superclasses. If nothing
 312   
      * is found, null is returned.
 313   
      *
 314   
      * @param tagName        The name of the tag to look for (without the 'at')
 315   
      * @param attributeName  The name of the attribute to look for within the tag.
 316   
      * @return               The value of the tag attribute.
 317   
      */
 318  0
     public String getTagAttributeValue( String tagName, String attributeName )
 319   
     {
 320  0
         return getTagAttributeValue( tagName, attributeName, false );
 321   
     }
 322   
 
 323   
     /**
 324   
      * Returns the tag attribute value. If superclasses is true, the first
 325   
      * occurrence is returned when walking up the class hierarchy. If nothing is
 326   
      * found, null is returned.
 327   
      *
 328   
      * @param tagName        The name of the tag to look for (without the 'at')
 329   
      * @param attributeName  The name of the attribute to look for within the tag.
 330   
      * @param superclasses   Set it to true to look in superclasses too.
 331   
      * @return               The value of the tag attribute.
 332   
      */
 333  1
     public String getTagAttributeValue( String tagName, String attributeName, boolean superclasses )
 334   
     {
 335  1
         tagName = dotted( tagName );
 336   
 
 337   
         // Get all the tags, loop over them and return the first occurrence of the attribute.
 338  1
         for( Iterator tags = getTags( tagName ).iterator(); tags.hasNext();  )
 339   
         {
 340  1
             XTag tag = ( XTag ) tags.next();
 341  1
             String attributeValue = tag.getAttributeValue( attributeName );
 342   
 
 343  1
             if( attributeValue != null )
 344   
             {
 345   
                 // found one! Return that.
 346  1
                 return attributeValue;
 347   
             }
 348   
         }
 349   
 
 350   
         // Couldn't find anything here. Ask superclasses
 351   
 
 352  0
         if( superclasses )
 353   
         {
 354  0
             XDoc superDoc = getSuperDoc();
 355   
 
 356  0
             if( superDoc != null )
 357   
             {
 358   
                 // prefer tags defined on a superclass to tags on interfaces
 359  0
                 String superclassTagValue = superDoc.getTagAttributeValue( tagName, attributeName, true );
 360  0
                 if (superclassTagValue!=null) return superclassTagValue;
 361   
             }
 362   
 
 363   
 
 364   
             // check interfaces!
 365  0
             Iterator docs = getAllSuperDocs().iterator();
 366  0
             while ( docs.hasNext() )
 367   
             {
 368  0
                 XDoc interfaceDoc = (XDoc) docs.next();
 369   
                 // Note: this will do a "depth first" search, is that desirable?
 370   
                 // Perhaps the last argument to getTagAttributeValue() should be false
 371  0
                 String tagValue = interfaceDoc.getTagAttributeValue( tagName, attributeName, true );
 372  0
                 if (tagValue!=null) return tagValue;
 373   
             }
 374   
 
 375   
             // We've come to an end. Nothing found. Return null;
 376  0
             return null;
 377   
 
 378   
         }
 379   
         else
 380   
         {
 381   
             // Don't look in superclasses or implemented interfaces. Just return null;
 382  0
             return null;
 383   
         }
 384   
     }
 385   
 
 386   
     /**
 387   
      * return description of program element
 388   
      *
 389   
      * @return   description of program element
 390   
      */
 391  0
     public String getCommentText()
 392   
     {
 393  0
         if( _dirty )
 394   
         {
 395  0
             parse();
 396   
         }
 397  0
         return _commentText;
 398   
     }
 399   
 
 400   
     /**
 401   
      * Return the first sentence of the text of the comment for this doc item.
 402   
      *
 403   
      * @return   First sentence
 404   
      */
 405  5
     public String getFirstSentence()
 406   
     {
 407  5
         if( _dirty )
 408   
         {
 409  3
             parse();
 410   
         }
 411   
 
 412  5
         if( _firstSentence == null )
 413   
         {
 414   
             // Ok, we only have one sentence
 415  5
             if( _commentText.indexOf( '.' ) == -1 )
 416   
             {
 417  2
                 _firstSentence = _commentText;
 418  2
                 return _firstSentence;
 419   
             }
 420   
 
 421   
             // Let's look for the first sentence separator. It should be a dot followed
 422   
             // by a blank, tab or line terminator.
 423  3
             int fromIndex = 0;
 424   
 
 425  3
             while( fromIndex < _commentText.length() - 1 && _firstSentence == null )
 426   
             {
 427  4
                 int dotIndex = _commentText.indexOf( '.', fromIndex );
 428   
 
 429  4
                 if( dotIndex != -1 && dotIndex < _commentText.length() - 1 )
 430   
                 {
 431  3
                     if( " \t\r\n".indexOf( _commentText.charAt( dotIndex + 1 ) ) != -1 )
 432  2
                         _firstSentence = _commentText.substring( 0, dotIndex + 1 );
 433   
                     else
 434  1
                         fromIndex = dotIndex + 1;
 435   
                 }
 436   
                 else
 437  1
                     _firstSentence = _commentText;
 438   
             }
 439   
 
 440   
             // We didn't find a proper first sentence separator. So we only have
 441   
             // one sentence.
 442  3
             if( _firstSentence == null )
 443   
             {
 444  0
                 _firstSentence = _commentText;
 445   
             }
 446   
         }
 447   
 
 448  3
         return _firstSentence;
 449   
     }
 450   
 
 451   
     /**
 452   
      * Set the text of the comment for this doc item.
 453   
      *
 454   
      * @param commentText  The new comment text
 455   
      */
 456  0
     public void setCommentText( String commentText )
 457   
     {
 458  0
         if( _dirty )
 459   
         {
 460  0
             parse();
 461   
         }
 462  0
         _commentText = commentText;
 463  0
         _firstSentence = null;
 464  0
         fireDocChanged();
 465   
     }
 466   
 
 467   
     /**
 468   
      * Returns true if the tag exists. Does not look in superclasses.
 469   
      *
 470   
      * @param tagName  The name of the tag to look for (without the 'at')
 471   
      * @return         true if the tag exists
 472   
      */
 473  0
     public boolean hasTag( String tagName )
 474   
     {
 475  0
         return hasTag( tagName, false );
 476   
     }
 477   
 
 478   
     /**
 479   
      * Returns true if the tag exists.
 480   
      *
 481   
      * @param tagName       The name of the tag to look for (without the 'at')
 482   
      * @param superclasses  If true, look in superclasses too.
 483   
      * @return              true if the tag exists
 484   
      */
 485  0
     public boolean hasTag( String tagName, boolean superclasses )
 486   
     {
 487  0
         return getTags( tagName, superclasses ).size() != 0;
 488   
     }
 489   
 
 490   
     /**
 491   
      * Utility method to set the value of a tag attribute. If the tag doesn't
 492   
      * exist, it is created. If the attribute doesn't exist it is created. If the
 493   
      * tag attribute exists, it is updated.
 494   
      *
 495   
      * @param tagName                The new name of the tag to update (without the
 496   
      * @param tagIndex               The index of the tag to update, in case there
 497   
      *      are several tags with the same name.
 498   
      * @param attributeName          The attribute name
 499   
      * @param attributeValue         The new attribute value
 500   
      * @return                       the updated tag
 501   
      * @exception XJavaDocException
 502   
      */
 503  3
     public XTag updateTagValue( String tagName, String attributeName, String attributeValue, int tagIndex ) throws XJavaDocException
 504   
     {
 505  3
         XTag tag = null;
 506  3
         List tags = getTags( tagName );
 507   
 
 508  3
         if( tags.size() == 0 || tags.size() <= tagIndex )
 509   
         {
 510   
             //debug("@" + tagName + " at index " + tagIndex + " doesn't exist. creating new tag");
 511   
             // There was no such tags. Create a new one.
 512  2
             String tagValue = attributeName + "=\"" + attributeValue + "\"";
 513   
 
 514  2
             tag = addTag_Impl( tagName, tagValue, -1 );
 515   
         }
 516   
         else
 517   
         {
 518   
             // Iterate to the tag at the right index
 519  1
             Iterator tagIterator = tags.iterator();
 520   
 
 521  1
             for( int i = 0; i < tagIndex; i++ )
 522   
             {
 523  0
                 tag = (XTag) tagIterator.next();
 524   
             }
 525  1
             if( tag != null )
 526   
             {
 527  0
                 tag.setAttribute( attributeName, attributeValue );
 528   
             }
 529   
         }
 530  3
         return tag;
 531   
     }
 532   
 
 533   
     /**
 534   
      * Add doc listener interested in changes.
 535   
      *
 536   
      * @param docListener  doc listener to register
 537   
      */
 538  0
     public void addDocListener( XDocListener docListener )
 539   
     {
 540  0
         _docListeners.add( docListener );
 541   
     }
 542   
 
 543   
     /**
 544   
      * remove doc listener
 545   
      *
 546   
      * @param docListener
 547   
      */
 548  0
     public void removeDocListener( XDocListener docListener )
 549   
     {
 550  0
         _docListeners.remove( docListener );
 551   
     }
 552   
 
 553   
     /**
 554   
      * Returns a String representation of this doc.
 555   
      *
 556   
      * @return   a String representation of this doc.
 557   
      */
 558  4
     public String toString()
 559   
     {
 560  4
         if( _dirty )
 561   
         {
 562  0
             parse();
 563   
         }
 564   
 
 565  4
         StringBuffer sb = new StringBuffer( "/**" ).append( NEWLINE );
 566   
 
 567  4
         if( !_commentText.trim().equals( "" ) )
 568   
         {
 569  3
             appendWhiteSpaces( sb ).append( " * " ).append( _commentText ).append( NEWLINE );
 570  3
             appendWhiteSpaces( sb ).append( " * " ).append( NEWLINE );
 571   
         }
 572   
 
 573   
 //        addSpaces(sb, _javadocToken).append(" * ").append(NEWLINE);
 574   
 
 575  4
         for( Iterator tags = getTags().iterator(); tags.hasNext();  )
 576   
         {
 577  9
             XTag tag = ( XTag ) tags.next();
 578   
 
 579  9
             appendWhiteSpaces( sb ).append( " * @" ).append( tag.getName() );
 580   
 
 581  9
             Collection attributeNames = tag.getAttributeNames();
 582   
 
 583  9
             if( attributeNames.size() == 0 )
 584   
             {
 585   
                 // no parameters, or malformed
 586  3
                 sb.append( ' ' ).append( tag.getValue() ).append( NEWLINE );
 587   
             }
 588   
             else
 589   
             {
 590  6
                 sb.append( NEWLINE );
 591  6
                 for( Iterator attrs = attributeNames.iterator(); attrs.hasNext();  )
 592   
                 {
 593  9
                     String attibuteName = ( String ) attrs.next();
 594  9
                     String attributeValue = tag.getAttributeValue( attibuteName );
 595   
 
 596  9
                     appendWhiteSpaces( sb ).append( " *    " ).append( attibuteName ).append( "=\"" ).append( attributeValue ).append( "\"" ).append( NEWLINE );
 597   
                 }
 598   
             }
 599   
         }
 600  4
         appendWhiteSpaces( sb ).append( " */" );
 601   
 
 602  4
         return sb.toString();
 603   
     }
 604   
 
 605   
     /**
 606   
      * update token
 607   
      */
 608  4
     public void updateToken()
 609   
     {
 610  4
         _javadocToken.image = toString();
 611   
     }
 612   
 
 613   
     /**
 614   
      * Removes tag. Note that XTag objects are compared by identity.
 615   
      *
 616   
      * @param tag  tag to be removed
 617   
      * @return     true if it was removed
 618   
      */
 619  0
     public boolean removeTag( XTag tag )
 620   
     {
 621  0
         boolean removed = _tags.remove( tag );
 622   
 
 623  0
         if( removed )
 624   
         {
 625   
             // purge it from tag map too
 626  0
             ensureTagMapInitialised();
 627   
 
 628  0
             Collection tags = ( Collection ) _tagMap.get( dotted( tag.getName() ) );
 629   
 
 630  0
             tags.remove( tag );
 631  0
             fireDocChanged();
 632   
         }
 633  0
         return removed;
 634   
     }
 635   
 
 636   
     /**
 637   
      * Add a tag to the doc item.
 638   
      *
 639   
      * @param tagName                  The name of the tag to add
 640   
      * @param text                     The value of the tag
 641   
      * @return                         The created XTag
 642   
      * @throws TagValidationException  if validation is activated (in XTagFactory)
 643   
      *      and tagName is not among the registered tags.
 644   
      */
 645  0
     public XTag addTag( String tagName, String text )
 646   
     {
 647  0
         if( _dirty )
 648   
         {
 649  0
             parse();
 650   
         }
 651   
 
 652  0
         XTag rtag = addTag_Impl( tagName, text, -1 );
 653   
 
 654   
         // fire doc change event
 655  0
         fireDocChanged();
 656  0
         return rtag;
 657   
     }
 658   
 
 659   
     /**
 660   
      * receive change notification from xtag
 661   
      *
 662   
      * @param event
 663   
      */
 664  0
     public void tagChanged( XTagEvent event )
 665   
     {
 666   
         // invalidate attribute value cache
 667   
         // for tag in question
 668  0
         if( event.getSource() instanceof XTag )
 669   
         {
 670   
             //XTag tag = ( XTag ) event.getSource();
 671   
 
 672   
             /*
 673   
              * if( tagAttrValueCurrent != null )
 674   
              * {
 675   
              * tagAttrValueCurrent.remove( tag.getName() );
 676   
              * }
 677   
              */
 678  0
             fireDocChanged();
 679   
         }
 680   
     }
 681   
 
 682   
     /**
 683   
      * Returns the doc in the superclass. If the super element is null, or not from
 684   
      * source, null is returned.
 685   
      *
 686   
      * @return   the superclass' doc
 687   
      */
 688  264
     private XDoc getSuperDoc()
 689   
     {
 690  264
         XProgramElement superElement = _owner.getSuperElement();
 691   
 
 692  264
         if( superElement != null )
 693   
         {
 694  10
             return superElement.getDoc();
 695   
         }
 696   
         else
 697   
         {
 698  254
             return null;
 699   
         }
 700   
     }
 701   
 
 702   
     /**
 703   
      * Returns the doc in all the superclasses. If the super element is null, or not from
 704   
      * source, an empty list is returned.
 705   
      *
 706   
      * @return   A List of XDoc
 707   
      */
 708  264
     private List getAllSuperDocs()
 709   
     {
 710  264
         List superElements = _owner.getSuperInterfaceElements();
 711   
 
 712  264
         if ( superElements!=null )
 713   
         {
 714  264
             List result = new ArrayList();
 715  264
             Iterator elements = superElements.iterator();
 716  264
             while ( elements.hasNext() )
 717   
             {
 718  80
                 XDoc doc = ( (XProgramElement) elements.next() ).getDoc();
 719  80
                 result.add(doc);
 720   
             }
 721  264
             return result;
 722   
         }
 723   
         else
 724   
         {
 725  0
             return Collections.EMPTY_LIST;
 726   
         }
 727   
     }
 728   
 
 729  703
     private final void ensureTagMapInitialised()
 730   
     {
 731  703
         if( _tagMap == null )
 732   
         {
 733  347
             _tagMap = new TreeMap();
 734   
         }
 735   
     }
 736   
 
 737   
     /**
 738   
      * Creates and adds a tag
 739   
      *
 740   
      * @param tagName                     The name of the tag (without the 'at')
 741   
      * @param text                        The raw content of the tag
 742   
      * @param lineNumber                  The feature to be added to the Tag_Impl
 743   
      *      attribute
 744   
      * @return                            An instance of XTag, created by the
 745   
      *      current XTagFactory
 746   
      * @exception TagValidationException
 747   
      */
 748  355
     private XTag addTag_Impl( String tagName, String text, int lineNumber ) throws TagValidationException
 749   
     {
 750  355
         tagName = dotted( tagName );
 751   
 
 752  355
         ensureTagMapInitialised();
 753   
 
 754  355
         Collection tags = ( Collection ) _tagMap.get( tagName );
 755   
 
 756  355
         if( tags == null )
 757   
         {
 758  306
             tags = new LinkedList();
 759  306
             _tagMap.put( tagName, tags );
 760   
         }
 761   
 
 762  355
         if( _tags == null )
 763   
         {
 764  213
             _tags = new LinkedList();
 765   
         }
 766   
 
 767  355
         XTag tag = _tagFactory.createTag( tagName, text, this, lineNumber );
 768   
 
 769   
         // We want to be notified when this tag changes
 770  355
         tag.addTagListener( this );
 771   
 
 772   
         // Add to the Collection in the map
 773  355
         tags.add( tag );
 774   
 
 775   
         // Add to the global tag list
 776  355
         _tags.add( tag );
 777   
 
 778  355
         return tag;
 779   
     }
 780   
 
 781   
     /**
 782   
      * fire docChange event
 783   
      */
 784  0
     private void fireDocChanged()
 785   
     {
 786  0
         for( Iterator i = _docListeners.iterator(); i.hasNext();  )
 787   
         {
 788  0
             XDocListener docListener = ( XDocListener ) i.next();
 789   
 
 790  0
             docListener.docChanged( new XDocEvent( this ) );
 791   
         }
 792   
 
 793   
         // also set containing class to dirty
 794  0
         if( _owner != null )
 795   
         {
 796  0
             XClass clazz = _owner instanceof XClass ? ( XClass ) _owner : _owner.getContainingClass();
 797   
 
 798  0
             clazz.setDirty();
 799   
         }
 800   
     }
 801   
 
 802   
     /**
 803   
      * Add some white space to the string being built up in toString().
 804   
      *
 805   
      * @param sb  StringBuffer that the text is being built in
 806   
      * @return    the StringBuffer
 807   
      */
 808  28
     private StringBuffer appendWhiteSpaces( StringBuffer sb )
 809   
     {
 810  28
         return sb.append( "   " );
 811   
         /*
 812   
          * Token tk = _programElementToken;
 813   
          * while (tk.previous != null && isTabOrSpace(tk.previous)) {
 814   
          * tk = tk.previous;
 815   
          * }
 816   
          * while (tk.next != null && tk != _programElementToken) {
 817   
          * sb.append(tk.image);
 818   
          * tk = tk.next;
 819   
          * }
 820   
          * return sb;
 821   
          */
 822   
     }
 823   
 
 824   
     /**
 825   
      * Parse token into comments, tags and tag attributes. We remove excess spaces.
 826   
      *
 827   
      * @exception TagValidationException
 828   
      */
 829  349
     private void parse() throws TagValidationException
 830   
     {
 831  349
         if( _dirty )
 832   
         {
 833   
             //debug("parse");
 834   
             // We must read line by line, since a @tags can only begin as the first token of a line.
 835  349
             JavaDocReader javaDocReader = new JavaDocReader( new StringReader( _javadocToken.image ) );
 836  349
             BufferedReader in = new BufferedReader( javaDocReader );
 837  349
             StringBuffer docElement = new StringBuffer();
 838  349
             String tagName = null;
 839  349
             String line = null;
 840   
 
 841  349
             int tagStartLine = -1;
 842   
 
 843  349
             try
 844   
             {
 845  ?
                 while( ( line = in.readLine() ) != null )
 846   
                 {
 847  1201
                     if( line.startsWith( "@" ) )
 848   
                     {
 849   
                         // remember the line number where the tag starts.
 850  353
                         tagStartLine = _javadocToken.beginLine + javaDocReader.getLineOffset();
 851   
 
 852   
                         // It's a new tag
 853  353
                         if( tagName == null )
 854   
                         {
 855   
                             // what we've been reading so far has been a general comment.
 856  212
                             _commentText = tokenizeAndTrim( docElement.toString() );
 857   
                         }
 858   
                         else
 859   
                         {
 860   
                             // Add the previous tag
 861  141
                             addTag_Impl( tagName, tokenizeAndTrim( docElement.toString() ), tagStartLine );
 862   
                         }
 863  353
                         docElement = new StringBuffer();
 864   
 
 865  353
                         StringTokenizer st = new StringTokenizer( line );
 866   
 
 867  353
                         tagName = st.nextToken().substring( 1 );
 868  353
                         docElement.append( line.substring( tagName.length() + 1 ).trim() ).append( ' ' );
 869   
                     }
 870   
                     else
 871   
                     {
 872   
                         // It's the continuation of a tag or a comment, or start of comment;
 873  848
                         if( docElement == null )
 874   
                         {
 875   
                             // It was the start of the comment
 876  0
                             docElement = new StringBuffer();
 877   
                         }
 878  848
                         docElement.append( line.trim() ).append( ' ' );
 879   
                     }
 880   
                 }
 881  349
                 if( tagName == null )
 882   
                 {
 883   
                     // what we've been reading so far has been a general comment.
 884  137
                     _commentText = docElement.toString().trim();
 885   
                 }
 886   
                 else
 887   
                 {
 888   
                     // Add the previous tag
 889  212
                     addTag_Impl( tagName, tokenizeAndTrim( docElement.toString() ), tagStartLine );
 890   
                 }
 891   
             }
 892   
             catch( IOException e )
 893   
             {
 894  0
                 e.printStackTrace();
 895   
             }
 896   
             catch( StringIndexOutOfBoundsException e )
 897   
             {
 898  0
                 e.printStackTrace();
 899   
             }
 900  349
             _dirty = false;
 901   
         }
 902   
     }
 903   
 
 904   
 }
 905