/* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This file is part of the debugger and core tools for the AspectJ(tm)
* programming language; see http://aspectj.org
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is AspectJ.
*
* The Initial Developer of the Original Code is Xerox Corporation. Portions
* created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
* All Rights Reserved.
*/
package org.aspectj.tools.ajdoc;
import org.aspectj.ajdoc.AspectDoc;
import org.aspectj.ajdoc.PackageDoc;
import org.aspectj.compiler.base.ast.Type;
import org.aspectj.compiler.base.ast.TypeDec;
import org.aspectj.compiler.crosscuts.AspectJCompiler;
import com.sun.javadoc.ClassDoc;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Represents a package in the aspectj-world.
* A package is a passive container of classes given to it.
* It does not enforce visibility rules. However, you can
* purge packages without classes from the static list of packages.
* @author Jeff Palm
*/
public class PackageDocImpl
extends DocImpl
implements org.aspectj.ajdoc.PackageDoc {
public final static String UNNAMED_PACKAGE = ""; //unnamed-package";
private static AjdocCompiler ajdoc = Ajdoc.instance();
private static AspectJCompiler ajc = ajdoc;
public AspectJCompiler ajc() { return ajc; }
private Set allClasses = new HashSet();
private Comment comment;
private String name;
/**
* Only want to create these within the static access.
*
* @param name name of the new package.
*/
private PackageDocImpl(String name) {
this.name = name;
findDocumentation();
}
/**
* Adds a class to this package.
*
* @param classDoc The new class.
*/
public void addClass(ClassDoc classDoc) {
allClasses.add(classDoc);
}
/**
* Attempts to find a class with name className
* in this package.
*
* @param className name of the class to find.
*/
public ClassDoc findClass(String className) {
Type type = ajc.getTypeManager().
findType(name(), className);
if (type != null) {
return ClassDocImpl.getInstance(type.getTypeDec());
}
for (Iterator i = allClasses.iterator(); i.hasNext();) {
ClassDoc cd = (ClassDoc)i.next();
if (className.equals(cd.name())) {
return cd; //todo wes was null?
}
}
return null;
}
/**
* Returns all the classes in this package.
*
* @return an array of ClassDoc representing all
* the classes in this package.
*/
public ClassDoc[] allClasses() {
return (ClassDoc[])allClasses.toArray(new ClassDoc[allClasses.size()]);
}
/**
* Returns all the aspects in this package.
*
* @return an array of AspectDoc representing all
* the aspects in this package.
*/
public AspectDoc[] aspects() {
List list = new ArrayList();
for (Iterator i = allClasses.iterator(); i.hasNext();) {
org.aspectj.ajdoc.ClassDoc doc = (org.aspectj.ajdoc.ClassDoc)i.next();
if (doc.isAspect()) list.add(doc);
}
return (AspectDoc[])list.toArray
(new AspectDoc[list.size()]);
}
/**
* Returns all the ordinary classes in this package.
*
* @return an array of ClassDoc representing all
* the ordinary classes in this package.
*/
public ClassDoc[] ordinaryClasses() {
List list = new ArrayList();
for (Iterator i = allClasses.iterator(); i.hasNext();) {
ClassDoc doc = (ClassDoc)i.next();
if (doc.isOrdinaryClass()) list.add(doc);
}
return (ClassDoc[])list.toArray
(new ClassDoc[list.size()]);
}
/**
* Returns all the exceptions in this package.
*
* @return an array of ClassDoc representing all
* the exceptions in this package.
*/
public ClassDoc[] exceptions() {
List list = new ArrayList();
for (Iterator i = allClasses.iterator(); i.hasNext();) {
ClassDoc doc = (ClassDoc)i.next();
if (doc.isException()) list.add(doc);
}
return (ClassDoc[])list.toArray
(new ClassDoc[list.size()]);
}
/**
* Returns all the errors in this package.
*
* @return an array of ClassDoc representing all
* the errors in this package.
*/
public ClassDoc[] errors() {
List list = new ArrayList();
for (Iterator i = allClasses.iterator(); i.hasNext();) {
ClassDoc doc = (ClassDoc)i.next();
if (doc.isError()) list.add(doc);
}
return (ClassDoc[])list.toArray
(new ClassDoc[list.size()]);
}
/**
* Returns all the interfaces in this package.
*
* @return an array of ClassDoc representing all
* the interfaces in this package.
*/
public ClassDoc[] interfaces() {
List list = new ArrayList();
for (Iterator i = allClasses.iterator(); i.hasNext();) {
ClassDoc doc = (ClassDoc)i.next();
if (doc.isInterface()) list.add(doc);
}
return (ClassDoc[])list.toArray
(new ClassDoc[list.size()]);
}
/**
* Returns the name if included -- null otherwise.
*
* @return the name if included -- null otherwise.
*/
public String name() {
return isIncluded() ? name : null;
}
/**
* Compare based on name()
.
*
* @param other other Object.
* @return true
if the other Object is a
* PackageDocImpl and has the same name.
*/
public boolean equals(Object other) {
return other instanceof PackageDocImpl && other != null
? name().equals(((PackageDocImpl)other).name())
: super.equals(other);
}
/**
* Returns the name.
*
* @return the name.
*/
public String toString() {
return name();
}
private void findDocumentation() {
if (ajdoc == null) return;
String filename = (name.equals("")
? name
: name.replace('.',File.separatorChar)
+ File.separatorChar) + "package.html";
File html = ajdoc.findFile(filename, false);
if (html == null) return;
String rawCommentText = Util.documentation(html, ajdoc.err());
//TODO: should be done in aspect from Aspects.java
//FormalComment comment = new FormalComment(rawCommentText);
setComment(new Comment(this, rawCommentText));
}
/* ------------------------------------------------------------
* Factory stuff
* ------------------------------------------------------------
*/
private static Map namesToPackages = new HashMap();
/**
* Returns the collection of known packages.
*
* @return a Collection representing the known packages.
*/
public static Collection packages() {
return namesToPackages.values();
}
/**
* Inits the world and AspectJCompiler with these
* packages.
*
* @param world current World.
* @param ajc current compiler.
*/
public static void init(AspectJCompiler ajc) {
PackageDocImpl.ajc = ajc;
if (ajc instanceof AjdocCompiler) {
PackageDocImpl.ajdoc = (AjdocCompiler)ajc;
}
}
/**
* Returns a package for a TypeDec.
*
* @param typeDec TypeDec whose package is desired.
* @return a PackageDocImpl for a given TypeDec.
*/
public static PackageDocImpl getPackageDoc(TypeDec typeDec) {
return getPackageDoc(typeDec.getPackageName());
}
/**
* Returns a package for a name.
*
* @param packageName package name for which to look.
* @return a PackageDocImpl for a given package name.
*/
public static PackageDocImpl getPackageDoc(String packageName) {
return addPackageDoc(packageName);
}
/**
* Adds a package with name name
if it
* already doesn't exist, and returns the new package
* (if own with the same name didn't exist) or the
* existing package.
*
* @param name name of the new package.
* @return current package mapping to
* name
.
*/
public static PackageDocImpl addPackageDoc(String name) {
if (name == null) name = UNNAMED_PACKAGE;
PackageDocImpl packageDoc = (PackageDocImpl)namesToPackages.get(name);
if (packageDoc == null) {
packageDoc = new PackageDocImpl(name);
addPackageDoc(packageDoc);
}
return packageDoc;
}
/**
* Adds the PackageDoc if one doesn't already exist
* with the same name, and returns the existing or created
* package with the same name as the one passed in .
*
* @param packageDoc PackageDoc we want to add.
* @return package in the world with the same
* name as packageDoc
.
*/
public static PackageDocImpl addPackageDoc(PackageDoc packageDoc) {
if (packageDoc == null) return null;
return (PackageDocImpl)namesToPackages.put(packageDoc.name(),
packageDoc);
}
/**
* Sets the include flag to false for empty packages
* todo: remove instead?
*/
public static void excludeEmptyPackages() {
for (Iterator i = packages().iterator(); i.hasNext();) {
PackageDocImpl pkg = (PackageDocImpl)i.next();
if (pkg.allClasses().length < 1) {
pkg.setIncluded(false);
}
}
}
}