001: package edu.iu.uis.eden.xml;
002:
003: import java.io.InputStream;
004:
005: import javax.xml.parsers.DocumentBuilder;
006: import javax.xml.parsers.DocumentBuilderFactory;
007: import javax.xml.parsers.ParserConfigurationException;
008: import javax.xml.transform.TransformerException;
009: import javax.xml.xpath.XPath;
010: import javax.xml.xpath.XPathConstants;
011: import javax.xml.xpath.XPathExpressionException;
012: import javax.xml.xpath.XPathFactory;
013:
014: import org.apache.log4j.Logger;
015: import org.w3c.dom.Document;
016: import org.w3c.dom.Element;
017: import org.w3c.dom.Node;
018: import org.w3c.dom.NodeList;
019:
020: import edu.iu.uis.eden.EdenConstants;
021: import edu.iu.uis.eden.WorkflowServiceErrorException;
022: import edu.iu.uis.eden.WorkflowServiceErrorImpl;
023: import edu.iu.uis.eden.edl.EDocLiteStyle;
024: import edu.iu.uis.eden.edl.StyleService;
025: import edu.iu.uis.eden.user.WorkflowUser;
026: import edu.iu.uis.eden.util.XmlHelper;
027:
028: /**
029: * Parser for Style content type, managed by StyleService
030: * @author Aaron Hamid (arh14 at cornell dot edu)
031: */
032: public class StyleXmlParser {
033: private static final Logger LOG = Logger
034: .getLogger(StyleXmlParser.class);
035:
036: private static ThreadLocal DOCUMENT_BUILDER = new ThreadLocal() {
037: protected Object initialValue() {
038: try {
039: return DocumentBuilderFactory.newInstance()
040: .newDocumentBuilder();
041: } catch (ParserConfigurationException pce) {
042: // well folks, there is not much we can do if we get a ParserConfigurationException
043: // so might as well isolate the evilness here, and just balk if this occurs
044: String message = "Error obtaining document builder";
045: LOG.error(message, pce);
046: return new RuntimeException(message, pce);
047: }
048: }
049: };
050:
051: /**
052: * Returns a valid DocumentBuilder
053: * @return a valid DocumentBuilder
054: */
055: private static DocumentBuilder getDocumentBuilder() {
056: return (DocumentBuilder) DOCUMENT_BUILDER.get();
057: }
058:
059: public static void loadXml(StyleService styleService,
060: InputStream inputStream, WorkflowUser user) {
061: DocumentBuilder db = getDocumentBuilder();
062: XPath xpath = XPathFactory.newInstance().newXPath();
063: Document doc;
064: // parse and save EDocLiteDefinition, EDocLiteStyle, or EDocLiteAssociation xml from to-be-determined XML format
065: //try {
066: try {
067: doc = db.parse(inputStream);
068: } catch (Exception e) {
069: throw generateException("Error parsing Style XML file", e);
070: }
071: /*try {
072: LOG.info(XmlHelper.writeNode(doc.getFirstChild(), true));
073: } catch (TransformerException e) {
074: LOG.warn("Error displaying document");
075: }*/
076:
077: NodeList styles;
078: try {
079: styles = (NodeList) xpath.evaluate("//"
080: + XmlConstants.STYLE_STYLES, doc.getFirstChild(),
081: XPathConstants.NODESET);
082: } catch (XPathExpressionException e) {
083: throw generateException(
084: "Error evaluating XPath expression", e);
085: }
086:
087: LOG.info("Styles: " + styles);
088: for (int i = 0; i < styles.getLength(); i++) {
089: Node edl = styles.item(i);
090: NodeList children = edl.getChildNodes();
091: for (int j = 0; j < children.getLength(); j++) {
092: Node node = children.item(j);
093: if (node.getNodeType() == Node.ELEMENT_NODE) {
094: Element e = (Element) node;
095: if (XmlConstants.STYLE_STYLE.equals(node
096: .getNodeName())) {
097: LOG.debug("Digesting style: "
098: + e.getAttribute("name"));
099: EDocLiteStyle style = parseStyle(e);
100: styleService.saveStyle(style);
101: }
102: }
103: }
104: }
105: //} catch (Exception e) {
106: // throw generateException("Error parsing EDocLite XML file", e);
107: //}
108: }
109:
110: private static WorkflowServiceErrorException generateException(
111: String error, Throwable cause) {
112: WorkflowServiceErrorException wsee = new WorkflowServiceErrorException(
113: error, new WorkflowServiceErrorImpl(error,
114: EdenConstants.XML_FILE_PARSE_ERROR));
115: if (cause != null) {
116: wsee.initCause(cause);
117: }
118: return wsee;
119: }
120:
121: /**
122: * Parses an EDocLiteStyle
123: *
124: * @param e
125: * element to parse
126: * @return an EDocLiteStyle
127: */
128: private static EDocLiteStyle parseStyle(Element e) {
129: String name = e.getAttribute("name");
130: if (name == null || name.length() == 0) {
131: throw generateMissingAttribException(
132: XmlConstants.STYLE_STYLE, "name");
133: }
134: EDocLiteStyle style = new EDocLiteStyle();
135: style.setName(name);
136: Element stylesheet = null;
137: NodeList children = e.getChildNodes();
138: for (int i = 0; i < children.getLength(); i++) {
139: Node child = children.item(i);
140: /*
141: * LOG.debug("NodeName: " + child.getNodeName()); LOG.debug("LocalName: " + child.getLocalName()); LOG.debug("Prefix: " + child.getPrefix()); LOG.debug("NS URI: " + child.getNamespaceURI());
142: */
143: if (child.getNodeType() == Node.ELEMENT_NODE
144: && "xsl:stylesheet".equals(child.getNodeName())) {
145: stylesheet = (Element) child;
146: break;
147: }
148: }
149: if (stylesheet == null) {
150: throw generateMissingChildException(
151: XmlConstants.STYLE_STYLE, "xsl:stylesheet");
152: }
153: try {
154: style.setXmlContent(XmlHelper.writeNode(stylesheet, true));
155: } catch (TransformerException te) {
156: throw generateSerializationException(
157: XmlConstants.STYLE_STYLE, te);
158: }
159: return style;
160: }
161:
162: private static WorkflowServiceErrorException generateMissingAttribException(
163: String element, String attrib) {
164: return generateException(
165: "Style '" + element + "' element must contain a '"
166: + attrib + "' attribute", null);
167: }
168:
169: private static WorkflowServiceErrorException generateMissingChildException(
170: String element, String child) {
171: return generateException("Style '" + element
172: + "' element must contain a '" + child
173: + "' child element", null);
174: }
175:
176: private static WorkflowServiceErrorException generateSerializationException(
177: String element, TransformerException cause) {
178: return generateException("Error serializing Style '" + element
179: + "' element", cause);
180: }
181: }
|