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.routeheader;
018:
019: import java.io.BufferedReader;
020: import java.io.IOException;
021: import java.io.ObjectInputStream;
022: import java.io.Serializable;
023: import java.io.StringReader;
024:
025: import javax.xml.parsers.DocumentBuilder;
026: import javax.xml.parsers.DocumentBuilderFactory;
027: import javax.xml.parsers.ParserConfigurationException;
028:
029: import org.w3c.dom.Document;
030: import org.w3c.dom.Element;
031: import org.w3c.dom.Node;
032: import org.w3c.dom.NodeList;
033: import org.xml.sax.InputSource;
034: import org.xml.sax.SAXException;
035:
036: import edu.iu.uis.eden.EdenConstants;
037: import edu.iu.uis.eden.engine.RouteContext;
038: import edu.iu.uis.eden.exception.InvalidXmlException;
039: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
040: import edu.iu.uis.eden.util.Utilities;
041:
042: /**
043: * Standard implementation of {@link DocumentContent} which nows hows to parse a
044: * String that it's constructed with into content with the application,
045: * attribute, and searchable content sections.
046: *
047: * @author ewestfal
048: */
049: public class StandardDocumentContent implements DocumentContent,
050: Serializable {
051:
052: private static final long serialVersionUID = -3189330007364191220L;
053:
054: private String docContent;
055:
056: private transient Document document;
057:
058: private transient Element applicationContent;
059:
060: private transient Element attributeContent;
061:
062: private transient Element searchableContent;
063:
064: private RouteContext routeContext;
065:
066: public StandardDocumentContent(String docContent)
067: throws InvalidXmlException {
068: this (docContent, null);
069: }
070:
071: public StandardDocumentContent(String docContent,
072: RouteContext routeContext) throws InvalidXmlException {
073: this .routeContext = routeContext;
074: initialize(docContent, routeContext);
075: }
076:
077: private void initialize(String docContent, RouteContext routeContext)
078: throws InvalidXmlException {
079: if (Utilities.isEmpty(docContent)) {
080: this .docContent = "";
081: this .document = null;
082: } else {
083: try {
084: this .docContent = docContent;
085: this .document = parseDocContent(docContent);
086: extractElements(this .document);
087: } catch (IOException e) {
088: throw new InvalidXmlException(
089: "I/O Error when attempting to parse document content.",
090: e);
091: } catch (SAXException e) {
092: throw new InvalidXmlException(
093: "XML parse error when attempting to parse document content.",
094: e);
095: } catch (ParserConfigurationException e) {
096: throw new InvalidXmlException(
097: "XML parser configuration error when attempting to parse document content.",
098: e);
099: }
100: }
101: }
102:
103: private Document parseDocContent(String docContent)
104: throws IOException, SAXException,
105: ParserConfigurationException {
106: DocumentBuilder documentBuilder = DocumentBuilderFactory
107: .newInstance().newDocumentBuilder();
108: return documentBuilder.parse(new InputSource(
109: new BufferedReader(new StringReader(docContent))));
110: }
111:
112: private void extractElements(Document document) {
113: // this handles backward compatibility in document content
114: if (!document.getDocumentElement().getNodeName().equals(
115: EdenConstants.DOCUMENT_CONTENT_ELEMENT)) {
116: // if the root element is the flexdoc element (pre Workflow 2.0)
117: // then designate that as attribute content
118: if (document.getDocumentElement().getNodeName().equals(
119: EdenConstants.FLEXDOC_ELEMENT)) {
120: attributeContent = document.getDocumentElement();
121: } else {
122: applicationContent = document.getDocumentElement();
123: }
124: } else {
125: NodeList nodes = document.getDocumentElement()
126: .getChildNodes();
127: for (int index = 0; index < nodes.getLength(); index++) {
128: Node node = nodes.item(index);
129: if (node.getNodeType() == Node.ELEMENT_NODE
130: && node
131: .getNodeName()
132: .equals(
133: EdenConstants.APPLICATION_CONTENT_ELEMENT)) {
134: int numChildElements = 0;
135: for (int childIndex = 0; childIndex < node
136: .getChildNodes().getLength(); childIndex++) {
137: Node child = (Node) node.getChildNodes().item(
138: childIndex);
139: if (child.getNodeType() == Node.ELEMENT_NODE) {
140: applicationContent = (Element) child;
141: numChildElements++;
142: }
143: }
144: // TODO can we have application content without a root node?
145: if (numChildElements > 1) {
146: applicationContent = (Element) node;
147: }
148: } else if (node.getNodeType() == Node.ELEMENT_NODE
149: && node
150: .getNodeName()
151: .equals(
152: EdenConstants.ATTRIBUTE_CONTENT_ELEMENT)) {
153: attributeContent = (Element) node;
154: } else if (node.getNodeType() == Node.ELEMENT_NODE
155: && node
156: .getNodeName()
157: .equals(
158: EdenConstants.SEARCHABLE_CONTENT_ELEMENT)) {
159: searchableContent = (Element) node;
160: }
161: }
162: }
163: }
164:
165: public Element getApplicationContent() {
166: return applicationContent;
167: }
168:
169: public Element getAttributeContent() {
170: return attributeContent;
171: }
172:
173: public String getDocContent() {
174: return docContent;
175: }
176:
177: public Document getDocument() {
178: return document;
179: }
180:
181: public Element getSearchableContent() {
182: return searchableContent;
183: }
184:
185: public RouteContext getRouteContext() {
186: return this .routeContext;
187: }
188:
189: private void readObject(ObjectInputStream ais) throws IOException,
190: ClassNotFoundException {
191: ais.defaultReadObject();
192: try {
193: initialize(this .docContent, this .routeContext);
194: } catch (Exception e) {
195: throw new WorkflowRuntimeException(e);
196: }
197: }
198:
199: }
|