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