001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.edl.impl;
017
018 import org.apache.log4j.Logger;
019 import org.kuali.rice.core.api.util.xml.XmlHelper;
020 import org.kuali.rice.core.api.util.xml.XmlJotter;
021 import org.kuali.rice.edl.impl.bo.EDocLiteAssociation;
022 import org.kuali.rice.edl.impl.service.EDocLiteService;
023 import org.kuali.rice.edl.impl.service.EdlServiceLocator;
024 import org.kuali.rice.kew.api.WorkflowRuntimeException;
025 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
026 import org.w3c.dom.Document;
027 import org.w3c.dom.Element;
028 import org.w3c.dom.Node;
029 import org.w3c.dom.NodeList;
030
031 import javax.xml.parsers.DocumentBuilderFactory;
032 import javax.xml.transform.Templates;
033 import java.util.Iterator;
034 import java.util.LinkedHashMap;
035 import java.util.Map;
036
037
038 /**
039 * Creates EDL controllers. The parsed config is a definition name related to
040 * a Map containing config element and their associated class.
041 *
042 * @author Kuali Rice Team (rice.collab@kuali.org)
043 *
044 */
045 public final class EDLControllerFactory {
046
047 private EDLControllerFactory() {
048 throw new UnsupportedOperationException("do not call");
049 }
050
051 private static final Logger LOG = Logger.getLogger(EDLControllerFactory.class);
052
053 public static EDLController createEDLController(EDocLiteAssociation edlAssociation, EDLGlobalConfig edlGlobalConfig) {
054 EDLController edlController = new EDLController();
055 edlController.setEdocLiteAssociation(edlAssociation);
056
057 try {
058 edlController.setEdlGlobalConfig(edlGlobalConfig);
059 edlController.setDefaultDOM(getDefaultDOM(edlAssociation));
060 loadConfigProcessors(edlController, edlGlobalConfig);
061 loadPreProcessors(edlController, edlGlobalConfig);
062 loadPostProcessor(edlController, edlGlobalConfig);
063 loadStateComponents(edlController, edlGlobalConfig);
064 loadStyle(edlController);
065
066 } catch (Exception e) {
067 String edl = null;
068 if (edlAssociation != null) {
069 edl = edlAssociation.getEdlName();
070 }
071 String message = "Error creating controller for EDL" + (edl == null ? "" : ": " + edl);
072 LOG.error(message, e);
073 throw new WorkflowRuntimeException("Problems creating controller for EDL: " + edl, e);
074 }
075
076 return edlController;
077 }
078
079 public static EDLController createEDLController(EDocLiteAssociation edlAssociation, EDLGlobalConfig edlGlobalConfig, DocumentRouteHeaderValue document) {
080 EDLController edlController = createEDLController(edlAssociation, edlGlobalConfig);
081 try {
082 Document defaultDom = edlController.getDefaultDOM();
083 Document documentDom = XmlHelper.readXml(document.getDocContent());
084 // get the data node and import it into our default DOM
085 Element documentData = (Element) documentDom.getElementsByTagName(EDLXmlUtils.DATA_E).item(0);
086 if (documentData != null) {
087 Element defaultDomEDL = EDLXmlUtils.getEDLContent(defaultDom, false);
088 Element defaultDomData = (Element) defaultDomEDL.getElementsByTagName(EDLXmlUtils.DATA_E).item(0);
089 defaultDomEDL.replaceChild(defaultDom.importNode(documentData, true), defaultDomData);
090 }
091 if (LOG.isDebugEnabled()) {
092 LOG.debug("Created default Node from document id " + document.getDocumentId() + " content " + XmlJotter.jotNode(defaultDom));
093 }
094 } catch (Exception e) {
095 throw new WorkflowRuntimeException("Problems creating controller for EDL " + edlAssociation.getEdlName() + " document " + document.getDocumentId(), e);
096 }
097 return edlController;
098 }
099
100 private static synchronized void loadStyle(EDLController edlController) throws Exception {
101 EDocLiteService edlService = getEDLService();
102 final Templates styleSheet = edlService.getStyleAsTranslet(edlController.getEdocLiteAssociation().getStyle());
103 edlController.setStyle(styleSheet);
104 }
105
106 private static synchronized void loadPreProcessors(EDLController edlController, EDLGlobalConfig edlGlobalConfig) {
107 edlController.setPreProcessors(cloneConfigMap(edlGlobalConfig.getPreProcessors(), edlController.getDefaultDOM()));
108 }
109
110 private static synchronized void loadPostProcessor(EDLController edlController, EDLGlobalConfig edlGlobalConfig) {
111 edlController.setPostProcessors(cloneConfigMap(edlGlobalConfig.getPostProcessors(), edlController.getDefaultDOM()));
112 }
113
114 private static synchronized void loadStateComponents(EDLController edlController, EDLGlobalConfig edlGlobalConfig) {
115 edlController.setStateComponents(cloneConfigMap(edlGlobalConfig.getStateComponents(), edlController.getDefaultDOM()));
116 }
117
118 private static synchronized void loadConfigProcessors(final EDLController edlController, final EDLGlobalConfig edlGlobalConfig) throws Exception {
119 EDocLiteAssociation edlAssociation = edlController.getEdocLiteAssociation();
120 // these are classes mapped to the conf element from the edlconfig.
121 Document document = getEDLService().getDefinitionXml(edlAssociation);
122 Element definitionElement = (Element) document.getFirstChild();
123
124 Map configProcessorMappings = new LinkedHashMap();
125 edlController.setEdlGlobalConfig(edlGlobalConfig);
126 NodeList edlDefinitionNodes = definitionElement.getChildNodes();
127 for (int i = 0; i < edlDefinitionNodes.getLength(); i++) {
128 Node definitionNode = edlDefinitionNodes.item(i);
129 Class configProcessorClass = edlGlobalConfig.getConfigProcessor(definitionNode);
130 if (configProcessorClass != null) {
131 configProcessorMappings.put(definitionNode, configProcessorClass);
132 }
133 }
134 edlController.setConfigProcessors(cloneConfigMap(configProcessorMappings, edlController.getDefaultDOM()));
135 }
136
137 private static synchronized Map cloneConfigMap(Map configMap, Document defaultDom) {
138 Map tempConfigProcessors = new LinkedHashMap();
139 for (Iterator iter = configMap.entrySet().iterator(); iter.hasNext();) {
140 Map.Entry configProcessorMapping = (Map.Entry) iter.next();
141 tempConfigProcessors.put(defaultDom.importNode((Node)configProcessorMapping.getKey(), true), configProcessorMapping.getValue());
142 }
143 return tempConfigProcessors;
144 }
145
146 private static EDocLiteService getEDLService() {
147 return EdlServiceLocator.getEDocLiteService();
148 }
149
150 private static Document getDefaultDOM(EDocLiteAssociation edlAssociation) throws Exception {
151 Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
152 Element rootElement = dom.createElement("documentContent"); // this is a
153 // throwback
154 // to some
155 // original
156 // madness
157 // to get EDL routing over a year ago we need to look into this being
158 // eliminated.
159 dom.appendChild(rootElement);
160 Element edlContentElement = EDLXmlUtils.getEDLContent(dom, true);
161 EDLXmlUtils.getDataFromEDLDocument(edlContentElement, true);
162
163 // get the data element that was just created ***jitrue***
164 Element edlData = EDLXmlUtils.getChildElement(edlContentElement, EDLXmlUtils.DATA_E);
165 // set edlName attribute on data element of default DOM ***jitrue***
166 edlData.setAttribute("edlName", edlAssociation.getEdlName());
167
168 return dom;
169 }
170 }