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

org.enhydra.xml.xmlc.compiler.AccessMethods 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: AccessMethods.java,v 1.3 2005/10/23 03:16:49 jkjome Exp $
 */

package org.enhydra.xml.xmlc.compiler;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;

import org.enhydra.xml.xmlc.codegen.IndentWriter;
import org.enhydra.xml.xmlc.codegen.JavaClass;
import org.enhydra.xml.xmlc.codegen.JavaCode;
import org.enhydra.xml.xmlc.codegen.JavaLang;
import org.enhydra.xml.xmlc.codegen.JavaMethod;
import org.enhydra.xml.xmlc.codegen.JavaModifiers;
import org.enhydra.xml.xmlc.codegen.JavaParameter;
import org.enhydra.xml.xmlc.dom.AccessorGenerator;
import org.enhydra.xml.xmlc.metadata.MetaData;

/**
 * Data collection and code generation for element access methods.
 */
class AccessMethods {
    /**
     * Information collected about each element.
     */
    private ElementTable fElementTable;

    /**
     * Should delegation support be create.
     */
    private boolean fCreateDelegation;

    /**
     * Class being generated.
     */
    private JavaClass fDocClass;

    /**
     * DOM Accessor generator.
     */
    private AccessorGenerator fAccessorGenerator;

    /**
     * List of accessor methods, indexed by element info object.
     */
    private HashMap fAccessorMethods = new HashMap();

    /**
     * Parameter for syncWithDocument methods.
     * A static since in can be shared.
     */
    private static final JavaParameter[] syncWithDocParam = {
        new JavaParameter("node", "Node",
                          "Root of subtree to sync.")
    };

    /**
     * Constructor.
     */
    public AccessMethods(MetaData metaData,
                         ElementTable elementTable,
                         AccessorGenerator accessorGenerator) {
        fCreateDelegation = metaData.getDocumentClass().getDelegateSupport();
        fElementTable = elementTable;
        fAccessorGenerator = accessorGenerator;
    }

    /**
     * Create the access methods and field definitions for an element.
     */
    private void createAccessMethods(ElementInfo elementInfo) {
        ElementInfo.AccessorInfo[] accessors = elementInfo.getAccessors();
        int methodIdx = 0;
        JavaMethod[] methods = new JavaMethod[elementInfo.getNumAccessMethods()];
        if (accessors != null) {
            for (int idx = 0; idx < accessors.length; idx++) {
                methods[methodIdx++]
                    = fAccessorGenerator.createAccessorMethod(elementInfo,
                                                              accessors[idx],
                                                              fCreateDelegation,
                                                              fDocClass);
            }
        }
        if (elementInfo.createSetText()) {
            methods[methodIdx++]
                = fAccessorGenerator.createSetTextMethod(elementInfo,
                                                         fCreateDelegation,
                                                         fDocClass);
        }
        fAccessorMethods.put(elementInfo, methods);
    }


    /**
     * Generate access methods and field definitions.
     */
    private void createAccessMethods() {
        Iterator elements = fElementTable.getJavaIdElements();
        while (elements.hasNext()) {
            ElementInfo elementInfo = (ElementInfo)elements.next();
            if (elementInfo.getNumAccessMethods() > 0) {
                createAccessMethods(elementInfo);
            }
        }
    }

    /**
     * Create code for initializing accessor fields from ElementInfo objects.
     */
    private void createAccessorFieldInits(JavaCode body,
                                          Iterator elements) {
        while (elements.hasNext()) {
            ElementInfo elementInfo = (ElementInfo)elements.next();
            if (elementInfo.getNumAccessMethods() > 0) {
                body.addln("} else if (id.equals(" + JavaLang.createStringConst(elementInfo.getXmlId()) + ")) {");
                body.enter();
                fAccessorGenerator.createResetElementAccess(elementInfo, "node", body);
                body.leave();
            }
        }
    }

    /**
     * Create body of code to set all element access fields to null.
     */
    private void createNullAccessFieldsInit(JavaCode body) {
        Iterator elements = fElementTable.getJavaIdElements();
        while (elements.hasNext()) {
            ElementInfo elementInfo = (ElementInfo)elements.next();
            if (elementInfo.getNumAccessMethods() > 0) {
                fAccessorGenerator.createNullElementAccess(elementInfo, body);
            }
        }
        body.addln();
    }

