1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.edl.impl.service.impl;
17
18 import org.apache.log4j.Logger;
19 import org.kuali.rice.core.api.config.property.ConfigContext;
20 import org.kuali.rice.core.api.impex.ExportDataSet;
21 import org.kuali.rice.core.api.impex.xml.XmlIngestionException;
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.kuali.rice.edl.impl.EDLController;
26 import org.kuali.rice.edl.impl.EDLControllerFactory;
27 import org.kuali.rice.edl.impl.EDLGlobalConfig;
28 import org.kuali.rice.edl.impl.EDLGlobalConfigFactory;
29 import org.kuali.rice.edl.impl.EDLXmlUtils;
30 import org.kuali.rice.edl.impl.bo.EDocLiteAssociation;
31 import org.kuali.rice.edl.impl.bo.EDocLiteDefinition;
32 import org.kuali.rice.edl.impl.dao.EDocLiteDAO;
33 import org.kuali.rice.edl.impl.service.EDocLiteService;
34 import org.kuali.rice.edl.impl.xml.EDocLiteXmlParser;
35 import org.kuali.rice.edl.impl.xml.export.EDocLiteXmlExporter;
36 import org.kuali.rice.kew.api.WorkflowRuntimeException;
37 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
38 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
39 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
40 import org.kuali.rice.kew.rule.bo.RuleAttribute;
41 import org.kuali.rice.kew.service.KEWServiceLocator;
42 import org.kuali.rice.kew.api.KewApiConstants;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47 import org.xml.sax.InputSource;
48
49 import javax.xml.parsers.DocumentBuilderFactory;
50 import javax.xml.transform.Templates;
51 import javax.xml.transform.TransformerConfigurationException;
52 import javax.xml.xpath.XPath;
53 import javax.xml.xpath.XPathConstants;
54 import javax.xml.xpath.XPathExpressionException;
55 import javax.xml.xpath.XPathFactory;
56 import java.io.InputStream;
57 import java.io.StringReader;
58 import java.util.ArrayList;
59 import java.util.Collection;
60 import java.util.Iterator;
61 import java.util.List;
62 import java.util.concurrent.atomic.AtomicReference;
63
64
65
66
67
68
69 public class EDocLiteServiceImpl implements EDocLiteService {
70 private static final Logger LOG = Logger.getLogger(EDocLiteServiceImpl.class);
71
72 private final AtomicReference<EDLGlobalConfig> edlGlobalConfig = new AtomicReference<EDLGlobalConfig>(null);
73
74
75
76 private EDocLiteDAO dao;
77
78
79
80 private StyleService styleService;
81
82
83
84 public void setEDocLiteDAO(EDocLiteDAO dao) {
85 this.dao = dao;
86 }
87
88 public EDLController getEDLControllerUsingEdlName(String edlName) {
89 EDocLiteAssociation edlAssociation = this.dao.getEDocLiteAssociation(edlName);
90 if (edlAssociation == null) {
91 throw new WorkflowRuntimeException("No document association active for EDL: " + edlName);
92 }
93 initEDLGlobalConfig();
94 return EDLControllerFactory.createEDLController(edlAssociation, edlGlobalConfig.get());
95 }
96
97 public EDLController getEDLControllerUsingDocumentId(String documentId) {
98 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
99 String edlName = document.getAppDocId();
100 if (edlName == null) {
101 edlName = document.getDocumentType().getName();
102 }
103 EDocLiteAssociation edlAssociation = this.dao.getEDocLiteAssociation(edlName);
104 if (edlAssociation == null) {
105 throw new WorkflowRuntimeException("No document association active for EDL: " + edlName);
106 }
107 initEDLGlobalConfig();
108 return EDLControllerFactory.createEDLController(edlAssociation, edlGlobalConfig.get(), document);
109 }
110
111 @Override
112 public void initEDLGlobalConfig() {
113 edlGlobalConfig.compareAndSet(null, getEDLGlobalConfig());
114 }
115
116 private EDLGlobalConfig getEDLGlobalConfig() {
117 try {
118 return EDLGlobalConfigFactory.createEDLGlobalConfig(ConfigContext.getCurrentContextConfig().getEDLConfigLocation());
119 } catch (Exception e) {
120 throw new WorkflowRuntimeException(e);
121 }
122 }
123
124 public Document getDefinitionXml(EDocLiteAssociation edlAssociation) {
125 try {
126 Document def = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(
127 new StringReader(getEDocLiteDefinition(edlAssociation.getDefinition()).getXmlContent())));
128 return def;
129 } catch (Exception e) {
130 throw new WorkflowRuntimeException("Caught exception parsing EDL definition " + edlAssociation.getDefinition(), e);
131 }
132 }
133
134 private static XmlIngestionException generateException(String error, Throwable cause) {
135 return new XmlIngestionException(error, cause);
136 }
137
138 private static XmlIngestionException generateMissingAttribException(String element, String attrib) {
139 return generateException("EDocLite '" + element + "' element must contain a '" + attrib + "' attribute", null);
140 }
141
142 private static XmlIngestionException generateMissingChildException(String element, String child) {
143 return generateException("EDocLite '" + element + "' element must contain a '" + child + "' child element", null);
144 }
145
146 private static XmlIngestionException generateSerializationException(String element, XmlException cause) {
147 return generateException("Error serializing EDocLite '" + element + "' element", cause);
148 }
149
150
151
152
153
154
155
156
157 private static Document parse(InputStream stream) {
158 try {
159 return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
160 } catch (Exception e) {
161 WorkflowServiceErrorException wsee = new WorkflowServiceErrorException("Error parsing EDocLite XML file", new WorkflowServiceErrorImpl("Error parsing XML file.", KewApiConstants.XML_FILE_PARSE_ERROR));
162 wsee.initCause(e);
163 throw wsee;
164 }
165 }
166
167
168
169
170
171
172
173
174 private static EDocLiteAssociation parseEDocLiteAssociation(Element e) {
175 String docType = EDLXmlUtils.getChildElementTextValue(e, "docType");
176 if (docType == null) {
177 throw generateMissingChildException("association", "docType");
178 }
179 EDocLiteAssociation assoc = new EDocLiteAssociation();
180 assoc.setEdlName(docType);
181 assoc.setDefinition(EDLXmlUtils.getChildElementTextValue(e, "definition"));
182 assoc.setStyle(EDLXmlUtils.getChildElementTextValue(e, "style"));
183 assoc.setActiveInd(Boolean.valueOf(EDLXmlUtils.getChildElementTextValue(e, "active")));
184 return assoc;
185 }
186
187
188
189
190
191
192
193
194 private static EDocLiteDefinition parseEDocLiteDefinition(Element e) {
195 EDocLiteDefinition def = new EDocLiteDefinition();
196 String name = e.getAttribute("name");
197 if (name == null || name.length() == 0) {
198 throw generateMissingAttribException(EDLXmlUtils.EDL_E, "name");
199 }
200 def.setName(name);
201
202
203
204
205 XPath xpath = XPathFactory.newInstance().newXPath();
206 NodeList fields;
207 try {
208 fields = (NodeList) xpath.evaluate("fieldDef", e, XPathConstants.NODESET);
209 } catch (XPathExpressionException xpee) {
210 throw new RuntimeException("Invalid EDocLiteDefinition", xpee);
211 }
212
213 if (fields != null) {
214 Collection invalidAttributes = new ArrayList(5);
215 for (int i = 0; i < fields.getLength(); i++) {
216 Node node = (Node) fields.item(i);
217
218 if (node instanceof Element) {
219 Element field = (Element) node;
220
221 String fieldName = field.getAttribute("name");
222 String attribute = field.getAttribute("attributeName");
223 if (attribute != null && attribute.length() > 0) {
224 RuleAttribute ruleAttrib = KEWServiceLocator.getRuleAttributeService().findByName(attribute);
225 if (ruleAttrib == null) {
226 LOG.error("Invalid attribute referenced in EDocLite definition: " + attribute);
227 invalidAttributes.add("Attribute '" + attribute + "' referenced in field '" + fieldName + "' not found");
228 }
229 }
230 }
231 }
232 if (invalidAttributes.size() > 0) {
233 LOG.error("Invalid attributes referenced in EDocLite definition");
234 StringBuffer message = new StringBuffer("EDocLite definition contains references to non-existent attributes;\n");
235 Iterator it = invalidAttributes.iterator();
236 while (it.hasNext()) {
237 message.append(it.next());
238 message.append("\n");
239 }
240 throw new RuntimeException(message.toString());
241 }
242 }
243
244 try {
245 def.setXmlContent(XmlJotter.jotNode(e, true));
246 } catch (XmlException te) {
247 throw generateSerializationException(EDLXmlUtils.EDL_E, te);
248 }
249 return def;
250 }
251
252
253
254 public void saveEDocLiteDefinition(EDocLiteDefinition data) {
255 EDocLiteDefinition existingData = getEDocLiteDefinition(data.getName());
256 if (existingData != null) {
257 existingData.setActiveInd(Boolean.FALSE);
258 dao.saveEDocLiteDefinition(existingData);
259 }
260
261 if (data.getActiveInd() == null) {
262 data.setActiveInd(Boolean.TRUE);
263 }
264 dao.saveEDocLiteDefinition(data);
265 }
266
267 public void saveEDocLiteAssociation(EDocLiteAssociation assoc) {
268 EDocLiteAssociation existingData = getEDocLiteAssociation(assoc.getEdlName());
269 if (existingData != null) {
270 existingData.setActiveInd(Boolean.FALSE);
271 dao.saveEDocLiteAssociation(existingData);
272 }
273
274 if (assoc.getActiveInd() == null) {
275 assoc.setActiveInd(Boolean.TRUE);
276 }
277 dao.saveEDocLiteAssociation(assoc);
278 }
279
280
281
282 public void saveEDocLiteDefinition(InputStream xml) {
283
284 EDocLiteDefinition data = parseEDocLiteDefinition(parse(xml).getDocumentElement());
285 saveEDocLiteDefinition(data);
286 }
287
288 public void saveEDocLiteAssociation(InputStream xml) {
289
290 EDocLiteAssociation assoc = parseEDocLiteAssociation(parse(xml).getDocumentElement());
291 saveEDocLiteAssociation(assoc);
292 }
293
294 public EDocLiteDefinition getEDocLiteDefinition(String definitionName) {
295 return dao.getEDocLiteDefinition(definitionName);
296 }
297
298 public EDocLiteAssociation getEDocLiteAssociation(String docTypeName) {
299 return dao.getEDocLiteAssociation(docTypeName);
300 }
301
302 public List getEDocLiteDefinitions() {
303 return dao.getEDocLiteDefinitions();
304 }
305
306 public List getEDocLiteAssociations() {
307 return dao.getEDocLiteAssociations();
308 }
309
310 public Templates getStyleAsTranslet(String name) throws TransformerConfigurationException {
311 if (name == null || "null".equals(name)) {
312 name = "Default";
313 }
314
315 return styleService.getStyleAsTranslet(name);
316 }
317
318 public List search(EDocLiteAssociation edocLite) {
319 return this.dao.search(edocLite);
320 }
321
322 public EDocLiteAssociation getEDocLiteAssociation(Long associationId) {
323 return dao.getEDocLiteAssociation(associationId);
324 }
325
326
327
328 public void loadXml(InputStream inputStream, String principalId) {
329 EDocLiteXmlParser.loadXml(inputStream, principalId);
330 }
331
332
333 public org.jdom.Element export(ExportDataSet dataSet) {
334 return new EDocLiteXmlExporter().export(dataSet);
335 }
336
337 @Override
338 public boolean supportPrettyPrint() {
339 return false;
340 }
341
342 public void setStyleService(StyleService styleService) {
343 this.styleService = styleService;
344 }
345
346 }