
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