All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.xml.xmlc.metadata.MetaDataDocument Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 * 
 * The contents of this file are subject to the Enhydra 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 on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 * 
 * 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 terms governing rights and limitations
 * under the License.
 * 
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * $Id: MetaDataDocument.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.xml.xmlc.metadata;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.util.HashMap;

import org.enhydra.apache.xerces.dom.DOMImplementationImpl;
import org.enhydra.apache.xerces.dom.DocumentImpl;
import org.enhydra.xml.dom.DOMInfo;
import org.enhydra.xml.io.DOMFormatter;
import org.enhydra.xml.io.DOMParser;
import org.enhydra.xml.io.ErrorReporter;
import org.enhydra.xml.io.InputSourceOps;
import org.enhydra.xml.io.OutputOptions;
import org.enhydra.xml.io.XMLEntityResolver;
import org.enhydra.xml.xmlc.XMLCError;
import org.enhydra.xml.xmlc.XMLCException;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

//FIXME: modify Xerces to take a already created document class.
//FIXME: use DOMImplementation

/**
 * Metadata XML document associated with a Document being parsed.  Data maybe
 * set from the command line or read from an XML file (or both).
 */
public class MetaDataDocument extends DocumentImpl {
    /** Document type name */
    public static final String DOC_TYPE_NAME = "xmlc";

    /** Public id for created metadata files */
    public static final String PUBLIC_ID
        = "-//ENHYDRA//DTD XMLC 1.1//EN";

    /** System id for created metadata files */
    public static final String SYSTEM_ID
        = "http://www.enhydra.org/xml/xmlc/xmlc-1.1.dtd";

    /** Error messages */
    private static final String ERR_PARSE_FAILED
        = "XMLC metadata file parse failed: ";
    private static final String ERR_WRITE_FAILED
        = "XMLC metadata file write failed: ";

    /**
     * Compile-time debugging.
     */
    private static final boolean DEBUG = false;

    /**
     * Extension for XMLC metadata files.
     */
    public static final String METADATA_FILE_EXTENSION = ".xmlc";

    /**
     * Table of tag name to element class.
     */
    private static HashMap tagClassTable = new HashMap();

    /**
     * Signature used to locate constructor of element class.
     */
    private static final Class[] elemClassConstructorSign
        = new Class[]{Document.class};

    /**
     * Static constructor.
     */
    static {
        // Initialize tag table.
        tagClassTable.put(JavaCompilerSection.TAG_NAME, JavaCompilerSection.class);
        tagClassTable.put(CompileOptions.TAG_NAME,  CompileOptions.class);
        tagClassTable.put(InputDocument.TAG_NAME,  InputDocument.class);
        tagClassTable.put(Include.TAG_NAME,  Include.class);
        tagClassTable.put(DeleteElement.TAG_NAME, DeleteElement.class);
        tagClassTable.put(DOMEdits.TAG_NAME, DOMEdits.class);
        tagClassTable.put(DocumentClass.TAG_NAME, DocumentClass.class);
        tagClassTable.put(DocumentSection.TAG_NAME, DocumentSection.class);
        tagClassTable.put(ElementDef.TAG_NAME, ElementDef.class);
        tagClassTable.put(HTMLAttr.TAG_NAME, HTMLAttr.class);
        tagClassTable.put(HTMLTag.TAG_NAME, HTMLTag.class);
        tagClassTable.put(HTMLTagSet.TAG_NAME, HTMLTagSet.class);
        tagClassTable.put(HTMLCompatibility.TAG_NAME, HTMLCompatibility.class);
        tagClassTable.put(HTMLSection.TAG_NAME, HTMLSection.class);
        tagClassTable.put(Implements.TAG_NAME, Implements.class);
        tagClassTable.put(JavacOption.TAG_NAME, JavacOption.class);
        tagClassTable.put(Parser.TAG_NAME, Parser.class);
        tagClassTable.put(TagClass.TAG_NAME, TagClass.class);
        tagClassTable.put(URLRegExpMapping.TAG_NAME, URLRegExpMapping.class);
        tagClassTable.put(URLMapping.TAG_NAME, URLMapping.class);
        tagClassTable.put(XCatalog.TAG_NAME, XCatalog.class);
        tagClassTable.put(MetaData.TAG_NAME, MetaData.class);
    }

    /**
     * Do work of parsing a XMLC metadata file.
     */
    static private MetaDataDocument doParseMetaData(InputSource inputSource,
                                                    ErrorReporter reporter,
                                                    ClassLoader classLoader) 
        throws XMLCException, IOException, SAXException {

        DOMParser parser = new DOMParser();
        XMLEntityResolver resolver = new XMLEntityResolver();
        if (DEBUG) {
            resolver.setDebugWriter(new PrintWriter(System.err, true));
        }

        if (classLoader != null) {
            resolver.addClassLoader(classLoader);
        }
        resolver.setDefaultResolving();
        parser.setEntityResolver(resolver);

        parser.setErrorHandler(reporter);
        parser.setDocumentClassName(MetaDataDocument.class.getName());

        MetaDataDocument document
            = (MetaDataDocument)parser.parse(inputSource);
        if (reporter.getErrorCnt() > 0) {
            throw new XMLCException(ERR_PARSE_FAILED + reporter.getErrorCnt()
                                    + " errors, (see log file): "
                                    + InputSourceOps.getName(inputSource));
        }
        if (DEBUG) {
            DOMInfo.printTree("Document after parse: "
                              + InputSourceOps.getName(inputSource),
                              document, System.err);
        }

        document.completeModifications();

        if (DEBUG) {
            DOMInfo.printTree("Document after completeModifications: " + InputSourceOps.getName(inputSource),
                              document, System.err);
        }
        return document;
    }

