Clover coverage report - XJavaDoc - 1.1
Coverage timestamp: Sun Oct 3 2004 19:56:54 BST
file stats: LOC: 775   Methods: 35
NCLOC: 492   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
SourceClass.java 47.2% 62.4% 71.4% 58.6%
coverage coverage
 1   
 /*
 2   
  * Copyright (c) 2001-2003 The XDoclet team
 3   
  * All rights reserved.
 4   
  */
 5   
 package xjavadoc;
 6   
 
 7   
 import xjavadoc.filesystem.AbstractFile;
 8   
 import xjavadoc.filesystem.XJavadocFile;
 9   
 import xjavadoc.filesystem.ReaderFile;
 10   
 
 11   
 import java.util.*;
 12   
 import java.io.*;
 13   
 
 14   
 /**
 15   
  * This class represents a class for which the source code is available
 16   
  *XJavaDocFil
 17   
  * @author    Aslak Hellesøy
 18   
  * @created   3. januar 2002
 19   
  */
 20   
 public final class SourceClass extends AbstractClass
 21   
 {
 22   
     public static int  instanceCount = 0;
 23   
 
 24   
     private final Map  _qualifiedClasses = new HashMap();
 25   
 
 26   
     private final boolean _isExtraClass;
 27   
 
 28   
     private final List _tagsForValidation = new ArrayList();
 29   
 
 30   
     /**
 31   
      * The root node of the AST
 32   
      */
 33   
     private SimpleNode _compilationUnit;
 34   
 
 35   
     private Reader     _in = null;
 36   
 
 37   
     /**
 38   
      * Keep a ref to the file in case of warning reporting
 39   
      */
 40   
     private AbstractFile _sourceFile;
 41   
 
 42   
     //private JavaParser _parser;
 43   
 
 44   
     /**
 45   
      * doe we nees saving?
 46   
      */
 47   
     private boolean    _dirty;
 48   
 
 49   
     /**
 50   
      * Constructor to use for inner classes.
 51   
      *
 52   
      * @param containingClass  The containing class;
 53   
      */
 54  252
     public SourceClass( SourceClass containingClass, XTagFactory tagFactory )
 55   
     {
 56  252
         super( containingClass, tagFactory );
 57  252
         setContainingPackage( containingClass.getContainingPackage().getName() );
 58  252
         _isExtraClass = false;
 59   
     }
 60   
 
 61   
     /**
 62   
      * Constructor to use for "extra" classes, that is, secondary classes that
 63   
      * figure in the same source.
 64   
      *
 65   
      * @param mainClass  The containing class. Or rather the "main" class in the
 66   
      *      source.
 67   
      * @param dummy
 68   
      */
 69  48
     public SourceClass( SourceClass mainClass, int dummy, XTagFactory tagFactory )
 70   
     {
 71  48
         super( mainClass.getXJavaDoc(), tagFactory );
 72  48
         setContainingPackage( mainClass.getContainingPackage().getName() );
 73  48
         _isExtraClass = true;
 74  48
         _sourceFile = mainClass.getFile();
 75   
     }
 76   
 
 77   
     /**
 78   
      * Constructor to use for outer classes
 79   
      *
 80   
      * @param sourceFile  The file containing the source
 81   
      */
 82  0
     public SourceClass( XJavaDoc xJavaDoc, File sourceFile, XTagFactory tagFactory )
 83   
     {
 84  0
         this( xJavaDoc, new XJavadocFile( sourceFile ), false, tagFactory, null );
 85   
     }
 86   
 
 87   
     /**
 88   
      * Constructor to use for outer classes
 89   
      *
 90   
      * @param sourceFile  The file containing the source
 91   
      */
 92  0
     public SourceClass( XJavaDoc xJavaDoc, Reader sourceFile, XTagFactory tagFactory )
 93   
     {
 94  0
         this( xJavaDoc, new ReaderFile( sourceFile ), false, tagFactory, null);
 95   
     }
 96   
 
 97   
     /**
 98   
      * @param sourceFile
 99   
      * @param useNodeParser
 100   
      */
 101  12
     public SourceClass( XJavaDoc xJavaDoc, File sourceFile, boolean useNodeParser, XTagFactory tagFactory )
 102   
     {
 103  12
         this( xJavaDoc, new XJavadocFile( sourceFile ), useNodeParser, tagFactory ,null );
 104   
     }
 105   
 
 106   
     /**
 107   
      * Constructor to use for outer classes
 108   
      *
 109   
      * @param sourceFile     The file containing the source
 110   
      * @param useNodeParser
 111   
      */
 112  684
     public SourceClass( XJavaDoc xJavaDoc, AbstractFile sourceFile, boolean useNodeParser, XTagFactory tagFactory ,String encoding)
 113   
     {
 114  684
         super( xJavaDoc, tagFactory );
 115  684
         if( sourceFile == null )
 116   
         {
 117  0
             throw new IllegalArgumentException( "sourceFile can't be null for outer classes!" );
 118   
         }
 119  684
         _sourceFile = sourceFile;
 120   
 
 121  684
         try
 122   
         {
 123  684
             _in = sourceFile.getReader(encoding);
 124  684
             parse( useNodeParser );
 125   
         }
 126   
         catch( IOException e )
 127   
         {
 128   
             // That's tough. Shouldn't happen
 129  0
             if(encoding==null)
 130   
             {
 131  0
             throw new IllegalStateException( "Couldn't find " + sourceFile );
 132   
         }
 133   
             else
 134   
             {
 135  0
                 throw new IllegalStateException( "Invalid Encoding '"+encoding+"' or couldn't find '" + sourceFile +"'");
 136   
             }
 137   
         }
 138   
 
 139  684
         instanceCount++;
 140  684
         _dirty = false;
 141  684
         _isExtraClass = false;
 142   
     }
 143   
 
 144   
     /**
 145   
      * Describe what the method does
 146   
      *
 147   
      * @param qualifiedName  Describe what the parameter does
 148   
      * @return               Describe the return value
 149   
      */
 150  8
     public static String getFileName( String qualifiedName )
 151   
     {
 152  8
         return qualifiedName.replace( '.', File.separatorChar ) + ".java";
 153   
     }
 154   
 
 155  1386
     public boolean isExtraClass()
 156   
     {
 157  1386
         return _isExtraClass;
 158   
     }
 159   
 
 160   
     /**
 161   
      * Returns "1", "2", etc., depending on how many inner classes we have.
 162   
      *
 163   
      * @return String containing number of next anonymous inner class
 164   
      */
 165  40
     public String getNextAnonymousClassName()
 166   
     {
 167  40
         return String.valueOf( getInnerClasses().size() + 1 );
 168   
     }
 169   
 
 170   
     /**
 171   
      * Gets the OuterClass attribute of the SourceClass object
 172   
      *
 173   
      * @return   The OuterClass value
 174   
      */
 175  4
     private boolean isOuterClass()
 176   
     {
 177  4
         return _sourceFile != null;
 178   
     }
 179   
 
 180   
     /**
 181   
      * Gets the Writeable attribute of the SourceClass object
 182   
      *
 183   
      * @return   The Writeable value
 184   
      */
 185  16
     public boolean isWriteable()
 186   
     {
 187  16
         return _compilationUnit != null;
 188   
     }
 189   
 
 190  4
     public SimpleNode getCompilationUnit()
 191   
     {
 192  4
         return _compilationUnit;
 193   
     }
 194   
 
 195   
     /**
 196   
      * Returns a reader for the source code.
 197   
      *
 198   
      * @return   a reader for the source code.
 199   
      */
 200  684
     public Reader getReader()
 201   
     {
 202  684
         return _in;
 203   
     }
 204   
 
 205  48
     public AbstractFile getFile()
 206   
     {
 207  48
         return _sourceFile;
 208   
     }
 209   
 
 210  0
     public boolean isPrimitive()
 211   
     {
 212  0
         return false;
 213   
     }
 214   
 
 215   
     /**
 216   
      * say this class is dirty and needs saving propagate to outer class ( if any )
 217   
      */
 218  0
     public void setDirty()
 219   
     {
 220  0
         if( isInner() )
 221   
         {
 222  0
             getContainingClass().setDirty();
 223   
         }
 224   
         else
 225   
         {
 226  0
             _dirty = true;
 227   
         }
 228   
     }
 229   
     /**
 230   
      * Called by JavaParser at the end of the parsing
 231   
      *
 232   
      * @param compilationUnit  The new CompilationUnit value
 233   
      */
 234  12
     public void setCompilationUnit( SimpleNode compilationUnit )
 235   
     {
 236  12
         _compilationUnit = compilationUnit;
 237   
     }
 238   
 
 239   
     /**
 240   
      * Called by XJavaDoc after the entire source is parsed, but only if validation
 241   
      * is on.
 242   
      *
 243   
      * @throws TagValidationException
 244   
      */
 245  0
     public void validateTags() throws TagValidationException
 246   
     {
 247   
         // Validate the tags on the class level and on our members.
 248  0
         for( Iterator i = _tagsForValidation.iterator(); i.hasNext();  )
 249   
         {
 250  0
             XTag tag = ( XTag ) i.next();
 251   
 
 252  0
             tag.validate();
 253   
         }
 254   
 
 255   
         // then validate tags in all our inner classes.
 256  0
         for( Iterator i = getInnerClasses().iterator(); i.hasNext();  )
 257   
         {
 258  0
             SourceClass inner = ( SourceClass ) i.next();
 259   
 
 260  0
             inner.validateTags();
 261   
         }
 262   
     }
 263   
 
 264  710
     public void addTagForValidation( DefaultXTag tag )
 265   
     {
 266  710
         _tagsForValidation.add( tag );
 267   
     }
 268   
 
 269  0
     public boolean saveNeeded()
 270   
     {
 271  0
         return isWriteable() && _dirty;
 272   
     }
 273   
 
 274   
     /**
 275   
      * Describe what the method does
 276   
      *
 277   
      * @return   Describe the return value
 278   
      */
 279  4
     public long lastModified()
 280   
     {
 281  4
         if( isOuterClass() )
 282   
         {
 283  4
             return _sourceFile.lastModified();
 284   
         }
 285   
         else
 286   
         {
 287  0
             return getContainingClass().lastModified();
 288   
         }
 289   
     }
 290   
 
 291   
     /**
 292   
      * Prints this class to a stream
 293   
      *
 294   
      * @param out  Describe what the parameter does
 295   
      */
 296  8
     public void print( Writer out )
 297   
     {
 298  8
         updateDoc();
 299  8
         if( !isWriteable() )
 300   
         {
 301   
             // parsed with simple parser
 302  0
             throw new UnsupportedOperationException( "Can't save classes that are parsed with simpleparser" );
 303   
         }
 304  8
         NodePrinter.print( _compilationUnit, out );
 305   
     }
 306   
 
 307   
     /**
 308   
      * Saves the class at root dir rootDir. The actual java file is derived from
 309   
      * tha package name. If no root dir is specified, save where it was loaded from
 310   
      *
 311   
      * @param rootDir       the root directory.
 312   
      * @return              the relative fileName to which the file was saved.
 313   
      * @throws IOException  if the file couldn't be saved
 314   
      */
 315  8
     public String save( File rootDir ) throws IOException
 316   
     {
 317  8
         if( !isWriteable() )
 318   
         {
 319  0
             throw new UnsupportedOperationException( "Can't save classes that aren't parsed in AST mode (do getXJavaDoc().setUseNodeParser(true) before parsing starts!)" );
 320   
         }
 321  8
         if( getContainingClass() != null )
 322   
         {
 323   
             // inner class. can't save these.
 324  0
             throw new UnsupportedOperationException( "Can't save inner classes" );
 325   
         }
 326  8
         else if( rootDir != null )
 327   
         {
 328  8
             String fileName = getFileName( getQualifiedName() );
 329  8
             File javaFile = new File( rootDir, fileName );
 330   
 
 331  8
             javaFile.getParentFile().mkdirs();
 332  8
             FileWriter fwtr = new FileWriter( javaFile );
 333  8
             print( fwtr );
 334  8
             fwtr.flush();
 335  8
             fwtr.close(); 
 336  8
             return fileName;
 337   
         }
 338   
         else
 339   
         {
 340   
             // no root dir specified, save in place
 341  0
             Writer outputStream = _sourceFile.getWriter();
 342   
 
 343  0
             print( new PrintWriter( outputStream ) );
 344  0
             outputStream.flush();
 345  0
             outputStream.close();
 346  0
             return _sourceFile.toString();
 347   
         }
 348   
     }
 349   
 
 350   
     /**
 351   
      * Returns fully qualified name of a class. 1: check for "." 2: if "." it's
 352   
      * already qualified 3: if no ".", must try with all imported packages or
 353   
      * classes
 354   
      *
 355   
      * @param unqualifiedClassName  Describe what the parameter does
 356   
      * @return                      Describe the return value
 357   
      */
 358  5656
     public XClass qualify( final String unqualifiedClassName )
 359   
     {
 360  5656
         XClass result = null;
 361   
 
 362  5656
         result = ( XClass ) _qualifiedClasses.get( unqualifiedClassName );
 363  5656
         if( result == null )
 364   
         {
 365   
 
 366  3414
             if( getContainingClass() == null )
 367   
             {
 368   
                 // If there are dots, consider it to be qualified or a reference to an inner class in one
 369   
                 // of the imported classes.
 370  3116
                 if( unqualifiedClassName.indexOf( '.' ) != -1 )
 371   
                 {
 372  1944
                     result = unqualifiedNameInImportedClassesInnerClasses( unqualifiedClassName );
 373  1944
                     if( result == null )
 374   
                     {
 375   
                         // It wasn't a ref to an imported inner class. Consider it already qualified
 376  1938
                         result = getXJavaDoc().getXClass( unqualifiedClassName );
 377   
                     }
 378   
                 }
 379   
                 else
 380   
                 {
 381   
                     // There are no dots in the class name. It's a primitive or unqualified.
 382  1172
                     Primitive primitive;
 383   
 
 384  ?
                     if( ( primitive = XJavaDoc.getPrimitive( unqualifiedClassName ) ) != null )
 385   
                     {
 386  124
                         result = primitive;
 387   
                     }
 388   
                     else
 389   
                     {
 390  1048
                         String qualifiedName;
 391   
 
 392  ?
                         if( ( qualifiedName = unqualifiedNameInTheSameClassAsAnInnerClass( unqualifiedClassName ) ) != null )
 393   
                         {
 394  460
                             result = getXJavaDoc().getXClass( qualifiedName );
 395   
                         }
 396  ?
                         else if( ( qualifiedName = unqualifiedNameInInnerClasses( unqualifiedClassName ) ) != null )
 397   
                         {
 398  46
                             result = getXJavaDoc().getXClass( qualifiedName );
 399   
                         }
 400  ?
                         else if( ( qualifiedName = unqualifiedNameInJavaDotLang( unqualifiedClassName ) ) != null )
 401   
                         {
 402  208
                             result = getXJavaDoc().getXClass( qualifiedName );
 403   
                         }
 404  ?
                         else if( ( qualifiedName = unqualifiedNameInImportedClasses( unqualifiedClassName ) ) != null )
 405   
                         {
 406  212
                             result = getXJavaDoc().getXClass( qualifiedName );
 407   
                         }
 408  ?
                         else if( ( qualifiedName = unqualifiedNameInImportedPackages( unqualifiedClassName ) ) != null )
 409   
                         {
 410  122
                             result = getXJavaDoc().getXClass( qualifiedName );
 411   
                         }
 412  0
                         else if( ( qualifiedName = unqualifiedNameInTheSamePackage( unqualifiedClassName ) ) != null )
 413   
                         {
 414  0
                             result = getXJavaDoc().getXClass( qualifiedName );
 415   
                         }
 416  0
                         else if( ( qualifiedName = unqualifiedNameInInnerClassesOfSuperClass( unqualifiedClassName ) ) != null )
 417   
                         {
 418  0
                             result = getXJavaDoc().getXClass( qualifiedName );
 419   
                         }
 420  0
                         else if( ( qualifiedName = unqualifiedNameInInnerInterface( unqualifiedClassName ) ) != null )
 421   
                         {
 422  0
                             result = getXJavaDoc().getXClass( qualifiedName );
 423   
                         }
 424   
                         else
 425   
                         {
 426  0
                             String unknownClassName;
 427   
 
 428  0
                             if( getContainingPackage().getName().equals( "" ) )
 429   
                             {
 430  0
                                 unknownClassName = unqualifiedClassName;
 431   
                             }
 432   
                             else
 433   
                             {
 434  0
                                 unknownClassName = getContainingPackage().getName() + "." + unqualifiedClassName;
 435   
                             }
 436   
 
 437  0
                             UnknownClass unknownClass = new UnknownClass( getXJavaDoc(), unknownClassName );
 438   
 
 439   
                             /*
 440   
                              * We couldn't qualify the class. If there are no package import statements,
 441   
                              * we'll assume the class belongs to the same package as ourself.
 442   
                              */
 443  0
                             if( !hasImportedPackages() )
 444   
                             {
 445   
                                 // No import foo.bar.* statements. Just add an informative message that we guessed
 446  0
                                 getXJavaDoc().logMessage( this, unknownClass, unqualifiedClassName, XJavaDoc.NO_IMPORTED_PACKAGES );
 447   
                             }
 448   
                             else
 449   
                             {
 450   
 
 451   
                                 // We can't decide. Add a warning that will be displayed in the end.
 452  0
                                 getXJavaDoc().logMessage( this, unknownClass, unqualifiedClassName, XJavaDoc.ONE_OR_MORE_IMPORTED_PACKAGES );
 453   
                             }
 454  0
                             result = unknownClass;
 455   
                         }
 456   
                     }
 457   
                 }
 458   
             }
 459   
             else
 460   
             {
 461  298
                 result = getContainingAbstractClass().qualify( unqualifiedClassName );
 462   
             }
 463  3414
             _qualifiedClasses.put( unqualifiedClassName, result );
 464   
         }
 465   
 
 466  5656
         return result;
 467   
     }
 468   
 
 469  0
     public void reset()
 470   
     {
 471  0
         super.reset();
 472   
 
 473  0
         _compilationUnit = null;
 474  0
         _in = null;
 475  0
         _sourceFile = null;
 476  0
         _qualifiedClasses.clear();
 477   
     }
 478   
 
 479  334
     private final String unqualifiedNameInImportedClasses( final String unqualifiedClassName )
 480   
     {
 481  334
         if( !hasImportedClasses() )
 482   
         {
 483  20
             return null;
 484   
         }
 485   
 
 486  314
         final String suffix = "." + unqualifiedClassName;
 487  314
         String candidate = null;
 488   
 
 489  314
         for( Iterator i = getImportedClasses().iterator(); i.hasNext();  )
 490   
         {
 491  806
             XClass clazz = ( XClass ) i.next();
 492  806
             String qualifiedClassName = clazz.getQualifiedName();
 493   
 
 494  806
             if( qualifiedClassName.endsWith( suffix ) )
 495   
             {
 496   
                 // perform sanity check for ambiguous imports
 497  212
                 if( candidate != null && !candidate.equals( qualifiedClassName ) )
 498   
                 {
 499   
                     // ambiguous class import
 500  0
                     throw new IllegalStateException( "In class " + getQualifiedName() + ": Ambiguous class:" + unqualifiedClassName + ". Is it " + candidate + " or " + qualifiedClassName + "?" );
 501   
                 }
 502   
                 else
 503   
                 {
 504  212
                     candidate = qualifiedClassName;
 505   
                 }
 506   
             }
 507   
         }
 508  314
         return candidate;
 509   
     }
 510   
 
 511  1944
     private final XClass unqualifiedNameInImportedClassesInnerClasses( final String unqualifiedClassName )
 512   
     {
 513  1944
         if( !hasImportedClasses() )
 514   
         {
 515  110
             return null;
 516   
         }
 517   
 
 518  1834
         XClass candidate = null;
 519   
 
 520  1834
         for( Iterator i = getImportedClasses().iterator(); i.hasNext();  )
 521   
         {
 522  5210
             XClass clazz = ( XClass ) i.next();
 523   
 
 524   
             // See if it's among the inner classes.
 525  5210
             for( Iterator inners = clazz.getInnerClasses().iterator(); inners.hasNext();  )
 526   
             {
 527  18
                 XClass inner = ( XClass ) inners.next();
 528  18
                 boolean isAccessible = inner.isPublic();
 529   
 
 530  18
                 if( inner.getName().equals( unqualifiedClassName ) && isAccessible )
 531   
                 {
 532  6
                     if( candidate != null )
 533   
                     {
 534   
                         // ambiguous class import
 535  0
                         throw new IllegalStateException( "In class " + getQualifiedName() + ": Ambiguous class:" + unqualifiedClassName + ". Is it " + candidate.getQualifiedName() + " or " + inner.getQualifiedName() + "?" );
 536   
                     }
 537   
                     else
 538   
                     {
 539  6
                         candidate = inner;
 540   
                     }
 541   
                 }
 542   
             }
 543   
         }
 544  1834
         return candidate;
 545   
     }
 546   
 
 547   
     /**
 548   
      * Describe what the method does
 549   
      *
 550   
      * @param unqualifiedClassName  Describe what the parameter does
 551   
      * @return                      Describe the return value
 552   
      */
 553  588
     private final String unqualifiedNameInInnerClasses( final String unqualifiedClassName )
 554   
     {
 555  588
         if( !hasInnerClasses() )
 556   
         {
 557  422
             return null;
 558   
         }
 559   
 
 560  166
         final String innerClassName = getQualifiedName() + '.' + unqualifiedClassName;
 561   
 
 562  166
         String candidate = null;
 563   
 
 564  166
         for( Iterator i = getInnerClasses().iterator(); i.hasNext();  )
 565   
         {
 566  248
             XClass innerClass = ( XClass ) i.next();
 567  248
             String qualifiedClassName = innerClass.getQualifiedName();
 568   
 
 569  248
             if( innerClassName.equals( qualifiedClassName ) )
 570   
             {
 571  46
                 candidate = qualifiedClassName;
 572  46
                 break;
 573   
             }
 574   
         }
 575  166
         return candidate;
 576   
     }
 577   
 
 578   
     /**
 579   
      * Resolves Inner interfaces that exist in current class.
 580   
     *
 581   
     * This catches inner classes as well because isInterface()
 582   
     * does not indicate if it's an interface.
 583   
      *
 584   
      * @param unqualifiedClassName  Name of the class to resolve
 585   
      * @return                      The qualified name of the inner class.
 586   
      */
 587  0
     private final String unqualifiedNameInInnerInterface( final String unqualifiedClassName )
 588   
     {
 589  0
         String qualifiedClassName = getQualifiedName() + '$' + unqualifiedClassName;
 590  0
         if (getXJavaDoc().classExists(qualifiedClassName)) {
 591   
 //            // The isInterface() method is not implemented for source classes.
 592   
 //            if (XJavaDoc.getInstance().getXClass(qualifiedClassName).isInterface()) {
 593   
 //                return getQualifiedName() + '.' + unqualifiedClassName;
 594   
 //            }
 595  0
             return getQualifiedName() + '.' + unqualifiedClassName;
 596   
         }
 597  0
         return null;
 598   
     }
 599   
 
 600   
     /**
 601   
      * Resolves Inner classes that exist in the super class hierarchy.
 602   
      *
 603   
      * @param unqualifiedClassName  Name of the class to resolve
 604   
      * @return                      The qualified name of the inner class.
 605   
      */
 606  0
     private final String unqualifiedNameInInnerClassesOfSuperClass( final String unqualifiedClassName )
 607   
     {
 608  0
         XClass clazz = getXJavaDoc().getXClass(getQualifiedName());
 609  0
         XClass superClazz = clazz.getSuperclass();
 610  0
         while (superClazz != null && ! superClazz.getQualifiedName().equals("java.lang.Object")) {
 611  0
             String innerClassName = superClazz.getQualifiedName() + '.' + unqualifiedClassName;
 612  0
             for( Iterator i = superClazz.getInnerClasses().iterator(); i.hasNext();  )
 613   
             {
 614  0
                 XClass innerClass = ( XClass ) i.next();
 615  0
                 String qualifiedClassName = innerClass.getQualifiedName();
 616  0
                 if( innerClassName.equals( qualifiedClassName ) )
 617   
                 {
 618  0
                     return qualifiedClassName;
 619   
                 }
 620   
             }
 621  0
             superClazz = superClazz.getSuperclass();
 622   
         }
 623  0
         return null;
 624   
     }
 625   
 
 626   
     /**
 627   
      * Describe what the method does
 628   
      *
 629   
      * @param unqualifiedClassName  Describe what the parameter does
 630   
      * @return                      Describe the return value
 631   
      */
 632  122
     private final String unqualifiedNameInImportedPackages( final String unqualifiedClassName )
 633   
     {
 634  122
         if( !hasImportedPackages() )
 635   
         {
 636  0
             return null;
 637   
         }
 638   
 
 639  122
         final String suffix = "." + unqualifiedClassName;
 640  122
         String candidate = null;
 641   
 
 642  122
         for( Iterator i = getImportedPackages().iterator(); i.hasNext();  )
 643   
         {
 644  182
             String importedPackageName = ( ( XPackage ) i.next() ).getName();
 645  182
             String qualifiedClassName = importedPackageName + suffix;
 646   
 
 647  182
             if( getXJavaDoc().classExists( qualifiedClassName ) )
 648   
             {
 649  122
                 if( candidate != null && !candidate.equals( qualifiedClassName ) )
 650   
                 {
 651   
                     // ambiguous class import
 652  0
                     throw new IllegalStateException( "In class " + getQualifiedName() + ": Ambiguous class:" + unqualifiedClassName + ". Is it " + candidate + " or " + qualifiedClassName + "?" );
 653   
                 }
 654   
                 else
 655   
                 {
 656  122
                     candidate = qualifiedClassName;
 657   
                 }
 658   
             }
 659   
         }
 660  122
         return candidate;
 661   
     }
 662   
 
 663   
     /**
 664   
      * Returns the fully qualified class name if it's found in java.lang, otherwise
 665   
      * null.
 666   
      *
 667   
      * @param unqualifiedClassName
 668   
      * @return fully qualified class name, or null
 669   
      */
 670  542
     private final String unqualifiedNameInJavaDotLang( final String unqualifiedClassName )
 671   
     {
 672  542
         String qualifiedClassName = "java.lang." + unqualifiedClassName;
 673   
 
 674  542
         if( getXJavaDoc().classExists( qualifiedClassName ) )
 675   
         {
 676  208
             return qualifiedClassName;
 677   
         }
 678   
         else
 679   
         {
 680  334
             return null;
 681   
         }
 682   
     }
 683   
 
 684   
     /**
 685   
      * Describe what the method does
 686   
      *
 687   
      * @param unqualifiedClassName  Describe what the parameter does
 688   
      * @return                      Describe the return value
 689   
      */
 690  0
     private final String unqualifiedNameInTheSamePackage( final String unqualifiedClassName )
 691   
     {
 692  0
         String qualifiedClassName;
 693   
 
 694  0
         if( getContainingPackage().getName().equals( "" ) )
 695   
         {
 696  0
             qualifiedClassName = unqualifiedClassName;
 697   
         }
 698   
         else
 699   
         {
 700  0
             qualifiedClassName = getContainingPackage().getName() + '.' + unqualifiedClassName;
 701   
         }
 702   
 
 703  0
         if( getXJavaDoc().classExists( qualifiedClassName ) )
 704   
         {
 705  0
             return qualifiedClassName;
 706   
         }
 707   
         else
 708   
         {
 709  0
             return null;
 710   
         }
 711   
 
 712   
     }
 713   
 
 714  1048
     private final String unqualifiedNameInTheSameClassAsAnInnerClass( final String unqualifiedClassName )
 715   
     {
 716   
         //containing class=com.p.A, inner-reference=B ->com.p.A.B
 717  1048
         String qualifiedClassName = getQualifiedName() + '.' + unqualifiedClassName;
 718   
 
 719  1048
         if( getXJavaDoc().classExists( qualifiedClassName ) )
 720  0
             return qualifiedClassName;
 721   
 
 722   
         //containing class=com.p.A, inner-reference=A.B ->com.p.A.B
 723  1048
         if( getContainingPackage().getName().equals( "" ) )
 724   
         {
 725  196
             qualifiedClassName = unqualifiedClassName;
 726   
         }
 727   
         else
 728   
         {
 729  852
             qualifiedClassName = getContainingPackage().getName() + '.' + unqualifiedClassName;
 730   
         }
 731   
 
 732  1048
         if( getXJavaDoc().classExists( qualifiedClassName ) )
 733  460
             return qualifiedClassName;
 734   
 
 735  588
         return null;
 736   
     }
 737   
 
 738   
     /**
 739   
      * Describe what the method does
 740   
      *
 741   
      * @param useNodeParser  Describe what the parameter does
 742   
      */
 743  684
     private void parse( boolean useNodeParser )
 744   
     {
 745  684
         try
 746   
         {
 747  684
             if( useNodeParser )
 748   
             {
 749   
                 // We need a pool of parsers, because parsing one file
 750   
                 // might kick away the parsing of another etc.
 751   
 //                _nodeParser.populate( this );
 752  12
                 new NodeParser( getXJavaDoc(), getTagFactory() ).populate( this );
 753   
             }
 754   
             else
 755   
             {
 756   
 //                _simpleParser.populate( this );
 757  672
                 new SimpleParser( getXJavaDoc(), getTagFactory() ).populate( this );
 758   
             }
 759   
         }
 760   
         catch( ParseException e )
 761   
         {
 762   
             // Source code is bad. Not according to grammar. User's fault.
 763  0
             String cls = _sourceFile != null ? _sourceFile.toString() : getQualifiedName();
 764   
 
 765  0
             System.err.println( "Error parsing " + cls + ':' + e.getMessage() );
 766   
         }
 767   
         catch( TokenMgrError e )
 768   
         {
 769  0
             String cls = _sourceFile != null ? _sourceFile.toString() : getQualifiedName();
 770   
 
 771  0
             System.err.println( "Error parsing " + cls + ':' + e.getMessage() );
 772   
         }
 773   
     }
 774   
 }
 775