View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.coreservice.impl.style;
17  
18  import org.apache.log4j.Logger;
19  import org.kuali.rice.core.api.impex.xml.XmlConstants;
20  import org.kuali.rice.core.api.impex.xml.XmlIngestionException;
21  import org.kuali.rice.coreservice.api.style.Style;
22  import org.kuali.rice.coreservice.api.style.StyleService;
23  import org.kuali.rice.core.api.util.xml.XmlException;
24  import org.kuali.rice.core.api.util.xml.XmlJotter;
25  import org.w3c.dom.Document;
26  import org.w3c.dom.Element;
27  import org.w3c.dom.Node;
28  import org.w3c.dom.NodeList;
29  
30  import javax.xml.parsers.DocumentBuilder;
31  import javax.xml.parsers.DocumentBuilderFactory;
32  import javax.xml.parsers.ParserConfigurationException;
33  import javax.xml.xpath.XPath;
34  import javax.xml.xpath.XPathConstants;
35  import javax.xml.xpath.XPathExpressionException;
36  import javax.xml.xpath.XPathFactory;
37  import java.io.InputStream;
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  
42  /**
43   * Parser for Style content type, managed by StyleService
44   * @author Kuali Rice Team (rice.collab@kuali.org)
45   */
46  public class StyleXmlParserImpl implements StyleXmlParser {
47  	private static final Logger LOG = Logger.getLogger(StyleXmlParserImpl.class);
48  
49  	private StyleService styleService;
50  	
51      /**
52       * Returns a valid DocumentBuilder
53       * @return a valid DocumentBuilder
54       */
55      private static DocumentBuilder getDocumentBuilder() {
56          try {
57              return DocumentBuilderFactory.newInstance().newDocumentBuilder();
58          } catch (ParserConfigurationException pce) {
59              // well folks, there is not much we can do if we get a ParserConfigurationException
60              // so might as well isolate the evilness here, and just balk if this occurs
61              String message = "Error obtaining document builder";
62              LOG.error(message, pce);
63              throw new RuntimeException(message, pce);
64          }
65      }
66  
67      public void loadXml(InputStream inputStream, String principalId) {
68      	List<Style> styles = parseStyles(inputStream);
69      	for (Style style : styles) {
70      		styleService.saveStyle(style);
71      	}
72      }
73      
74      public List<Style> parseStyles(InputStream inputStream) {
75      	DocumentBuilder db = getDocumentBuilder();
76          XPath xpath = XPathFactory.newInstance().newXPath();
77          Document doc;
78          try {
79              doc = db.parse(inputStream);
80          } catch (Exception e) {
81              throw generateException("Error parsing Style XML file", e);
82          }
83          NodeList styles;
84          try {
85          	styles = (NodeList) xpath.evaluate("//" + XmlConstants.STYLE_STYLES, doc.getFirstChild(), XPathConstants.NODESET);
86          } catch (XPathExpressionException e) {
87          	throw generateException("Error evaluating XPath expression", e);
88          }
89  
90          List<Style> parsedStyles = new ArrayList<Style>();
91          for (int i = 0; i < styles.getLength(); i++) {
92          	Node edl = styles.item(i);
93          	NodeList children = edl.getChildNodes();
94          	for (int j = 0; j < children.getLength(); j++) {
95          		Node node = children.item(j);
96          		if (node.getNodeType() == Node.ELEMENT_NODE) {
97          			Element e = (Element) node;
98          			if (XmlConstants.STYLE_STYLE.equals(node.getNodeName())) {
99          				LOG.debug("Digesting style: " + e.getAttribute("name"));
100         				Style.Builder styleBuilder = parseStyle(e);
101         				parsedStyles.add(styleBuilder.build());
102         			}
103                 }
104             }
105         }
106         return parsedStyles;
107     }
108     
109     /**
110      * Parses an EDocLiteStyle
111      *
112      * @param e
113      *            element to parse
114      * @return an EDocLiteStyle
115      */
116     private static Style.Builder parseStyle(Element e) {
117         String name = e.getAttribute("name");
118         if (name == null || name.length() == 0) {
119             throw generateMissingAttribException(XmlConstants.STYLE_STYLE, "name");
120         }
121         Style.Builder style = Style.Builder.create(name);
122         Element stylesheet = null;
123         NodeList children = e.getChildNodes();
124         for (int i = 0; i < children.getLength(); i++) {
125             Node child = children.item(i);
126             if (child.getNodeType() == Node.ELEMENT_NODE && "xsl:stylesheet".equals(child.getNodeName())) {
127                 stylesheet = (Element) child;
128                 break;
129             }
130         }
131         if (stylesheet == null) {
132             throw generateMissingChildException(XmlConstants.STYLE_STYLE, "xsl:stylesheet");
133         }
134         try {
135             style.setXmlContent(XmlJotter.jotNode(stylesheet, true));
136         } catch (XmlException te) {
137             throw generateSerializationException(XmlConstants.STYLE_STYLE, te);
138         }
139         return style;
140     }
141 
142     private static XmlIngestionException generateMissingAttribException(String element, String attrib) {
143         return generateException("Style '" + element + "' element must contain a '" + attrib + "' attribute", null);
144     }
145 
146     private static XmlIngestionException generateMissingChildException(String element, String child) {
147         return generateException("Style '" + element + "' element must contain a '" + child + "' child element", null);
148     }
149 
150     private static XmlIngestionException generateSerializationException(String element, XmlException cause) {
151         return generateException("Error serializing Style '" + element + "' element", cause);
152     }
153     
154     private static XmlIngestionException generateException(String error, Throwable cause) {
155     	return new XmlIngestionException(error, cause);
156     }
157     
158     public void setStyleService(StyleService styleService) {
159     	this.styleService = styleService;
160     }
161 
162 }