FileDocCategorySizeDatePackage
XMLToAPI.javaAPI DocAndroid 1.5 API15217Wed May 06 22:41:22 BST 2009jdiff

XMLToAPI

public class XMLToAPI extends Object
Creates an API object from an XML file. The API object is the internal representation of an API. All methods in this class for populating an API object are static. See the file LICENSE.txt for copyright details.
author
Matthew Doar, mdoar@pobox.com

Fields Summary
private static API
api_
The instance of the API object which is populated from the file.
public static boolean
validateXML
If set, validate the XML which represents an API. By default, this is not set for reasons of efficiency, and also because if JDiff generated the XML, it should not need validating.
private static boolean
showExceptionTypes
If set, then store and display the whole qualified name of exceptions. If not set, then store and display just the name of the exception, which is shorter, but may not detect when an exception changes class, but retains the same name.
Constructors Summary
private XMLToAPI()
Default constructor.


       
      
    
Methods Summary
public static voidaddClass(java.lang.String name, java.lang.String parent, boolean isAbstract, Modifiers modifiers)
Create a new class and add it to the current package. Called by the XML parser.

param
name The name of the class.
param
parent The name of the parent class, null if no class is extended.
param
modifiers Modifiers for this class.

        api_.currClass_ = new ClassAPI(name, parent, false, isAbstract, modifiers);
        api_.currPkg_.classes_.add(api_.currClass_);
        String fqName = api_.currPkg_.name_ + "." + name;
        ClassAPI caOld = (ClassAPI)api_.classes_.put(fqName, api_.currClass_);
        if (caOld != null) {
            System.out.println("Warning: duplicate class : " + fqName + " found. Using the first instance only.");
        }
    
public static voidaddCtor(java.lang.String type, Modifiers modifiers)
Add a constructor to the current class. Called by the XML parser.

param
name The name of the constructor.
param
type The type of the constructor.
param
modifiers Modifiers for this constructor.

        String t = type;
        if (t == null)
            t = "void";
        api_.currCtor_ = new ConstructorAPI(t, modifiers);
        api_.currClass_.ctors_.add(api_.currCtor_);
    
public static voidaddException(java.lang.String name, java.lang.String type, java.lang.String currElement)
Add an exception to the current method or constructor. Called by the XML parser.

param
name The name of the parameter.
param
type The type of the parameter. May be null in JDiff1.0.8 and earlier versions.
param
currElement Name of the current element.

	String exceptionId = type;
	if (type == null || !showExceptionTypes)
	    exceptionId = name;
        if (currElement.compareTo("method") == 0) {
            if (api_.currMethod_.exceptions_.compareTo("no exceptions") == 0)
                api_.currMethod_.exceptions_ = exceptionId;
            else
                api_.currMethod_.exceptions_ += ", " + exceptionId;
        } else {
            if (api_.currCtor_.exceptions_.compareTo("no exceptions") == 0)
                api_.currCtor_.exceptions_ = exceptionId;
            else
                api_.currCtor_.exceptions_ += ", " + exceptionId;
        }
    
public static voidaddField(java.lang.String name, java.lang.String type, boolean isTransient, boolean isVolatile, java.lang.String value, Modifiers modifiers)
Add a field to the current class. Called by the XML parser.

param
name The name of the field.
param
type The type of the field, null if it is void.
param
modifiers Modifiers for this field.

        String t = type;
        if (t == null)
            t = "void";
        api_.currField_ = new FieldAPI(name, t, isTransient, isVolatile, value, modifiers);
        api_.currClass_.fields_.add(api_.currField_);
    
public static voidaddImplements(java.lang.String name)
Add an inherited interface to the current class. Called by the XML parser.

param
name The name of the inherited interface.

       api_.currClass_.implements_.add(name);
    
