1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
44
45
46 public class StyleXmlParserImpl implements StyleXmlParser {
47 private static final Logger LOG = Logger.getLogger(StyleXmlParserImpl.class);
48
49 private StyleService styleService;
50
51 private static ThreadLocal<DocumentBuilder> DOCUMENT_BUILDER = new ThreadLocal<DocumentBuilder>() {
52 protected DocumentBuilder initialValue() {
53 try {
54 return DocumentBuilderFactory.newInstance().newDocumentBuilder();
55 } catch (ParserConfigurationException pce) {
56
57
58 String message = "Error obtaining document builder";
59 LOG.error(message, pce);
60 throw new RuntimeException(message, pce);
61 }
62 }
63 };
64
65
66
67
68
69 private static DocumentBuilder getDocumentBuilder() {
70 return (DocumentBuilder) DOCUMENT_BUILDER.get();
71 }
72
73 public void loadXml(InputStream inputStream, String principalId) {
74 List<Style> styles = parseStyles(inputStream);
75 for (Style style : styles) {
76 styleService.saveStyle(style);
77 }
78 }
79
80 public List<Style> parseStyles(InputStream inputStream) {
81 DocumentBuilder db = getDocumentBuilder();
82 XPath xpath = XPathFactory.newInstance().newXPath();
83 Document doc;
84 try {
85 doc = db.parse(inputStream);
86 } catch (Exception e) {
87 throw generateException("Error parsing Style XML file", e);
88 }
89 NodeList styles;
90 try {
91 styles = (NodeList) xpath.evaluate("//" + XmlConstants.STYLE_STYLES, doc.getFirstChild(), XPathConstants.NODESET);
92 } catch (XPathExpressionException e) {
93 throw generateException("Error evaluating XPath expression", e);
94 }
95
96 List<Style> parsedStyles = new ArrayList<Style>();
97 for (int i = 0; i < styles.getLength(); i++) {
98 Node edl = styles.item(i);
99 NodeList children = edl.getChildNodes();
100 for (int j = 0; j < children.getLength(); j++) {
101 Node node = children.item(j);
102 if (node.getNodeType() == Node.ELEMENT_NODE) {
103 Element e = (Element) node;
104 if (XmlConstants.STYLE_STYLE.equals(node.getNodeName())) {
105 LOG.debug("Digesting style: " + e.getAttribute("name"));
106 Style.Builder styleBuilder = parseStyle(e);
107 parsedStyles.add(styleBuilder.build());
108 }
109 }
110 }
111 }
112 return parsedStyles;
113 }
114
115
116
117
118
119
120
121
122 private static Style.Builder parseStyle(Element e) {
123 String name = e.getAttribute("name");
124 if (name == null || name.length() == 0) {
125 throw generateMissingAttribException(XmlConstants.STYLE_STYLE, "name");
126 }
127 Style.Builder style = Style.Builder.create(name);
128 Element stylesheet = null;
129 NodeList children = e.getChildNodes();
130 for (int i = 0; i < children.getLength(); i++) {
131 Node child = children.item(i);
132 if (child.getNodeType() == Node.ELEMENT_NODE && "xsl:stylesheet".equals(child.getNodeName())) {
133 stylesheet = (Element) child;
134 break;
135 }
136 }
137 if (stylesheet == null) {
138 throw generateMissingChildException(XmlConstants.STYLE_STYLE, "xsl:stylesheet");
139 }
140 try {
141 style.setXmlContent(XmlJotter.jotNode(stylesheet, true));
142 } catch (XmlException te) {
143 throw generateSerializationException(XmlConstants.STYLE_STYLE, te);
144 }
145 return style;
146 }
147
148 private static XmlIngestionException generateMissingAttribException(String element, String attrib) {
149 return generateException("Style '" + element + "' element must contain a '" + attrib + "' attribute", null);
150 }
151
152 private static XmlIngestionException generateMissingChildException(String element, String child) {
153 return generateException("Style '" + element + "' element must contain a '" + child + "' child element", null);
154 }
155
156 private static XmlIngestionException generateSerializationException(String element, XmlException cause) {
157 return generateException("Error serializing Style '" + element + "' element", cause);
158 }
159
160 private static XmlIngestionException generateException(String error, Throwable cause) {
161 return new XmlIngestionException(error, cause);
162 }
163
164 public void setStyleService(StyleService styleService) {
165 this.styleService = styleService;
166 }
167
168 }