Coverage Report - org.kuali.rice.kew.rule.RemoveReplaceRuleRoutingAttribute
 
Classes in this File Line Coverage Branch Coverage Complexity
RemoveReplaceRuleRoutingAttribute
0%
0/39
0%
0/18
2.667
RemoveReplaceRuleRoutingAttribute$RuleDocumentType
0%
0/15
0%
0/2
2.667
 
 1  
 /*
 2  
  * Copyright 2007 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.rule;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashSet;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 import java.util.Set;
 23  
 
 24  
 import javax.xml.xpath.XPath;
 25  
 import javax.xml.xpath.XPathConstants;
 26  
 import javax.xml.xpath.XPathExpressionException;
 27  
 
 28  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 29  
 import org.kuali.rice.kew.engine.RouteContext;
 30  
 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
 31  
 import org.kuali.rice.kew.routeheader.DocumentContent;
 32  
 import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
 33  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 34  
 import org.w3c.dom.Document;
 35  
 import org.w3c.dom.Element;
 36  
 import org.w3c.dom.NodeList;
 37  
 
 38  
 
 39  
 /**
 40  
  * An attribute for handling routing of RemoveReplace documents according to the Document Types of the
 41  
  * rules that are being changed.  Leverages the RuleRoutingAttribute and adds some additional logic
 42  
  * to verify that at least one rule exists for each Document Type which is represented in the rule
 43  
  * changeset.
 44  
  *
 45  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 46  
  */
 47  0
 public class RemoveReplaceRuleRoutingAttribute extends RuleRoutingAttribute implements MassRuleAttribute {
 48  
 
 49  
     private static final long serialVersionUID = 6377571664060038747L;
 50  
 
 51  
     private static final String RULE_XPATH = "//rules/rule/documentType";
 52  
 
 53  
     /**
 54  
      * Overrides the parseDocContent from the super class to handle the different XML on a Remove/Replace User Document.
 55  
      *
 56  
      * <p>This method returns a List of RuleRoutingAttributes which store the document type name found in the rule XML.
 57  
      *
 58  
      * @see org.kuali.rice.kew.rule.RuleRoutingAttribute#parseDocContent(org.kuali.rice.kew.routeheader.DocumentContent)
 59  
      */
 60  
     @Override
 61  
     public List<RuleRoutingAttribute> parseDocContent(DocumentContent docContent) {
 62  0
         List<RuleRoutingAttribute> ruleRoutingAttributes = new ArrayList<RuleRoutingAttribute>();
 63  0
         Set<RuleDocumentType> changedRuleDocTypes = calculateChangedRuleDocumentTypes(docContent);
 64  0
         for (RuleDocumentType ruleDocumentType : changedRuleDocTypes) {
 65  0
             ruleRoutingAttributes.add(new RuleRoutingAttribute(ruleDocumentType.getDocumentTypeName()));
 66  
         }
 67  0
         return ruleRoutingAttributes;
 68  
     }
 69  
 
 70  
     public List filterNonMatchingRules(RouteContext routeContext, List rules) {
 71  0
         Set<RuleDocumentType> changedRuleDocTypes = calculateChangedRuleDocumentTypes(routeContext.getDocumentContent());
 72  
 
 73  0
         for (RuleBaseValues rule : (List<RuleBaseValues>)rules) {
 74  0
             if (changedRuleDocTypes.isEmpty()) {
 75  0
                 break;
 76  
             }
 77  0
             String ruleDocumentType = getRuleDocumentTypeFromRuleExtensions(rule.getRuleExtensions());
 78  0
             for (Iterator<RuleDocumentType> iterator = changedRuleDocTypes.iterator(); iterator.hasNext();) {
 79  0
                 RuleDocumentType ruleDocType = iterator.next();
 80  0
                 if (ruleDocType.isDocTypeSatisfied(ruleDocumentType)) {
 81  0
                     iterator.remove();
 82  
                 }
 83  0
             }
 84  0
         }
 85  
 
 86  0
         if (!changedRuleDocTypes.isEmpty()) {
 87  0
             String message = "No rules found for document types: ";
 88  0
             int index = 0;
 89  0
             for (RuleDocumentType docType : changedRuleDocTypes) {
 90  0
                 message += docType.getDocumentTypeName();
 91  0
                 index++;
 92  0
                 if (index < changedRuleDocTypes.size()) {
 93  0
                     message += ", ";
 94  
                 }
 95  
             }
 96  0
             throw new WorkflowRuntimeException(message);
 97  
         }
 98  
 
 99  0
         return rules;
 100  
     }
 101  
 
 102  
     protected Set<RuleDocumentType> calculateChangedRuleDocumentTypes(DocumentContent documentContent) {
 103  
         try {
 104  0
             Set<RuleDocumentType> docTypes = new HashSet<RuleDocumentType>();
 105  0
             Document document = documentContent.getDocument();
 106  0
             XPath xpath = XPathHelper.newXPath(document);
 107  0
             NodeList ruleDocTypeNodes = (NodeList)xpath.evaluate(RULE_XPATH, document, XPathConstants.NODESET);
 108  0
             for (int index = 0; index < ruleDocTypeNodes.getLength(); index++) {
 109  0
                 Element docTypeNode = (Element)ruleDocTypeNodes.item(index);
 110  0
                 String docTypeName = docTypeNode.getTextContent();
 111  0
                 docTypes.add(new RuleDocumentType(docTypeName));
 112  
             }
 113  0
             return docTypes;
 114  0
         } catch (XPathExpressionException e) {
 115  0
             throw new WorkflowRuntimeException(e);
 116  
         }
 117  
     }
 118  
 
 119  0
     private class RuleDocumentType {
 120  
         private String documentTypeName;
 121  0
         private Set<String> documentTypeNames = new HashSet<String>();
 122  0
         public RuleDocumentType(String documentTypeName) {
 123  0
             this.documentTypeName = documentTypeName;
 124  0
             DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 125  0
             addNameAndClimb(documentType);
 126  0
         }
 127  
         private void addNameAndClimb(DocumentType documentType) {
 128  0
             if (documentType == null) {
 129  0
                 return;
 130  
             }
 131  0
             documentTypeNames.add(documentType.getName());
 132  0
             addNameAndClimb(documentType.getParentDocType());
 133  0
         }
 134  
         public boolean isDocTypeSatisfied(String documentTypeNameToCheck) {
 135  0
             return documentTypeNames.contains(documentTypeNameToCheck);
 136  
         }
 137  
         public String getDocumentTypeName() {
 138  0
             return documentTypeName;
 139  
         }
 140  
         @Override
 141  
         public boolean equals(Object obj) {
 142  0
             return documentTypeName.equals(obj);
 143  
         }
 144  
         @Override
 145  
         public int hashCode() {
 146  0
             return documentTypeName.hashCode();
 147  
         }
 148  
 
 149  
     }
 150  
 
 151  
 }