public static voidaddInheritedElements()
Add the inherited methods and fields to each class in turn.

        Iterator iter = api_.packages_.iterator();
        while (iter.hasNext()) {
            PackageAPI pkg = (PackageAPI)(iter.next());
            Iterator iter2 = pkg.classes_.iterator();
            while (iter2.hasNext()) {
                ClassAPI cls = (ClassAPI)(iter2.next());
                // Look up any inherited classes or interfaces
                if (cls.extends_ != null) {
                    ClassAPI parent = (ClassAPI)api_.classes_.get(cls.extends_);
                    if (parent != null)
                        addInheritedElements(cls, parent, cls.extends_);
                }
                if (cls.implements_.size() != 0) {
                    Iterator iter3 = cls.implements_.iterator();
                    while (iter3.hasNext()) {
                        String implName = (String)(iter3.next());
                        ClassAPI parent = (ClassAPI)api_.classes_.get(implName);
                        if (parent != null)
                            addInheritedElements(cls, parent, implName);
                    }
                }
            } //while (iter2.hasNext())
        } //while (iter.hasNext())
    
public static voidaddInheritedElements(ClassAPI child, ClassAPI parent, java.lang.String fqParentName)
Add all the inherited methods and fields in the second class to the first class, marking them as inherited from the second class. Do not add a method or a field if it is already defined locally. Only elements at the specified visibility level or higher appear in the XML file. All that remains to be tested for a private element, which is never inherited. If the parent class inherits any classes or interfaces, call this method recursively with those parents.

        if (parent.methods_.size() != 0) {
            Iterator iter = parent.methods_.iterator();
            while (iter.hasNext()) {
                MethodAPI m = (MethodAPI)(iter.next());
                // See if it the method is overridden locally
                boolean overridden = false;
                Iterator iter2 = child.methods_.iterator();
                while (iter2.hasNext()) {
                    MethodAPI localM = (MethodAPI)(iter2.next());
                    if (localM.name_.compareTo(m.name_) == 0 && 
                        localM.getSignature().compareTo(m.getSignature()) == 0)
                        overridden = true;
                }
                if (!overridden && m.inheritedFrom_ == null &&
                    m.modifiers_.visibility != null && 
                    m.modifiers_.visibility.compareTo("private") != 0) {
                    MethodAPI m2 = new MethodAPI(m);
                    m2.inheritedFrom_ = fqParentName;
                    child.methods_.add(m2);
                }
            }            
        }
        if (parent.fields_.size() != 0) {
            Iterator iter = parent.fields_.iterator();
            while (iter.hasNext()) {
                FieldAPI f = (FieldAPI)(iter.next());
                if (child.fields_.indexOf(f) == -1 &&
                    f.inheritedFrom_ == null &&
                    f.modifiers_.visibility != null && 
                    f.modifiers_.visibility.compareTo("private") != 0) {
                    FieldAPI f2 = new FieldAPI(f);
                    f2.inheritedFrom_ = fqParentName;
                    child.fields_.add(f2);
                }
            }            
        }

        // Look up any inherited classes or interfaces
        if (parent.extends_ != null) {
            ClassAPI parent2 = (ClassAPI)api_.classes_.get(parent.extends_);
            if (parent2 != null)
                addInheritedElements(child, parent2, parent.extends_);
        }
        if (parent.implements_.size() != 0) {
            Iterator iter3 = parent.implements_.iterator();
            while (iter3.hasNext()) {
                String implName = (String)(iter3.next());
                ClassAPI parent2 = (ClassAPI)api_.classes_.get(implName);
                if (parent2 != null)
                    addInheritedElements(child, parent2, implName);
            }
        }
    
public static voidaddInterface(java.lang.String name, java.lang.String parent, boolean isAbstract, Modifiers modifiers)
Add an new interface and add it to the current package. Called by the XML parser.

param
name The name of the interface.
param
parent The name of the parent interface, null if no interface is extended.

        api_.currClass_ = new ClassAPI(name, parent, true, isAbstract, modifiers);
        api_.currPkg_.classes_.add(api_.currClass_);
    
public static voidaddMethod(java.lang.String name, java.lang.String returnType, boolean isAbstract, boolean isNative, boolean isSynchronized, Modifiers modifiers)
Add a method to the current class. Called by the XML parser.

