
org.enhydra.xml.xmlc.compiler.ElementTable 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: ElementTable.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
*/
package org.enhydra.xml.xmlc.compiler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.enhydra.xml.xmlc.XMLCError;
import org.enhydra.xml.xmlc.XMLCException;
import org.enhydra.xml.xmlc.dom.XMLCDocument;
import org.enhydra.xml.xmlc.metadata.MetaData;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Table of information about each element.
*/
public class ElementTable {
/**
* Container for document.
*/
private XMLCDocument fXmlcDoc;
/**
* Metadata object associated with document.
*/
private MetaData fMetaData;
/**
* List of all element info objects, indexed by Element object.
*/
private Map fElements = new HashMap();
/**
* Sorted map of ids to element info.
*/
private SortedMap fXmlIds = new TreeMap();
/**
* Sorted map of Java ids to element info.
*/
private SortedMap fJavaIds = new TreeMap();
/**
* Sorted table of element ids that are not legal Java identifiers.
* Created when needed.
*/
private SortedMap fInvalidElementIds;
/**
* Is this global-id-attribute mode?
*/
private boolean fGlobalIdAttrMode;
/**
* Table of tag name to id attribute names. Null in
* global-id-attribute mode.
*/
private Map fTagName2IdAttrName;
/**
* Table of tag names to Lists of element info objects.
* Null in global-id-attribute mode.
*/
private Map fTagName2ElementInfoList;
/**
* The size of the document, in nodes.
*/
private int fDocumentNodeSize;
/**
* Constructor. Builds the table.
*/
public ElementTable(MetaData metaData,
XMLCDocument xmlcDoc) throws XMLCException {
fMetaData = metaData;
fXmlcDoc = xmlcDoc;
fGlobalIdAttrMode = (fXmlcDoc.getGlobalIdAttribute() != null);
if (!fGlobalIdAttrMode) {
fTagName2IdAttrName = new HashMap();
fTagName2ElementInfoList = new HashMap();
}
fDocumentNodeSize = addElements(fXmlcDoc.getDocument());
}
/**
* Recursively determine node sizes
*/
private int getRecursiveNodeCount(Node node) {
int count = getNodeCount(node);
for (Node child = node.getFirstChild(); child != null;
child = child.getNextSibling()) {
count += getRecursiveNodeCount(child);
}
return count;
}
/**
* Get the size of a single node (but not its children). Does
* include attribute sizes.
*/
private int getNodeCount(Node node) {
int count = 1; // this node
NamedNodeMap attrs = node.getAttributes();
if (attrs != null) {
int len = attrs.getLength();
for (int idx = 0; idx < len; idx++) {
count += getRecursiveNodeCount(attrs.item(idx));
}
}
return count;
}
/**
* Record information for local id-attribute mode.
*/
private void recordLocalIdAttributeInfo(ElementInfo elementInfo,
Element element) {
String tagName = element.getTagName();
fTagName2IdAttrName.put(tagName, fXmlcDoc.getIdAttrName(element));
List idElementList = (List)fTagName2ElementInfoList.get(tagName);
if (idElementList == null) {
idElementList = new ArrayList();
fTagName2ElementInfoList.put(tagName, idElementList);
}
idElementList.add(elementInfo);
}
/**
* Add an element to the table.
*/
private void addElement(Element element,
int nodeSize,
int subTreeSize) throws XMLCException {
ElementInfo elementInfo
= new ElementInfo(element, nodeSize, subTreeSize,
fMetaData, fXmlcDoc);
// Check that Java id is unique
String javaId = elementInfo.getJavaId();
if (javaId != null) {
//FIXME: Should build list and report at the end.
if (fJavaIds.containsKey(javaId)) {
throw new XMLCException("Duplicate element id \"" + elementInfo.getXmlId()
+ "\", id must be unique after first character is capitalized");
}
fJavaIds.put(javaId, elementInfo);
}
// Add to lists of all.
fElements.put(element, elementInfo);
// Handle id to element mapping
if (elementInfo.hasInvalidJavaId()) {
// Remember if this element has an invalid java id
if (fInvalidElementIds == null) {
fInvalidElementIds = new TreeMap();
}
fInvalidElementIds.put(elementInfo.getXmlId(),
elementInfo);
} else {
// It has an id, add it to the index.
String xmlId = elementInfo.getXmlId();
if (xmlId != null) {
fXmlIds.put(xmlId, elementInfo);
}
}
if (!fGlobalIdAttrMode) {
recordLocalIdAttributeInfo(elementInfo, element);
}
}
/**
* Recursively walk the DOM and enter all elements.
* @return the size, in nodes, of the subtree starting at this
* element.
*/
private int addElements(Node node) throws XMLCException {
int nodeSize = getNodeCount(node);
int childSize = 0;
for (Node child = node.getFirstChild(); child != null;
child = child.getNextSibling()) {
childSize += addElements(child);
}
if (node instanceof Element) {
addElement((Element)node, nodeSize, nodeSize+childSize);
}
return nodeSize+childSize;
}
/**
* Get the XMLCDocument object stored in the table.
*/
public XMLCDocument getXMLCDocument() {
return fXmlcDoc;
}
/**
* Get the size of the document, in nodes.
*/
public int getDocumentNodeSize() {
return fDocumentNodeSize;
}
/**
* Is there only one attribute name for all id attributes?
*/
public boolean isGlobalIdAttrMode() {
return fGlobalIdAttrMode;
}
/**
* Look up an ElementInfo by Element.
*/
public ElementInfo getElementInfo(Element element) {
ElementInfo info = (ElementInfo)fElements.get(element);
if (info == null) {
throw new XMLCError("element not found in element info table");
}
return info;
}
/**
* Get a interator of all ElementInfo objects.
*/
public Iterator getElements() {
return fElements.values().iterator();
}
/**
* Get an iterator of all ElementInfo objects that have Java ids.
*/
public Iterator getJavaIdElements() {
return fJavaIds.values().iterator();
}
/**
* Get an iterator of ElementInfo entries by tag name.
* Only valid in local-id-attribute mode.
*/
public Iterator getElementsByTagName(String tagName) {
return ((List)fTagName2ElementInfoList.get(tagName)).iterator();
}
/**
* Get all tag names that were found in local-id-attribute mode.
* Returns null in global-id-attribute mode.
*/
public Iterator getTagNames() {
if (fGlobalIdAttrMode) {
return null; // Not kept for global.
} else {
return fTagName2IdAttrName.keySet().iterator();
}
}
/**
* Get the id-attribute name for a tag.
*/
public String getIdAttributeName(String tagName) {
//FXIME: still needed??
return (String)fTagName2IdAttrName.get(tagName);
}
/**
* Get an sorted iterator of element ids that are not legal Java
* identifiers, or null if all ids were legal.
*/
public Iterator getInvalidElementIds() {
if (fInvalidElementIds != null) {
return fInvalidElementIds.keySet().iterator();
} else {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy