001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.edl;
018:
019: import java.util.Date;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import javax.xml.parsers.DocumentBuilder;
024: import javax.xml.parsers.DocumentBuilderFactory;
025: import javax.xml.parsers.ParserConfigurationException;
026:
027: import org.apache.log4j.Logger;
028: import org.w3c.dom.Document;
029: import org.w3c.dom.Element;
030: import org.w3c.dom.Node;
031: import org.w3c.dom.NodeList;
032:
033: import edu.iu.uis.eden.edl.components.MatchingParam;
034: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
035:
036: /**
037: * Contains a bunch of dom utility methods.
038: *
039: * @author rkirkend
040: * @author ahamid
041: *
042: */
043: public class EDLXmlUtils {
044:
045: private static final Logger LOG = Logger
046: .getLogger(EDLXmlUtils.class);
047:
048: public static final String EDL_E = "edl";
049: public static final String EDLCONTENT_E = "edlContent";
050: public static final String DATA_E = "data";
051: public static final String TYPE_E = "type";
052: public static final String VALIDATION_E = "validation";
053: public static final String VERSION_E = "version";
054: public static final String DOCID_E = "docId";
055:
056: private static ThreadLocal DOCUMENT_BUILDER = new ThreadLocal() {
057: protected Object initialValue() {
058: try {
059: return DocumentBuilderFactory.newInstance()
060: .newDocumentBuilder();
061: } catch (ParserConfigurationException pce) {
062: // well folks, there is not much we can do if we get a ParserConfigurationException
063: // so might as well isolate the evilness here, and just balk if this occurs
064: String message = "Error obtaining document builder";
065: LOG.error(message, pce);
066: return new RuntimeException(message, pce);
067: }
068: }
069: };
070:
071: /**
072: * Returns a valid DocumentBuilder
073: * @return a valid DocumentBuilder
074: */
075: public static DocumentBuilder getDocumentBuilder() {
076: return (DocumentBuilder) DOCUMENT_BUILDER.get();
077: }
078:
079: public static Element createFieldDataElement(
080: Element parentVersionElement, MatchingParam matchingParam) {
081: Element fieldData = createChildElement(parentVersionElement,
082: "field");
083: fieldData.setAttribute("name", matchingParam.getParamName());
084: if (matchingParam.getError().booleanValue()) {
085: fieldData.setAttribute("invalid", "true");
086: Element errorMessage = getOrCreateChildElement(fieldData,
087: "errorMessage", true);
088: placeTextInElement(errorMessage, matchingParam
089: .getErrorMessage());
090: }
091: Element fieldValue = getOrCreateChildElement(fieldData,
092: "value", true);
093: placeTextInElement(fieldValue, matchingParam.getParamValue());
094: return fieldData;
095: }
096:
097: public static Element createChildElement(Element parentElement,
098: String elementName) {
099: Element child = parentElement.getOwnerDocument().createElement(
100: elementName);
101: parentElement.appendChild(child);
102: return child;
103: }
104:
105: public static Element getDocumentStateElement(Document dom) {
106: return EDLXmlUtils.getOrCreateChildElement(dom
107: .getDocumentElement(), "documentState", true);
108: }
109:
110: public static void addGlobalErrorMessage(Document dom,
111: String errorMessage) {
112: Element documentState = getDocumentStateElement(dom);
113: createTextElementOnParent(documentState, "error", errorMessage);
114: }
115:
116: private static void placeTextInElement(Element element, String text) {
117: if (element.getOwnerDocument() == null) {
118: throw new WorkflowRuntimeException(
119: "The element must have an owner document in order to add text");
120: }
121: element.appendChild(element.getOwnerDocument().createTextNode(
122: text));
123: }
124:
125: public static Element createTextElementOnParent(Element parent,
126: String childElementName, String text) {
127: if (text == null) {
128: throw new WorkflowRuntimeException(
129: "The text placed in an Element cannot be null");
130: }
131: Element childElement = parent.getOwnerDocument().createElement(
132: childElementName);
133: parent.appendChild(childElement);
134: childElement.appendChild(parent.getOwnerDocument()
135: .createTextNode(text));
136: return childElement;
137: }
138:
139: public static Element getVersionFromData(Element dataElement,
140: Integer versionCount) {
141: if (dataElement == null) {
142: throw new WorkflowRuntimeException(
143: "Attempting to put version element inside null data Element");
144: }
145: if (!dataElement.getTagName().equals(DATA_E)) {
146: throw new WorkflowRuntimeException(
147: "Attempting to put version element inside a parent that is not a data element "
148: + dataElement.getTagName());
149: }
150: Element version = createChildElement(dataElement, VERSION_E);
151: version.setAttribute("current", "true");
152: version.setAttribute("date", new Date().toString());
153: version.setAttribute("version", versionCount.toString());
154: return version;
155: }
156:
157: public static Element getDataFromEDLDocument(Element edlContent,
158: boolean create) {
159: return getOrCreateChildElement(edlContent, DATA_E, create);
160: }
161:
162: public static Element getEDLContent(Document displayDoc,
163: boolean create) {
164: return getOrCreateChildElement(displayDoc.getDocumentElement(),
165: EDLCONTENT_E, create);
166: }
167:
168: /**
169: * Returns, and creates if absent, a child element
170: * @param parent the parent element
171: * @param name the name of the child element to create and/or return
172: * @return reference to the child element
173: */
174: public static Element getOrCreateChildElement(Element parent,
175: String name, boolean create) {
176: if (parent == null) {
177: throw new WorkflowRuntimeException(
178: "Passed in null parent element attempting to create child element '"
179: + name + "'");
180: }
181: Element child = getChildElement(parent, name);
182: if (child == null && create) {
183: LOG.debug("Creating child element '" + name
184: + "' of parent: ");
185: child = parent.getOwnerDocument().createElement(name);
186: parent.appendChild(child);
187: }
188: return child;
189: }
190:
191: /**
192: * Returns a node child with the specified tag name of the specified parent node,
193: * or null if no such child node is found.
194: * @param parent the parent node
195: * @param name the name of the child node
196: * @return child node if found, null otherwise
197: */
198: public static Element getChildElement(Node parent, String name) {
199: NodeList childList = parent.getChildNodes();
200: for (int i = 0; i < childList.getLength(); i++) {
201: Node node = childList.item(i);
202: // we must test against NodeName, not just LocalName
203: // LocalName seems to be null - I am guessing this is because
204: // the DocumentBuilderFactory is not "namespace aware"
205: // although I would have expected LocalName to default to
206: // NodeName
207: if (node.getNodeType() == Node.ELEMENT_NODE
208: && (name.equals(node.getLocalName()) || name
209: .equals(node.getNodeName()))) {
210: return (Element) node;
211: }
212: }
213: return null;
214: }
215:
216: /**
217: * Returns the text value of a child element with the given name, of the given parent element,
218: * or null if the child does not exist or does not have a child text node
219: * @param parent parent element
220: * @param name name of child element
221: * @return the text value of a child element with the given name, of the given parent element,
222: * or null if the child does not exist or does not have a child text node
223: */
224: public static String getChildElementTextValue(Node parent,
225: String name) {
226: Element child = getChildElement(parent, name);
227: if (child == null) {
228: return null;
229: }
230: Node textNode = child.getFirstChild();
231: if (textNode == null) {
232: return null;
233: }
234: return textNode.getNodeValue();
235: }
236:
237: /**
238: * Adds the specified errors and messages to the <documentState> element of the
239: * given EDL doc
240: * @param doc the EDL doc
241: * @param errors the list of error Strings
242: * @param messages the list of message Strings
243: */
244: public static void addErrorsAndMessagesToDocument(Document doc,
245: List errors, List messages) {
246: Node documentState = EDLXmlUtils.getDocumentStateElement(doc);
247: Iterator it = errors.iterator();
248: while (it.hasNext()) {
249: Element error = doc.createElement("error");
250: error.appendChild(doc.createTextNode(it.next().toString()));
251: documentState.appendChild(error);
252: }
253: it = messages.iterator();
254: while (it.hasNext()) {
255: Element error = doc.createElement("message");
256: error.appendChild(doc.createTextNode(it.next().toString()));
257: documentState.appendChild(error);
258: }
259: }
260:
261: }
|