001    /**
002     * Copyright 2005-2013 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.kuali.rice.krad.util.GlobalVariables;
027    import org.w3c.dom.Document;
028    import org.w3c.dom.Element;
029    import org.w3c.dom.Node;
030    import org.w3c.dom.NodeList;
031    
032    import javax.xml.parsers.DocumentBuilderFactory;
033    import javax.xml.transform.Templates;
034    import javax.xml.xpath.XPathFactory;
035    import java.util.Iterator;
036    import java.util.LinkedHashMap;
037    import 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     */
047    public 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    }