param
name The name of the method.
param
returnType The return type of the method, null if it is void.
param
modifiers Modifiers for this method.

        String rt = returnType;
        if (rt == null)
            rt = "void";
        api_.currMethod_ = new MethodAPI(name, rt, isAbstract, isNative,
                                         isSynchronized, modifiers);
        api_.currClass_.methods_.add(api_.currMethod_);
    
public static voidaddPackage(java.lang.String name)
Create a new package and add it to the API. Called by the XML parser.

param
name The name of the package.

        api_.currPkg_ = new PackageAPI(name);
        api_.packages_.add(api_.currPkg_);
    
public static voidaddParam(java.lang.String name, java.lang.String type)
Add a parameter to the current method. Called by the XML parser. Constuctors have their type (signature) in an attribute, since it is often shorter and makes parsing a little easier.

param
name The name of the parameter.
param
type The type of the parameter, null if it is void.

        String t = type;
        if (t == null)
            t = "void";
        ParamAPI paramAPI = new ParamAPI(name, t);
        api_.currMethod_.params_.add(paramAPI);
    
public static voidnameAPI(java.lang.String name)
Set the name of the API object.

param
name The name of the package.

        if (name == null) {
            System.out.println("Error: no API identifier found in the XML file '" + api_.name_ + "'");
            System.exit(3);
        }
        // Check the given name against the filename currently stored in 
        // the name_ field
        String filename2 = name.replace(' ",'_");
        filename2 += ".xml";
        if (filename2.compareTo(api_.name_) != 0) {
            System.out.println("Warning: API identifier in the XML file (" + 
                               name + ") differs from the name of the file '" +
                               api_.name_ + "'");
        }
        api_.name_ = name;
    
public static APIreadFile(java.lang.String filename, boolean createGlobalComments, java.lang.String apiName)
Read the file where the XML representing the API is stored.

param
filename The full name of the file containing the XML representing the API
param
createGlobalComments If set, then store possible comments
param
apiName The simple name of the API file. If -oldapidir and -newapidir are not used, then this is the same as the filename parameter

        // The instance of the API object which is populated from the file. 
        api_ = new API();
        api_.name_ = apiName; // Checked later
        try {
            XMLReader parser = null;
            DefaultHandler handler = new APIHandler(api_, createGlobalComments);
            try {
                String parserName = System.getProperty("org.xml.sax.driver");
                if (parserName == null) {
                    parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
                } else {
                    // Let the underlying mechanisms try to work out which 
                    // class to instantiate
                    parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
                }
            } catch (SAXException saxe) {
                System.out.println("SAXException: " + saxe);
                saxe.printStackTrace();
                System.exit(1);
            }
            if (validateXML) {
                parser.setFeature("http://xml.org/sax/features/namespaces", true);
                parser.setFeature("http://xml.org/sax/features/validation", true);
                parser.setFeature("http://apache.org/xml/features/validation/schema", true);
            }

            parser.setContentHandler(handler);
            parser.setErrorHandler(handler);
            parser.parse(new InputSource(new FileInputStream(new File(filename))));
        } catch(org.xml.sax.SAXNotRecognizedException snre) {
            System.out.println("SAX Parser does not recognize feature: " + snre);
            snre.printStackTrace();
            System.exit(1);
        } catch(org.xml.sax.SAXNotSupportedException snse) {
            System.out.println("SAX Parser feature is not supported: " + snse);
            snse.printStackTrace();
            System.exit(1);
        } catch(org.xml.sax.SAXException saxe) {
            System.out.println("SAX Exception parsing file '" + filename + "' : " + saxe);
            saxe.printStackTrace();
            System.exit(1);
        } catch(java.io.IOException ioe) {
            System.out.println("IOException parsing file '" + filename + "' : " + ioe);
            ioe.printStackTrace();
            System.exit(1);
        }

        // Add the inherited methods and fields to each class
        addInheritedElements();
        return api_;