Coverage Report - org.kuali.rice.edl.impl.service.impl.EDocLiteServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
EDocLiteServiceImpl
0%
0/124
0%
0/44
2.393
 
 1  
 /*
 2  
  * Copyright 2006-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.kuali.rice.edl.impl.service.impl;
 18  
 
 19  
 import java.io.InputStream;
 20  
 import java.io.StringReader;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Collection;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 
 26  
 import javax.xml.parsers.DocumentBuilderFactory;
 27  
 import javax.xml.transform.Templates;
 28  
 import javax.xml.transform.TransformerConfigurationException;
 29  
 import javax.xml.xpath.XPath;
 30  
 import javax.xml.xpath.XPathConstants;
 31  
 import javax.xml.xpath.XPathExpressionException;
 32  
 import javax.xml.xpath.XPathFactory;
 33  
 
 34  
 import org.apache.log4j.Logger;
 35  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 36  
 import org.kuali.rice.core.api.impex.ExportDataSet;
 37  
 import org.kuali.rice.core.api.impex.xml.XmlIngestionException;
 38  
 import org.kuali.rice.core.api.style.StyleService;
 39  
 import org.kuali.rice.core.util.xml.XmlException;
 40  
 import org.kuali.rice.core.util.xml.XmlJotter;
 41  
 import org.kuali.rice.edl.impl.EDLController;
 42  
 import org.kuali.rice.edl.impl.EDLControllerFactory;
 43  
 import org.kuali.rice.edl.impl.EDLGlobalConfig;
 44  
 import org.kuali.rice.edl.impl.EDLGlobalConfigFactory;
 45  
 import org.kuali.rice.edl.impl.EDLXmlUtils;
 46  
 import org.kuali.rice.edl.impl.bo.EDocLiteAssociation;
 47  
 import org.kuali.rice.edl.impl.bo.EDocLiteDefinition;
 48  
 import org.kuali.rice.edl.impl.dao.EDocLiteDAO;
 49  
 import org.kuali.rice.edl.impl.service.EDocLiteService;
 50  
 import org.kuali.rice.edl.impl.xml.EDocLiteXmlParser;
 51  
 import org.kuali.rice.edl.impl.xml.export.EDocLiteXmlExporter;
 52  
 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
 53  
 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
 54  
 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
 55  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 56  
 import org.kuali.rice.kew.rule.bo.RuleAttribute;
 57  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 58  
 import org.kuali.rice.kew.util.KEWConstants;
 59  
 import org.w3c.dom.Document;
 60  
 import org.w3c.dom.Element;
 61  
 import org.w3c.dom.Node;
 62  
 import org.w3c.dom.NodeList;
 63  
 import org.xml.sax.InputSource;
 64  
 
 65  
 
 66  
 /**
 67  
  * DAO-based EDocLiteService implementation
 68  
  *
 69  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 70  
  */
 71  0
 public class EDocLiteServiceImpl implements EDocLiteService {
 72  0
     private static final Logger LOG = Logger.getLogger(EDocLiteServiceImpl.class);
 73  
 
 74  
         private EDLGlobalConfig edlGlobalConfig;
 75  
     /**
 76  
      * The Spring-wired DAO bean
 77  
      */
 78  
     private EDocLiteDAO dao;
 79  
     /**
 80  
      * Spring wired StyleService bean
 81  
      */
 82  
     private StyleService styleService;
 83  
 
 84  
     // ---- Spring DAO setters
 85  
 
 86  
     public void setEDocLiteDAO(EDocLiteDAO dao) {
 87  0
         this.dao = dao;
 88  0
     }
 89  
 
 90  
     public EDLController getEDLControllerUsingEdlName(String edlName) {
 91  0
                 EDocLiteAssociation edlAssociation = this.dao.getEDocLiteAssociation(edlName);
 92  0
         if (edlAssociation == null) {
 93  0
             throw new WorkflowRuntimeException("No document association active for EDL: " + edlName);
 94  
         }
 95  0
                 if (edlGlobalConfig == null) {
 96  0
                         initEDLGlobalConfig();
 97  
                 }
 98  0
                 return EDLControllerFactory.createEDLController(edlAssociation, edlGlobalConfig);
 99  
         }
 100  
 
 101  
         public EDLController getEDLControllerUsingDocumentId(String documentId) {
 102  0
                 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
 103  0
                 String edlName = document.getAppDocId();//components working with workflow docs will need to know this, perhaps through a document utils.
 104  0
                 if (edlName == null) {
 105  0
                         edlName = document.getDocumentType().getName();
 106  
                 }
 107  0
                 EDocLiteAssociation edlAssociation = this.dao.getEDocLiteAssociation(edlName);
 108  0
         if (edlAssociation == null) {
 109  0
             throw new WorkflowRuntimeException("No document association active for EDL: " + edlName);
 110  
         }
 111  0
                 if (edlGlobalConfig == null) {
 112  0
                         initEDLGlobalConfig();
 113  
                 }
 114  0
                 return EDLControllerFactory.createEDLController(edlAssociation, edlGlobalConfig, document);
 115  
         }
 116  
 
 117  
         public void initEDLGlobalConfig() {
 118  
                 try {
 119  0
                         this.edlGlobalConfig = EDLGlobalConfigFactory.createEDLGlobalConfig(ConfigContext.getCurrentContextConfig().getEDLConfigLocation());
 120  0
                 } catch (Exception e) {
 121  0
                         throw new WorkflowRuntimeException(e);
 122  0
                 }
 123  0
         }
 124  
 
 125  
         public Document getDefinitionXml(EDocLiteAssociation edlAssociation) {
 126  
                 try {
 127  0
                         Document def = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(
 128  
                         new StringReader(getEDocLiteDefinition(edlAssociation.getDefinition()).getXmlContent())));
 129  0
                         return def;
 130  0
                 } catch (Exception e) {
 131  0
                         throw new WorkflowRuntimeException("Caught exception parsing EDL definition " + edlAssociation.getDefinition(), e);
 132  
                 }
 133  
         }
 134  
 
 135  
         private static XmlIngestionException generateException(String error, Throwable cause) {
 136  0
         return new XmlIngestionException(error, cause);
 137  
     }
 138  
 
 139  
     private static XmlIngestionException generateMissingAttribException(String element, String attrib) {
 140  0
         return generateException("EDocLite '" + element + "' element must contain a '" + attrib + "' attribute", null);
 141  
     }
 142  
 
 143  
     private static XmlIngestionException generateMissingChildException(String element, String child) {
 144  0
         return generateException("EDocLite '" + element + "' element must contain a '" + child + "' child element", null);
 145  
     }
 146  
 
 147  
     private static XmlIngestionException generateSerializationException(String element, XmlException cause) {
 148  0
         return generateException("Error serializing EDocLite '" + element + "' element", cause);
 149  
     }
 150  
 
 151  
     /**
 152  
      * Parses an arbitrary XML stream
 153  
      *
 154  
      * @param stream
 155  
      *            stream containing XML doc content
 156  
      * @return parsed Document object
 157  
      */
 158  
     private static Document parse(InputStream stream) {
 159  
         try {
 160  0
             return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
 161  0
         } catch (Exception e) {
 162  0
             WorkflowServiceErrorException wsee = new WorkflowServiceErrorException("Error parsing EDocLite XML file", new WorkflowServiceErrorImpl("Error parsing XML file.", KEWConstants.XML_FILE_PARSE_ERROR));
 163  0
             wsee.initCause(e);
 164  0
             throw wsee;
 165  
         }
 166  
     }
 167  
 
 168  
     /**
 169  
      * Parses an EDocLiteAssocation
 170  
      *
 171  
      * @param e
 172  
      *            element to parse
 173  
      * @return an EDocLiteAssocation
 174  
      */
 175  
     private static EDocLiteAssociation parseEDocLiteAssociation(Element e) {
 176  0
         String docType = EDLXmlUtils.getChildElementTextValue(e, "docType");
 177  0
         if (docType == null) {
 178  0
             throw generateMissingChildException("association", "docType");
 179  
         }
 180  0
         EDocLiteAssociation assoc = new EDocLiteAssociation();
 181  0
         assoc.setEdlName(docType);
 182  0
         assoc.setDefinition(EDLXmlUtils.getChildElementTextValue(e, "definition"));
 183  0
         assoc.setStyle(EDLXmlUtils.getChildElementTextValue(e, "style"));
 184  0
         assoc.setActiveInd(Boolean.valueOf(EDLXmlUtils.getChildElementTextValue(e, "active")));
 185  0
         return assoc;
 186  
     }
 187  
 
 188  
     /**
 189  
      * Parses an EDocLiteDefinition
 190  
      *
 191  
      * @param e
 192  
      *            element to parse
 193  
      * @return an EDocLiteDefinition
 194  
      */
 195  
     private static EDocLiteDefinition parseEDocLiteDefinition(Element e) {
 196  0
         EDocLiteDefinition def = new EDocLiteDefinition();
 197  0
         String name = e.getAttribute("name");
 198  0
         if (name == null || name.length() == 0) {
 199  0
             throw generateMissingAttribException(EDLXmlUtils.EDL_E, "name");
 200  
         }
 201  0
         def.setName(name);
 202  
 
 203  
         // do some validation to ensure that any attributes referenced actually exist
 204  
         // blow up if there is a problem
 205  
 
 206  0
         XPath xpath = XPathFactory.newInstance().newXPath();
 207  
         NodeList fields;
 208  
         try {
 209  0
             fields = (NodeList) xpath.evaluate("fieldDef", e, XPathConstants.NODESET);
 210  0
         } catch (XPathExpressionException xpee) {
 211  0
             throw new RuntimeException("Invalid EDocLiteDefinition", xpee);
 212  0
         }
 213  
 
 214  0
         if (fields != null) {
 215  0
             Collection invalidAttributes = new ArrayList(5);
 216  0
             for (int i = 0; i < fields.getLength(); i++) {
 217  0
                 Node node = (Node) fields.item(i);
 218  
                 // they should all be Element...
 219  0
                 if (node instanceof Element) {
 220  0
                     Element field = (Element) node;
 221  
                     // rely on XML validation to ensure this is present
 222  0
                     String fieldName = field.getAttribute("name");
 223  0
                     String attribute = field.getAttribute("attributeName");
 224  0
                     if (attribute != null && attribute.length() > 0) {
 225  0
                         RuleAttribute ruleAttrib = KEWServiceLocator.getRuleAttributeService().findByName(attribute);
 226  0
                         if (ruleAttrib == null) {
 227  0
                             LOG.error("Invalid attribute referenced in EDocLite definition: " + attribute);
 228  0
                             invalidAttributes.add("Attribute '" + attribute + "' referenced in field '" + fieldName + "' not found");
 229  
                         }
 230  
                     }
 231  
                 }
 232  
             }
 233  0
             if (invalidAttributes.size() > 0) {
 234  0
                 LOG.error("Invalid attributes referenced in EDocLite definition");
 235  0
                 StringBuffer message = new StringBuffer("EDocLite definition contains references to non-existent attributes;\n");
 236  0
                 Iterator it = invalidAttributes.iterator();
 237  0
                 while (it.hasNext()) {
 238  0
                     message.append(it.next());
 239  0
                     message.append("\n");
 240  
                 }
 241  0
                 throw new RuntimeException(message.toString());
 242  
             }
 243  
         }
 244  
 
 245  
         try {
 246  0
             def.setXmlContent(XmlJotter.jotNode(e, true));
 247  0
         } catch (XmlException te) {
 248  0
             throw generateSerializationException(EDLXmlUtils.EDL_E, te);
 249  0
         }
 250  0
         return def;
 251  
     }
 252  
 
 253  
     // ---- helper methods
 254  
 
 255  
     public void saveEDocLiteDefinition(EDocLiteDefinition data) {
 256  0
         EDocLiteDefinition existingData = getEDocLiteDefinition(data.getName());
 257  0
         if (existingData != null) {
 258  0
             existingData.setActiveInd(Boolean.FALSE);
 259  0
             dao.saveEDocLiteDefinition(existingData);
 260  
         }
 261  
         // if not specified (from xml), mark it as active
 262  0
         if (data.getActiveInd() == null) {
 263  0
             data.setActiveInd(Boolean.TRUE);
 264  
         }
 265  0
         dao.saveEDocLiteDefinition(data);
 266  0
         removeDefinitionFromCache(data.getName());
 267  0
     }
 268  
 
 269  
     public void saveEDocLiteAssociation(EDocLiteAssociation assoc) {
 270  0
         EDocLiteAssociation existingData = getEDocLiteAssociation(assoc.getEdlName());
 271  0
         if (existingData != null) {
 272  0
             existingData.setActiveInd(Boolean.FALSE);
 273  0
             dao.saveEDocLiteAssociation(existingData);
 274  
         }
 275  
         // if not specified (from xml), mark it as active
 276  0
         if (assoc.getActiveInd() == null) {
 277  0
             assoc.setActiveInd(Boolean.TRUE);
 278  
         }
 279  0
         dao.saveEDocLiteAssociation(assoc);
 280  0
     }
 281  
 
 282  
     // ---- EDocLiteService interface implementation
 283  
 
 284  
     public void saveEDocLiteDefinition(InputStream xml) {
 285  
         // convert xml to EDocLiteDefinition
 286  0
         EDocLiteDefinition data = parseEDocLiteDefinition(parse(xml).getDocumentElement());
 287  0
         saveEDocLiteDefinition(data);
 288  0
     }
 289  
 
 290  
     public void saveEDocLiteAssociation(InputStream xml) {
 291  
         // convert xml to EDocLiteAssociation
 292  0
         EDocLiteAssociation assoc = parseEDocLiteAssociation(parse(xml).getDocumentElement());
 293  0
         saveEDocLiteAssociation(assoc);
 294  0
     }
 295  
 
 296  
     public EDocLiteDefinition getEDocLiteDefinition(String definitionName) {
 297  0
         return dao.getEDocLiteDefinition(definitionName);
 298  
     }
 299  
 
 300  
     public EDocLiteAssociation getEDocLiteAssociation(String docTypeName) {
 301  0
         return dao.getEDocLiteAssociation(docTypeName);
 302  
     }
 303  
 
 304  
     public List getEDocLiteDefinitions() {
 305  0
         return dao.getEDocLiteDefinitions();
 306  
     }
 307  
 
 308  
     public List getEDocLiteAssociations() {
 309  0
         return dao.getEDocLiteAssociations();
 310  
     }
 311  
 
 312  
     public Templates getStyleAsTranslet(String name) throws TransformerConfigurationException {
 313  0
         if (name == null || "null".equals(name)) { //"name".equals(name) - from a null value in the lookupable
 314  0
             name = "Default";
 315  
         }
 316  
 
 317  0
         return styleService.getStyleAsTranslet(name);
 318  
     }
 319  
 
 320  
     public void removeDefinitionFromCache(String defName) {
 321  0
         LOG.info("Removing definition " + defName + " from cache");
 322  0
         EDLControllerFactory.flushDefinitionFromConfigCache(defName);
 323  0
     }
 324  
 
 325  
     public List search(EDocLiteAssociation edocLite) {
 326  0
         return this.dao.search(edocLite);
 327  
     }
 328  
 
 329  
     public EDocLiteAssociation getEDocLiteAssociation(Long associationId) {
 330  0
         return dao.getEDocLiteAssociation(associationId);
 331  
     }
 332  
 
 333  
     // ---- XmlLoader interface implementation
 334  
 
 335  
     public void loadXml(InputStream inputStream, String principalId) {
 336  0
             EDocLiteXmlParser.loadXml(inputStream, principalId);
 337  0
     }
 338  
 
 339  
     // ---- XmlExporter interface implementation
 340  
         public org.jdom.Element export(ExportDataSet dataSet) {
 341  0
                 return new EDocLiteXmlExporter().export(dataSet);
 342  
         }
 343  
 
 344  
         @Override
 345  
         public boolean supportPrettyPrint() {
 346  0
                 return false;
 347  
         }
 348  
         
 349  
         public void setStyleService(StyleService styleService) {
 350  0
                 this.styleService = styleService;
 351  0
         }
 352  
         
 353  
 }