    /**
     * Create body of field initialization method for global id attribute
     * mode.
     */
    private void createGlobalIdModeInit(JavaCode body) {
        String idAttr = fElementTable.getXMLCDocument().getGlobalIdAttribute();
        body.addln("if (node instanceof Element) {");
        body.enter();
        body.addln("String id = ((Element)node).getAttribute("
                    + JavaLang.createStringConst(idAttr) + ");");
        body.addln("if (id.length() == 0) {");  // Block contains empty statement.
        
        createAccessorFieldInits(body, fElementTable.getJavaIdElements());

        body.addln("}");  // Closes last else-if
        body.leave();
        body.addln("}");
    }

    //FIXME: need to get the terminalogy straight:
    // global/local attribute id or single/multiple attribute id.

    /**
     * Create field initialization code for a tag in multple id attribute
     * mode.
     */
    private void createMultipleIdModeTagInit(String tagName,
                                             JavaCode body) {
        String idAttr = fElementTable.getIdAttributeName(tagName);
        if (idAttr == null) {
            return; // no id attribute
        }
        body.addln("if (tag.equals(" + JavaLang.createStringConst(tagName) + ")) {");
        body.enter();
        body.addln("String id = element.getAttribute("
                    + JavaLang.createStringConst(idAttr) + ");");
        // First block contains empty statement if id is empty
        body.addln("if (id.length() == 0) {");

        // Generate code for each id field for this tag.
        createAccessorFieldInits(body, fElementTable.getElementsByTagName(tagName));
        body.addln("}");  // Closes last else-if
        body.leave();
        body.addln("}");  // Closes tag.equals(xxx) block
    }

    /**
     * Create body of field initialization method for multple id attribute
     * mode.
     */
    private void createMultipleIdModeInit(JavaCode body) {
        body.addln(new String[] {
            "if (node instanceof Element) {",
            "    Element element = (Element)node;",
            "    String tag = element.getTagName();"
        });
        body.enter();
        
        // For each element tag name, generate code for all ids associated
        // with it.
        Iterator tags = fElementTable.getTagNames();
        while (tags.hasNext()) {
            createMultipleIdModeTagInit((String)tags.next(), body);
        }
        body.leave();
        body.addln("}");
    }

    /**
     * Generate access method field initialization function used in clone.
     * There are two versions of the code that can be generated:
     * 
    *
  • Global id attribute mode. One attribute names is used for * all ids and is not used anywhere else. That is, * XMLCDocument.getGlobalIdAttribute() returns a name. *
  • Multiple id attribute mode. Multiple attributes are declared * of type ID. *
*/ private void createAccessMethodSync() { String[] doc = { "Recursive function to do set access method fields from the DOM.", "Missing ids have fields set to null.", }; JavaMethod method = new JavaMethod("syncWithDocument", "void", JavaModifiers.PROTECTED, syncWithDocParam, doc); fDocClass.addMethod(method); JavaCode body = method.getCode(); // Generate body to initialize. if (fElementTable.isGlobalIdAttrMode()) { createGlobalIdModeInit(body); } else { createMultipleIdModeInit(body); } // Generate recursion down the tree. body.addln(new String[] { "Node child = node.getFirstChild();", "while (child != null) {", " syncWithDocument(child);", " child = child.getNextSibling();", "}" }); } /** * Generate the code for the access methods. * @param docClass Object containing the class being generated. */ public void generateCode(JavaClass docClass) { fDocClass = docClass; createAccessMethodSync(); createAccessMethods(); } /** * Print the signatures of the access methods are created. */ public void printAccessMethods(PrintWriter out) { IndentWriter iout = new IndentWriter(out); Iterator elements = fElementTable.getJavaIdElements(); while (elements.hasNext()) { ElementInfo elementInfo = (ElementInfo)elements.next(); JavaMethod[] methods = (JavaMethod[])fAccessorMethods.get(elementInfo); if (methods != null) { for (int idx = 0; idx < methods.length; idx++) { methods[idx].printMethodSignature(iout, false); } } } iout.flush(); } /** * Print ids that didn't have accessors generated due to being illegal * Java identifiers. We keep them sorted so that the test always work. */ public void printOmittedIds(PrintWriter out) { Iterator ids = fElementTable.getInvalidElementIds(); if ((ids != null) && ids.hasNext()) { out.println("Access methods not created for these element IDs"); out.println("since they are not legal Java identifiers:"); while (ids.hasNext()) { out.print("`"); out.print((String)ids.next()); out.println("'"); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy