
org.enhydra.xml.xmlc.metadata.MetaDataElement 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: MetaDataElement.java,v 1.3 2005/01/26 08:29:24 jkjome Exp $
*/
package org.enhydra.xml.xmlc.metadata;
import java.lang.reflect.Array;
import java.util.StringTokenizer;
import org.enhydra.apache.xerces.dom.DocumentImpl;
import org.enhydra.apache.xerces.dom.ElementImpl;
import org.enhydra.xml.xmlc.XMLCException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Base DOM class for all XMLC metadata element classes. This provides
* methods to implement attribute and child lookup
*/
public class MetaDataElement extends ElementImpl {
/**
* An empty string array.
*/
private static final String[] emptyStringArray = new String[0];
/**
* This is the change counter of the object taken when it was
* marked as being allDefaults. This is used to determine if
* a node as any custom values in or are only defaults.
* FIXME: implement
*/
/**
* Constructor.
*/
protected MetaDataElement(Document ownerDoc,
String name) {
super((DocumentImpl)ownerDoc, name);
}
/**
* Get the metadata document object.
*/
public MetaDataDocument getDocument() {
return (MetaDataDocument)getOwnerDocument();
}
/**
* Get the metadata root element object.
*/
public MetaData getMetaData() {
return getDocument().getMetaData();
}
// FIXME: the mechanism for defaulting children and the creation
// on the fly of needed children may have some undesriable
// side affects (if one child updates another). What really
// needs to happen is that the defaulted child are all created
// initialally and marked as defaulted.
/**
* Locate a child element given its class. This is used when only
* a single instance of an element can be a child.
*
* @return The first child elment of the specified class.
*/
protected MetaDataElement getCreateChild(Class elementClass) {
Node child = getChild(elementClass);
if (child == null) {
// Need to create
child = getDocument().createElement(elementClass);
appendChild(child);
}
return (MetaDataElement)child;
}
/**
* Locate a child element given its class, creating if if it doesn't
* exist.
*
* @return The first child elment of the specified class or null
* in no child element implements the class.
*/
protected MetaDataElement getChild(Class elementClass) {
for (Node child = getFirstChild(); child != null;
child = child.getNextSibling()) {
if (elementClass.isInstance(child)) {
return (MetaDataElement)child;
}
}
return null;
}
/**
* Add or replace a child element. This is used when only
* a single instance of an element can be a child.
*/
protected void setChild(MetaDataElement element) {
Node current = getChild(element.getClass());
if (current == null) {
appendChild(element);
} else {
replaceChild(element, current);
}
}
/**
* Delete a child element given its class. This is used when only
* a single instance of an element can be a child. If the element
* does not exist, the call is ignored.
*/
protected void deleteChild(Class elementClass) {
Node current = getChild(elementClass.getClass());
if (current != null) {
removeChild(current);
}
}
/**
* Get all children of the specified class.
*/
protected Node[] getChildren(Class elementClass) {
// Count
int numChildren = 0;
for (Node child = getFirstChild(); child != null;
child = child.getNextSibling()) {
if (elementClass.isInstance(child)) {
numChildren++;
}
}
// Create array of the children
Node[] children = (Node[])Array.newInstance(elementClass, numChildren);
int idx = 0;
for (Node child = getFirstChild();
(child != null) && (idx < numChildren);
child = child.getNextSibling()) {
if (elementClass.isInstance(child)) {
children[idx++] = child;
}
}
return children;
}
/**
* Determine if an attribute is specified.
*/
protected boolean isAttributeSpecified(String attrName) {
Attr attr = getAttributeNode(attrName);
if (attr == null) {
return false;
} else {
return attr.getSpecified();
}
}
/**
* Get the value of a boolean object attribute. Boolean objects
* are used ot value that can be true, false, or unspecified.
*
* @param attrName The name of the attribute.
* @return The value of the object, or null if it doesn't exists.
*/
protected Boolean getBooleanObjectAttribute(String attrName) {
String attrValue = getAttributeNull(attrName);
if (attrValue == null) {
return null;
} else {
if (attrValue.equalsIgnoreCase("true")
|| attrValue.equalsIgnoreCase("yes")) {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
}
/**
* Set or delete the value of a boolean object attribute. Boolean objects
* are used for value that can be true, false, or unspecified.
*
* @param attrName The name of the attribute.
* @param value The value of the attribute, or null to delete.
*/
protected void setBooleanObjectAttribute(String attrName,
Boolean value) {
if (value == null) {
removeAttribute(attrName);
} else {
setAttribute(attrName, value.toString());
}
}
/**
* Get the value of a boolean primitive attribute.
*
* @param attrName The name of the attribute.
* @param defaultValue Value to return if attribute doesn't exist.
* @return The value of the object.
*/
protected boolean getBooleanAttribute(String attrName,
boolean defaultValue) {
String attrValue = getAttributeNull(attrName);
if (attrValue == null) {
return defaultValue;
} else {
if (attrValue.equalsIgnoreCase("true")
|| attrValue.equalsIgnoreCase("yes")) {
return true;
} else {
return false;
}
}
}
/**
* Get the value of a boolean primitive attribute, with the default
* being false.
*
* @param attrName The name of the attribute.
* @return The value of the object.
*/
protected boolean getBooleanAttribute(String attrName) {
return getBooleanAttribute(attrName, false);
}
/**
* Set the value of a boolean primitive attribute.
*
* @param attrName The name of the attribute.
* @param value The value of the attribute.
* @param defaultValue The default value for the attribute.
* If the value matches the default value, the attribute
* is removed rather than set. This must match the default
* passed to get.
*/
protected void setBooleanAttribute(String attrName,
boolean value,
boolean defaultValue) {
if (value == defaultValue) {
removeAttribute(attrName);
} else {
setAttribute(attrName, (value ? "true" : "false"));
}
}
/**
* Set the value of a boolean primitive attribute, with a
* default of false.
*
* @param attrName The name of the attribute.
* @param value The value of the attribute.
*/
protected void setBooleanAttribute(String attrName,
boolean value) {
setBooleanAttribute(attrName, value, false);
}
/**
* Get the value of a string attribute, or null if its not defined.
*/
protected String getAttributeNull(String attrName) {
Attr attr = getAttributeNode(attrName);
if (attr == null) {
return null;
} else {
return attr.getValue();
}
}
/**
* Set or remove a string attribute. If the value is null, it is removed.
*/
protected void setRemoveAttribute(String attrName,
String value) {
if (value == null) {
removeAttribute(attrName);
} else {
setAttribute(attrName, value);
}
}
/**
* Get the value of a String array attribute.
*/
protected String[] getStringArrayAttribute(String attrName) {
String value = getAttributeNull(attrName);
String[] values;
if (value == null) {
values = emptyStringArray;
} else {
// Parse into tokens
StringTokenizer tokenizer = new StringTokenizer(value);
values = new String[tokenizer.countTokens()];
for (int idx = 0; idx < values.length; idx++) {
values[idx] = tokenizer.nextToken();
}
}
return values;
}
/**
* Set or remove a String array attribute. If the values is null, it is
* removed.
*/
protected void setRemoveStringArrayAttribute(String attrName,
String[] values) {
if (values == null) {
removeAttribute(attrName);
} else {
// Join into a string.
StringBuffer value = new StringBuffer();
for (int idx = 0; idx < values.length; idx++) {
if (idx > 0) {
value.append(' ');
}
value.append(values[idx]);
}
setAttribute(attrName, value.toString());
}
}
/**
* Add a addtribute to a String array attribute.
*/
protected void addStringArrayAttribute(String attrName,
String value) {
String currentValue = getAttributeNull(attrName);
if (currentValue == null) {
currentValue = "";
}
StringBuffer currentBuf = new StringBuffer(currentValue);
if (currentBuf.length() > 0) {
currentBuf.append(' ');
}
currentBuf.append(value);
setAttribute(attrName, currentBuf.toString());
}
/**
* Complete modifications to DOM. This method is called on all elements
* in the DOM in a bottom-first manner once a read or set of modifications
* are complete. Elements should override this method if they need to do
* any processing. Normally, they will call super.completeModifications()
* first to traverse the subtree, then do their work. This is also useful
* in report errors upfront rather than at access time.
*/
protected void completeModifications() throws XMLCException {
for (Node child = getFirstChild();
child != null;
child = child.getNextSibling()) {
if (child instanceof MetaDataElement) {
((MetaDataElement)child).completeModifications();
}
}
}
/**
* Merge attributes from another element into this element,
* with the other element overriding current attributes.
*/
protected void mergeAttributes(Element srcElement) {
Document doc = getOwnerDocument();
NamedNodeMap attrs = srcElement.getAttributes();
int len = attrs.getLength();
for (int idx = 0; idx < len; idx++) {
Attr attr = (Attr)attrs.item(idx);
if (attr.getSpecified()) {
setAttributeNode((Attr)doc.importNode(attr, true));
}
}
}
/**
* Merge a specified singleton child node, if it exists, otherwise
* clone it (if it exists).
*/
protected void mergeSingletonChild(Class childClass,
MetaDataElement srcElement) {
MetaDataElement srcChild = srcElement.getChild(childClass);
if (srcChild != null) {
MetaDataElement destChild = getChild(childClass);
if (destChild != null) {
destChild.mergeElement(srcChild);
} else {
appendChild(getOwnerDocument().importNode(srcChild, true));
}
}
}
/**
* Merge another element into this element. This merges the attributes,
* the children and then appends clones the children. This
* maybe overriden. In particular, calling mergeElement to
* merge children is desired if there should only be one child of
* a particular type.
*/
protected void mergeElement(MetaDataElement srcElement) {
mergeAttributes(srcElement);
Document document = getOwnerDocument();
for (Node child = srcElement.getFirstChild();
child != null;
child = child.getNextSibling()) {
appendChild(document.importNode(child, true));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy