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