    /**
     * Parse a XMLC metadata file.
     *
     * @param inputSource Specification of file to parse.
     * @param reporter Object use to report errors.
     * @param classLoader If not null, class loader to use in resolving
     *  entities to be found on the classpath.
     */
    static public MetaDataDocument parseMetaData(InputSource inputSource,
                                                 ErrorReporter reporter,
                                                 ClassLoader classLoader) 
        throws XMLCException {
        try {
            return doParseMetaData(inputSource, reporter, classLoader);
        } catch (IOException except) {
            throw new XMLCException(ERR_PARSE_FAILED + InputSourceOps.getName(inputSource),
                                    except);
        } catch (SAXException except) {
            throw new XMLCException(ERR_PARSE_FAILED + InputSourceOps.getName(inputSource),
                                    except);
        }
    }

    /**
     * Construct an empty instace of a metadata document.  This is for use of
     * the parse, use newInstance to create a new document.
     */
    public MetaDataDocument() {
    }

    /**
     * Construct an new instace of a metadata document.
     */
    private MetaDataDocument(DocumentType docType) {
        super(docType);
    }

    /**
     * Create a new, uninitialized document.  Used when constructing
     * a document programatically.
     */
    public static MetaDataDocument newInstance() {
        DOMImplementation domImpl = DOMImplementationImpl.getDOMImplementation();
        DocumentType docType = domImpl.createDocumentType(DOC_TYPE_NAME,
                                                          PUBLIC_ID,
                                                          SYSTEM_ID);
        return new MetaDataDocument(docType);
    }

    /**
     * Serialize this object to a XML file.
     */
    public void serialize(File file) throws XMLCException {
        if (DEBUG) {
            DOMInfo.printTree("Document before write: " + file,
                              this, System.err);
        }
        OutputOptions outputOptions = new OutputOptions();
        outputOptions.setPrettyPrinting(true);
        outputOptions.setPreserveSpace(false);
        DOMFormatter domFormatter = new DOMFormatter(outputOptions);
        
        try {
            domFormatter.write(this, file);
        } catch (IOException except) {
            throw new XMLCException(ERR_WRITE_FAILED + file, except);
        }
    }
    
    /**
     * Get the name of the metadata output file
     *
     * davidli: this is needed to be public for debugging/logging purpose
     */
    public File getMetadataOutputFile () {
        DocumentClass documentClass = getMetaData().getDocumentClass();
	String fileName;

        if (documentClass.getGenerate().generateInterface()) {
            fileName = documentClass.getUnqualInterfaceName() +  METADATA_FILE_EXTENSION;
        } else {
            fileName = documentClass.getUnqualClassName() +  METADATA_FILE_EXTENSION;
        }

	File metaDataOutputDir = documentClass.getJavaClassSource().getParentFile();
	if (metaDataOutputDir == null) {
	    metaDataOutputDir = new File(getMetaData().getCompileOptions().getClassOutputRoot());
	    String packageName = documentClass.getPackageName();
	    if (packageName != null) {
		packageName = packageName.replace('.', File.separatorChar);
		metaDataOutputDir = new File(getMetaData().getCompileOptions().getClassOutputRoot(), packageName);
	    }
	}

	metaDataOutputDir.mkdirs();
        return new File(metaDataOutputDir, fileName);
    }

    /**
     * Serialize this object to a XML file using the default name.
     */
    public void serialize() throws XMLCException {
        DocumentClass documentClass = getMetaData().getDocumentClass();
        if (documentClass == null) {
            throw new XMLCError("No DocumentClass metadata object; can't determine default name");
        }

        serialize(getMetadataOutputFile());
    }

    /**
     * Get the root MetaData object, which must exist.
     */
    public MetaData getMetaData() {
        MetaData root = (MetaData)getDocumentElement();
        if (root == null) {
            root = (MetaData)createElement(MetaData.TAG_NAME);
            appendChild(root);
        }
        return root;
    }
    
    /**
     * Create a XMLC metadata document given its class.
     */
    public Element createElement(Class elementClass) {
        try {
            Constructor constr = elementClass.getConstructor(elemClassConstructorSign);
            return (Element)constr.newInstance(new Object[]{this});
        } catch (Exception except) {
            throw new XMLCError(except);
        }
    }

    /**
     * Create a XMLC metadata document element.
     */
    public Element createElement(String tagName) throws DOMException {
        Class elementClass = (Class)tagClassTable.get(tagName);
        if (elementClass == null) {
            throw new XMLCError("Invalid tag name: \"" + tagName + "\"");
        }
        return createElement(elementClass);
    }

    /**
     * Create a XMLC metadata document element. in a namespace.
     */
    public Element createElementNS(String namespaceURI,
                                   String qualifiedName) {
	if ((namespaceURI == null) || (namespaceURI.length() == 0)) {
	    return createElement(qualifiedName);
	} else {
            // FIXME: this should work in a namespace.
            throw new XMLCError("createElementNS not implemented");
        }
    }

    /**
     * Complete modifications to DOM.  This should be called after a set of
     * modifcations have been completed (it is called after a read).  It is
     * used to synchronize data in different areas of the DOM.
     */
    public void completeModifications() throws XMLCException {
        getMetaData().completeModifications();
    }

    /**
     * Merge another MetaData document into this document.
     */
    public void merge(MetaDataDocument srcDocument) {
        getMetaData().mergeElement(srcDocument.getMetaData());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy