Coverage Report - org.kuali.rice.kew.dto.DTOConverter
 
Classes in this File Line Coverage Branch Coverage Complexity
DTOConverter
0%
0/135
0%
0/88
12.4
DTOConverter$RouteNodeInstanceLoader
N/A
N/A
12.4
 
 1  
 /**
 2  
  * Copyright 2005-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  
 package org.kuali.rice.kew.dto;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.apache.log4j.Logger;
 20  
 import org.kuali.rice.core.api.exception.RiceRuntimeException;
 21  
 import org.kuali.rice.core.api.reflect.DataDefinition;
 22  
 import org.kuali.rice.core.api.reflect.ObjectDefinition;
 23  
 import org.kuali.rice.core.api.reflect.PropertyDefinition;
 24  
 import org.kuali.rice.core.api.util.xml.XmlHelper;
 25  
 import org.kuali.rice.core.api.util.xml.XmlJotter;
 26  
 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
 27  
 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
 28  
 import org.kuali.rice.kew.api.KewApiServiceLocator;
 29  
 import org.kuali.rice.kew.api.WorkflowRuntimeException;
 30  
 import org.kuali.rice.kew.api.action.ActionRequest;
 31  
 import org.kuali.rice.kew.api.action.ActionTaken;
 32  
 import org.kuali.rice.kew.api.document.DocumentContentUpdate;
 33  
 import org.kuali.rice.kew.api.document.DocumentDetail;
 34  
 import org.kuali.rice.kew.api.document.InvalidDocumentContentException;
 35  
 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
 36  
 import org.kuali.rice.kew.api.extension.ExtensionDefinition;
 37  
 import org.kuali.rice.kew.api.extension.ExtensionUtils;
 38  
 import org.kuali.rice.kew.definition.AttributeDefinition;
 39  
 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
 40  
 import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
 41  
 import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent;
 42  
 import org.kuali.rice.kew.framework.postprocessor.AfterProcessEvent;
 43  
 import org.kuali.rice.kew.framework.postprocessor.BeforeProcessEvent;
 44  
 import org.kuali.rice.kew.framework.postprocessor.DeleteEvent;
 45  
 import org.kuali.rice.kew.framework.postprocessor.DocumentLockingEvent;
 46  
 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteLevelChange;
 47  
 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
 48  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 49  
 import org.kuali.rice.kew.routeheader.StandardDocumentContent;
 50  
 import org.kuali.rice.kew.rule.WorkflowRuleAttribute;
 51  
 import org.kuali.rice.kew.rule.WorkflowAttributeValidationError;
 52  
 import org.kuali.rice.kew.rule.WorkflowAttributeXmlValidator;
 53  
 import org.kuali.rice.kew.rule.XmlConfiguredAttribute;
 54  
 import org.kuali.rice.kew.rule.bo.RuleAttribute;
 55  
 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
 56  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 57  
 import org.kuali.rice.kew.api.KewApiConstants;
 58  
 import org.w3c.dom.Document;
 59  
 import org.w3c.dom.Element;
 60  
 import org.w3c.dom.NodeList;
 61  
 import org.xml.sax.SAXException;
 62  
 
 63  
 import javax.xml.parsers.DocumentBuilder;
 64  
 import javax.xml.parsers.DocumentBuilderFactory;
 65  
 import javax.xml.parsers.ParserConfigurationException;
 66  
 import javax.xml.transform.TransformerException;
 67  
 import java.io.IOException;
 68  
 import java.util.ArrayList;
 69  
 import java.util.HashMap;
 70  
 import java.util.Iterator;
 71  
 import java.util.List;
 72  
 import java.util.Map;
 73  
 
 74  
 /**
 75  
  * Translates Workflow server side beans into client side VO beans.
 76  
  *
 77  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 78  
  */
 79  0
 public class DTOConverter {
 80  0
     private static final Logger LOG = Logger.getLogger(DTOConverter.class);
 81  
 
 82  
     public static String buildUpdatedDocumentContent(String existingDocContent,
 83  
             DocumentContentUpdate documentContentUpdate, String documentTypeName) {
 84  0
         if (existingDocContent == null) {
 85  0
             existingDocContent = KewApiConstants.DEFAULT_DOCUMENT_CONTENT;
 86  
         }
 87  0
         String documentContent = KewApiConstants.DEFAULT_DOCUMENT_CONTENT;
 88  0
         StandardDocumentContent standardDocContent = new StandardDocumentContent(existingDocContent);
 89  
         try {
 90  0
             DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 91  0
             Document document = builder.newDocument();
 92  0
             Element root = document.createElement(KewApiConstants.DOCUMENT_CONTENT_ELEMENT);
 93  0
             document.appendChild(root);
 94  0
             Element applicationContentElement = standardDocContent.getApplicationContent();
 95  0
             if (documentContentUpdate.getApplicationContent() != null) {
 96  
                 // application content has changed
 97  0
                 if (!StringUtils.isEmpty(documentContentUpdate.getApplicationContent())) {
 98  0
                     applicationContentElement = document.createElement(KewApiConstants.APPLICATION_CONTENT_ELEMENT);
 99  0
                     XmlHelper.appendXml(applicationContentElement, documentContentUpdate.getApplicationContent());
 100  
                 } else {
 101  
                     // they've cleared the application content
 102  0
                     applicationContentElement = null;
 103  
                 }
 104  
             }
 105  0
             Element attributeContentElement = createDocumentContentSection(document,
 106  
                     standardDocContent.getAttributeContent(), documentContentUpdate.getAttributeDefinitions(),
 107  
                     documentContentUpdate.getAttributeContent(), KewApiConstants.ATTRIBUTE_CONTENT_ELEMENT,
 108  
                     documentTypeName);
 109  0
             Element searchableContentElement = createDocumentContentSection(document,
 110  
                     standardDocContent.getSearchableContent(), documentContentUpdate.getSearchableDefinitions(),
 111  
                     documentContentUpdate.getSearchableContent(), KewApiConstants.SEARCHABLE_CONTENT_ELEMENT,
 112  
                     documentTypeName);
 113  0
             if (applicationContentElement != null) {
 114  0
                 root.appendChild(applicationContentElement);
 115  
             }
 116  0
             if (attributeContentElement != null) {
 117  0
                 root.appendChild(attributeContentElement);
 118  
             }
 119  0
             if (searchableContentElement != null) {
 120  0
                 root.appendChild(searchableContentElement);
 121  
             }
 122  0
             documentContent = XmlJotter.jotNode(document);
 123  0
         } catch (ParserConfigurationException e) {
 124  0
             throw new RiceRuntimeException("Failed to initialize XML parser.", e);
 125  0
         } catch (SAXException e) {
 126  0
             throw new InvalidDocumentContentException("Failed to parse XML.", e);
 127  0
         } catch (IOException e) {
 128  0
             throw new InvalidDocumentContentException("Failed to parse XML.", e);
 129  0
         } catch (TransformerException e) {
 130  0
             throw new InvalidDocumentContentException("Failed to parse XML.", e);
 131  0
         }
 132  0
         return documentContent;
 133  
     }
 134  
 
 135  
     private static Element createDocumentContentSection(Document document, Element existingAttributeElement,
 136  
             List<WorkflowAttributeDefinition> definitions, String content, String elementName,
 137  
             String documentTypeName) throws TransformerException, SAXException, IOException, ParserConfigurationException {
 138  0
         Element contentSectionElement = existingAttributeElement;
 139  
         // if they've updated the content, we're going to re-build the content section element from scratch
 140  0
         if (content != null) {
 141  0
             if (!org.apache.commons.lang.StringUtils.isEmpty(content)) {
 142  0
                 contentSectionElement = document.createElement(elementName);
 143  
                 // if they didn't merely clear the content, let's build the content section element by combining the children
 144  
                 // of the incoming XML content
 145  0
                 Element incomingAttributeElement = XmlHelper.readXml(content).getDocumentElement();
 146  0
                 NodeList children = incomingAttributeElement.getChildNodes();
 147  0
                 for (int index = 0; index < children.getLength(); index++) {
 148  0
                     contentSectionElement.appendChild(document.importNode(children.item(index), true));
 149  
                 }
 150  0
             } else {
 151  0
                 contentSectionElement = null;
 152  
             }
 153  
         }
 154  
         // if they have new definitions we're going to append those to the existing content section
 155  0
         if (definitions != null && !definitions.isEmpty()) {
 156  0
             String errorMessage = "";
 157  0
             boolean inError = false;
 158  0
             if (contentSectionElement == null) {
 159  0
                 contentSectionElement = document.createElement(elementName);
 160  
             }
 161  0
             for (WorkflowAttributeDefinition definitionVO : definitions) {
 162  0
                 AttributeDefinition definition = convertWorkflowAttributeDefinition(definitionVO);
 163  0
                 ExtensionDefinition extensionDefinition = definition.getExtensionDefinition();
 164  0
                 Object attribute = ExtensionUtils.loadExtension(extensionDefinition);
 165  
 
 166  0
                 if (attribute instanceof XmlConfiguredAttribute) {
 167  0
                     ((XmlConfiguredAttribute)attribute).setExtensionDefinition(RuleAttribute.to(definition.getRuleAttribute()));
 168  
                 }
 169  0
                 boolean propertiesAsMap = false;
 170  0
                 if (KewApiConstants.RULE_XML_ATTRIBUTE_TYPE.equals(extensionDefinition.getType())) {
 171  0
                     propertiesAsMap = true;
 172  
                 }
 173  0
                 if (propertiesAsMap) {
 174  0
                     for (org.kuali.rice.kew.api.document.PropertyDefinition propertyDefinitionVO : definitionVO
 175  
                             .getPropertyDefinitions()) {
 176  0
                         if (attribute instanceof GenericXMLRuleAttribute) {
 177  0
                             ((GenericXMLRuleAttribute) attribute).getParamMap().put(propertyDefinitionVO.getName(),
 178  
                                     propertyDefinitionVO.getValue());
 179  
                         }
 180  
                     }
 181  
                 }
 182  
 
 183  
                 // validate inputs from client application if the attribute is capable
 184  0
                 if (attribute instanceof WorkflowAttributeXmlValidator) {
 185  0
                     List<WorkflowAttributeValidationError> errors =
 186  
                             ((WorkflowAttributeXmlValidator) attribute).validateClientRoutingData();
 187  0
                     if (!errors.isEmpty()) {
 188  0
                         inError = true;
 189  0
                         errorMessage += "Error validating attribute " + definitionVO.getAttributeName() + " ";
 190  0
                         for (WorkflowAttributeValidationError error : errors) {
 191  0
                             errorMessage += error.getMessage() + " ";
 192  
                         }
 193  
                     }
 194  
                 }
 195  
                 // dont add to xml if attribute is in error
 196  0
                 if (!inError) {
 197  0
                     if (attribute instanceof WorkflowRuleAttribute) {
 198  0
                         String attributeDocContent = ((WorkflowRuleAttribute) attribute).getDocContent();
 199  0
                         if (!StringUtils.isEmpty(attributeDocContent)) {
 200  0
                             XmlHelper.appendXml(contentSectionElement, attributeDocContent);
 201  
                         }
 202  0
                     } else if (attribute instanceof SearchableAttribute) {
 203  0
                         SearchableAttribute searchableAttribute = (SearchableAttribute) attribute;
 204  0
                         String searchableAttributeContent = searchableAttribute.generateSearchContent(extensionDefinition, documentTypeName,
 205  
                                 definitionVO);
 206  0
                         if (!StringUtils.isBlank(searchableAttributeContent)) {
 207  0
                             XmlHelper.appendXml(contentSectionElement, searchableAttributeContent);
 208  
                         }
 209  
                     }
 210  
                 }
 211  0
             }
 212  0
             if (inError) {
 213  0
                 throw new WorkflowRuntimeException(errorMessage);
 214  
             }
 215  
 
 216  
         }
 217  0
         if (contentSectionElement != null) {
 218  
             // always be sure and import the element into the new document, if it originated from the existing doc content
 219  
             // and
 220  
             // appended to it, it will need to be imported
 221  0
             contentSectionElement = (Element) document.importNode(contentSectionElement, true);
 222  
         }
 223  0
         return contentSectionElement;
 224  
     }
 225  
 
 226  
     /**
 227  
      * New for Rice 2.0
 228  
      */
 229  
     public static AttributeDefinition convertWorkflowAttributeDefinition(WorkflowAttributeDefinition definition) {
 230  0
         if (definition == null) {
 231  0
             return null;
 232  
         }
 233  
 
 234  0
         ExtensionDefinition extensionDefinition = KewApiServiceLocator.getExtensionRepositoryService().getExtensionByName(definition.getAttributeName());
 235  0
         if (extensionDefinition == null) {
 236  0
             throw new WorkflowRuntimeException("Extension " + definition.getAttributeName() + " not found");
 237  
         }
 238  0
         RuleAttribute ruleAttribute = KEWServiceLocator.getRuleAttributeService().findByName(definition.getAttributeName());
 239  0
         if (ruleAttribute == null) {
 240  0
             throw new WorkflowRuntimeException("Attribute " + definition.getAttributeName() + " not found");
 241  
         }
 242  
 
 243  0
         ObjectDefinition objectDefinition = new ObjectDefinition(extensionDefinition.getResourceDescriptor());
 244  0
         if (definition.getParameters() != null) {
 245  0
             for (String parameter : definition.getParameters()) {
 246  0
                 objectDefinition.addConstructorParameter(new DataDefinition(parameter, String.class));
 247  
             }
 248  
         }
 249  0
         boolean propertiesAsMap = KewApiConstants.RULE_XML_ATTRIBUTE_TYPE.equals(extensionDefinition.getType()) || KewApiConstants
 250  
                 .SEARCHABLE_XML_ATTRIBUTE_TYPE.equals(extensionDefinition.getType());
 251  0
         if (!propertiesAsMap && definition.getPropertyDefinitions() != null) {
 252  0
             for (org.kuali.rice.kew.api.document.PropertyDefinition propertyDefinition : definition
 253  
                     .getPropertyDefinitions()) {
 254  0
                 objectDefinition.addProperty(new PropertyDefinition(propertyDefinition.getName(), new DataDefinition(
 255  
                         propertyDefinition.getValue(), String.class)));
 256  
             }
 257  
         }
 258  
 
 259  0
         return new AttributeDefinition(ruleAttribute, extensionDefinition, objectDefinition);
 260  
     }
 261  
 
 262  
     /**
 263  
      * Interface for a simple service providing RouteNodeInstanceS based on their IDs
 264  
      */
 265  0
     public static interface RouteNodeInstanceLoader {
 266  
         RouteNodeInstance load(String routeNodeInstanceID);
 267  
     }
 268  
 
 269  
 
 270  
     public static DocumentDetail convertDocumentDetailNew(DocumentRouteHeaderValue routeHeader) {
 271  0
         if (routeHeader == null) {
 272  0
             return null;
 273  
         }
 274  0
         org.kuali.rice.kew.api.document.Document document = DocumentRouteHeaderValue.to(routeHeader);
 275  0
         DocumentDetail.Builder detail = DocumentDetail.Builder.create(document);
 276  0
         Map<String, RouteNodeInstance> nodeInstances = new HashMap<String, RouteNodeInstance>();
 277  0
         List<ActionRequest> actionRequestVOs = new ArrayList<ActionRequest>();
 278  0
         List<ActionRequestValue> rootActionRequests = KEWServiceLocator.getActionRequestService().getRootRequests(
 279  
                 routeHeader.getActionRequests());
 280  0
         for (Iterator<ActionRequestValue> iterator = rootActionRequests.iterator(); iterator.hasNext(); ) {
 281  0
             ActionRequestValue actionRequest = iterator.next();
 282  0
             actionRequestVOs.add(ActionRequestValue.to(actionRequest));
 283  0
             RouteNodeInstance nodeInstance = actionRequest.getNodeInstance();
 284  0
             if (nodeInstance == null) {
 285  0
                 continue;
 286  
             }
 287  0
             if (nodeInstance.getRouteNodeInstanceId() == null) {
 288  0
                 throw new IllegalStateException(
 289  
                         "Error creating document detail structure because of NULL node instance id.");
 290  
             }
 291  0
             nodeInstances.put(nodeInstance.getRouteNodeInstanceId(), nodeInstance);
 292  0
         }
 293  0
         detail.setActionRequests(actionRequestVOs);
 294  0
         List<org.kuali.rice.kew.api.document.node.RouteNodeInstance> nodeInstanceVOs =
 295  
                 new ArrayList<org.kuali.rice.kew.api.document.node.RouteNodeInstance>();
 296  0
         for (Iterator<RouteNodeInstance> iterator = nodeInstances.values().iterator(); iterator.hasNext(); ) {
 297  0
             RouteNodeInstance nodeInstance = iterator.next();
 298  0
             nodeInstanceVOs.add(RouteNodeInstance.to(nodeInstance));
 299  0
         }
 300  0
         detail.setRouteNodeInstances(nodeInstanceVOs);
 301  0
         List<ActionTaken> actionTakenVOs = new ArrayList<ActionTaken>();
 302  0
         for (Object element : routeHeader.getActionsTaken()) {
 303  0
             ActionTakenValue actionTaken = (ActionTakenValue) element;
 304  0
             actionTakenVOs.add(ActionTakenValue.to(actionTaken));
 305  0
         }
 306  0
         detail.setActionsTaken(actionTakenVOs);
 307  0
         return detail.build();
 308  
     }
 309  
 
 310  
 }