Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright 2005-2013 The Kuali Foundation Licensed under the Educational Community License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.opensource.org/licenses/ecl2.php Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 
 package org.kuali.rice.kew.xml;
 
 
 import java.util.List;
 
 import static org.kuali.rice.core.api.impex.xml.XmlConstants.*;

Parses rules from XML.

Author(s):
Kuali Rice Team (rice.collab@kuali.org)
See also:
org.kuali.rice.kew.rule.RuleBaseValues
 
 public class RuleXmlParser {
 
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RuleXmlParser.class);

    
Priority to use if rule responsibility omits priority
 
     private static final int DEFAULT_RULE_PRIORITY = 1;
    
Value of Force Action flag if omitted; default to false, we will NOT force action for approvals
 
     private static final boolean DEFAULT_FORCE_ACTION = false;
    
Default approve policy, if omitted; defaults to FIRST_APPROVE, the request will be satisfied by the first approval
 
     private static final String DEFAULT_APPROVE_POLICY = ..getCode();
    
Default action requested, if omitted; defaults to "A"pprove
 
 
     	try {
             Document doc = XmlHelper.trimSAXXml(input);
             Element root = doc.getRootElement();
             return parseRuleDelegations(root);
         } catch (JDOMException e) {
             throw new XmlException("Parse error."e);
         } catch (SAXException e){
             throw new XmlException("Parse error.",e);
         } catch(ParserConfigurationException e){
             throw new XmlException("Parse error.",e);
         }
     }
     
     public List<RuleBaseValuesparseRules(InputStream inputthrows IOExceptionXmlException {
         try {
             Document doc = XmlHelper.trimSAXXml(input);
             Element root = doc.getRootElement();
             return parseRules(root);
        } catch (JDOMException e) {
            throw new XmlException("Parse error."e);
        } catch (SAXException e){
            throw new XmlException("Parse error.",e);
        } catch(ParserConfigurationException e){
            throw new XmlException("Parse error.",e);
        }
    }

    
Parses and saves rules

Parameters:
element top-level 'data' element which should contain a <rules> child element
Throws:
org.kuali.rice.core.api.util.xml.XmlException
    public List<RuleBaseValuesparseRules(Element elementthrows XmlException {
    	List<RuleBaseValuesrulesToSave = new ArrayList<RuleBaseValues>();
        for (Element rulesElement: (List<Element>) element.getChildren()) {
            for (Element ruleElement: (List<Element>) rulesElement.getChildren()) {
                RuleBaseValues rule = parseRule(ruleElement);
                rulesToSave.add(rule);
            }
        }
        checkForDuplicateRules(rulesToSave);
        return KEWServiceLocator.getRuleService().saveRules(rulesToSavefalse);
    }
    
    
Parses and saves rule delegations

Parameters:
element top-level 'data' element which should contain a <rules> child element
Throws:
org.kuali.rice.core.api.util.xml.XmlException
    public List<RuleDelegationBoparseRuleDelegations(Element elementthrows XmlException {
    	List<RuleDelegationBoruleDelegationsToSave = new ArrayList<RuleDelegationBo>();
        for (Element ruleDelegationsElement: (List<Element>) element.getChildren()) {
            for (Element ruleDelegationElement: (List<Element>) ruleDelegationsElement.getChildren()) {
                RuleDelegationBo ruleDelegation = parseRuleDelegation(ruleDelegationElement);
                ruleDelegationsToSave.add(ruleDelegation);
            }
        }
        //checkForDuplicateRuleDelegations(ruleDelegationsToSave);
        return KEWServiceLocator.getRuleService().saveRuleDelegations(ruleDelegationsToSavefalse);
    }
    
    
Checks for rules in the List that duplicate other Rules already in the system
    private void checkForDuplicateRules(List<RuleBaseValuesrulesthrows XmlException {
    	for (RuleBaseValues rule : rules) {
    		if (StringUtils.isBlank(rule.getName())) {
    			.debug("Checking for rule duplication on an anonymous rule.");
    			checkRuleForDuplicate(rule);
    		}
    	}
    }
    
    
Checks for rule delegations in the List that duplicate other Rules already in the system
    private void checkForDuplicateRuleDelegations(List<RuleDelegationBoruleDelegationsthrows XmlException {
    	for (RuleDelegationBo ruleDelegation : ruleDelegations) {
    		if (StringUtils.isBlank(ruleDelegation.getDelegationRule().getName())) {
    			.debug("Checking for rule duplication on an anonymous rule delegation.");
    			checkRuleDelegationForDuplicate(ruleDelegation);
    		}
    	}
    }
    private RuleDelegationBo parseRuleDelegation(Element elementthrows XmlException {
    	RuleDelegationBo ruleDelegation = new RuleDelegationBo();
    	Element parentResponsibilityElement = element.getChild(element.getNamespace());
    	if (parentResponsibilityElement == null) {
    		throw new XmlException("parent responsibility was not defined");
    	}
    	String parentResponsibilityId = parseParentResponsibilityId(parentResponsibilityElement);
    	String delegationType = element.getChildText(element.getNamespace());
        if (delegationType == null || DelegationType.parseCode(delegationType) == null) {
            throw new XmlException("Invalid delegation type specified for delegate rule '" + delegationType + "'");
        }
        
        ruleDelegation.setResponsibilityId(parentResponsibilityId);
        ruleDelegation.setDelegationType(DelegationType.fromCode(delegationType));
        
        Element ruleElement = element.getChild(element.getNamespace());
        RuleBaseValues rule = parseRule(ruleElement);
        rule.setDelegateRule(true);
        ruleDelegation.setDelegationRule(rule);
    	
    	return ruleDelegation;
    }
    
    private String parseParentResponsibilityId(Element elementthrows XmlException {
    	String responsibilityId = element.getChildText(element.getNamespace());
    	if (!StringUtils.isBlank(responsibilityId)) {
    		return responsibilityId;
    	}
    	String parentRuleName = element.getChildText(element.getNamespace());
    	if (StringUtils.isBlank(parentRuleName)) {
    		throw new XmlException("One of responsibilityId or parentRuleName needs to be defined");
    	}
    	RuleBaseValues parentRule = KEWServiceLocator.getRuleService().getRuleByName(parentRuleName);
    	if (parentRule == null) {
    		throw new XmlException("Could find the parent rule with name '" + parentRuleName + "'");
    	}
    	RuleResponsibilityBo ruleResponsibilityNameAndType = CommonXmlParser.parseResponsibilityNameAndType(element);
    	if (ruleResponsibilityNameAndType == null) {
    		throw new XmlException("Could not locate a valid responsibility declaration for the parent responsibility.");
    	}
    	String parentResponsibilityId = KEWServiceLocator.getRuleService().findResponsibilityIdForRule(parentRuleName
    			ruleResponsibilityNameAndType.getRuleResponsibilityName(),
    			ruleResponsibilityNameAndType.getRuleResponsibilityType());
    	if (parentResponsibilityId == null) {
    		throw new XmlException("Failed to locate parent responsibility for rule with name '" + parentRuleName + "' and responsibility " + ruleResponsibilityNameAndType);
    	}
    	return parentResponsibilityId;
    }
    
    
Parses, and only parses, a rule definition (be it a top-level rule, or a rule delegation). This method will NOT dirty or save any existing data, it is side-effect-free.

Parameters:
element the rule element
Returns:
a new RuleBaseValues object which is not yet saved
Throws:
org.kuali.rice.core.api.util.xml.XmlException
    private RuleBaseValues parseRule(Element elementthrows XmlException {
        String name = element.getChildText(element.getNamespace());
        RuleBaseValues rule = createRule(name);
        
        setDefaultRuleValues(rule);
        rule.setName(name);
        
        String toDatestr = element.getChildTextelement.getNamespace());
        String fromDatestr = element.getChildTextelement.getNamespace());
        rule.setToDateValue(formatDate("toDate"toDatestr));
        rule.setFromDateValue(formatDate("fromDate"fromDatestr));
        String description = element.getChildText(element.getNamespace());
        if (StringUtils.isBlank(description)) {
            throw new XmlException("Rule must have a description.");
        }
                
        String documentTypeName = element.getChildText(element.getNamespace());
        if (StringUtils.isBlank(documentTypeName)) {
        	throw new XmlException("Rule must have a document type.");
        }
        DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
        if (documentType == null) {
        	throw new XmlException("Could not locate document type '" + documentTypeName + "'");
        }
        RuleTemplateBo ruleTemplate = null;
        String ruleTemplateName = element.getChildText(element.getNamespace());        
        Element ruleExtensionsElement = element.getChild(element.getNamespace());
        if (!StringUtils.isBlank(ruleTemplateName)) {
        	ruleTemplate = KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(ruleTemplateName);
        	if (ruleTemplate == null) {
        		throw new XmlException("Could not locate rule template '" + ruleTemplateName + "'");
        	}
        } else {
        	if (ruleExtensionsElement != null) {
        		throw new XmlException("Templateless rules may not have rule extensions");
        	}
        }
        RuleExpressionDef ruleExpressionDef = null;
        Element exprElement = element.getChild(element.getNamespace());
        if (exprElement != null) {
        	String exprType = exprElement.getAttributeValue("type");
        	if (StringUtils.isEmpty(exprType)) {
        		throw new XmlException("Expression type must be specified");
        	}
        	String expression = exprElement.getTextTrim();
        	ruleExpressionDef = new RuleExpressionDef();
        	ruleExpressionDef.setType(exprType);
        	ruleExpressionDef.setExpression(expression);
        }
        
        String forceActionValue = element.getChildText(element.getNamespace());
        Boolean forceAction = Boolean.valueOf();
        if (!StringUtils.isBlank(forceActionValue)) {
            forceAction = Boolean.valueOf(forceActionValue);
        }
        rule.setDocTypeName(documentType.getName());
        if (ruleTemplate != null) {
            rule.setRuleTemplateId(ruleTemplate.getId());
            rule.setRuleTemplate(ruleTemplate);
        }
        if (ruleExpressionDef != null) {
            rule.setRuleExpressionDef(ruleExpressionDef);
        }
        rule.setDescription(description);
        rule.setForceAction(forceAction);
        Element responsibilitiesElement = element.getChild(element.getNamespace());
        rule.setRuleResponsibilities(parseResponsibilities(responsibilitiesElementrule));
        rule.setRuleExtensions(parseRuleExtensions(ruleExtensionsElementrule));
        return rule;
    }
    
    
Creates the rule that the parser will populate. If a rule with the given name already exists, it's keys and responsibilities will be copied over to the new rule. The calling code will then sort through the original responsibilities and compare them with those being defined on the XML being parsed.
    private RuleBaseValues createRule(String ruleName) {
    	RuleBaseValues rule = new RuleBaseValues();
    	RuleBaseValues existingRule = (ruleName != null) ? KEWServiceLocator.getRuleService().getRuleByName(ruleName) : null;
    	if (existingRule != null) {
    		// copy keys and responsibiliities from the existing rule
    		rule.setId(existingRule.getId());
    		rule.setPreviousRuleId(existingRule.getPreviousRuleId());
    		rule.setPreviousVersion(existingRule.getPreviousVersion());
    	}
    	return rule;
    }

    
Checks to see whether this anonymous rule duplicates an existing rule. Currently the uniqueness is on ruleResponsibilityName, and extension key/values.

Parameters:
rule the rule to check
Throws:
org.kuali.rice.core.api.util.xml.XmlException if this incoming rule duplicates an existing rule
    private void checkRuleForDuplicate(RuleBaseValues rulethrows XmlException {
    	String ruleId = KEWServiceLocator.getRuleService().getDuplicateRuleId(rule);
        if (ruleId != null) {
        	throw new XmlException("Rule '" + rule.getDescription() + "' on doc '" + rule.getDocTypeName() + "' is a duplicate of rule with rule Id " + ruleId);
        }
    }
    
    private void checkRuleDelegationForDuplicate(RuleDelegationBo ruleDelegationthrows XmlException {
    	checkRuleForDuplicate(ruleDelegation.getDelegationRule());
    }
    private void setDefaultRuleValues(RuleBaseValues rulethrows XmlException {
        rule.setForceAction(.);
        rule.setActivationDate(new Timestamp(System.currentTimeMillis()));
        rule.setActive(.);
        rule.setCurrentInd(.);
        rule.setTemplateRuleInd(.);
        rule.setVersionNbr(new Integer(0));
        rule.setDelegateRule(false);
    }
    private List<RuleResponsibilityBoparseResponsibilities(Element elementRuleBaseValues rulethrows XmlException {
        if (element == null) {
            return new ArrayList<RuleResponsibilityBo>(0);
        }
        List<RuleResponsibilityBoexistingResponsibilities = rule.getRuleResponsibilities();
        List<RuleResponsibilityBoresponsibilities = new ArrayList<RuleResponsibilityBo>();
        List<ElementresponsibilityElements = (List<Element>)element.getChildren(element.getNamespace());
        for (Element responsibilityElement : responsibilityElements) {
            RuleResponsibilityBo responsibility = parseResponsibility(responsibilityElementrule);
            reconcileWithExistingResponsibility(responsibilityexistingResponsibilities);
            responsibilities.add(responsibility);
        }
        if (responsibilities.size() == 0) {
            throw new XmlException("Rule responsibility list must have at least one responsibility.");
        }
        return responsibilities;
    }
    public RuleResponsibilityBo parseResponsibility(Element elementRuleBaseValues rulethrows XmlException {
        RuleResponsibilityBo responsibility = new RuleResponsibilityBo();
        responsibility.setRuleBaseValues(rule);
        String actionRequested = null;
        String priority = null;
        actionRequested = element.getChildText(element.getNamespace());
        if (StringUtils.isBlank(actionRequested)) {
        	actionRequested = ;
        }
        priority = element.getChildText(element.getNamespace());
        if (StringUtils.isBlank(priority)) {
        	priority = String.valueOf();
        }
        String approvePolicy = element.getChildText(element.getNamespace());
        Element delegations = element.getChild(element.getNamespace());
        if (actionRequested == null) {
            throw new XmlException("actionRequested is required on responsibility");
        }
            throw new XmlException("Invalid action requested code '" + actionRequested + "'");
        }
        if (StringUtils.isBlank(approvePolicy)) {
            approvePolicy = ;
        }
        if (!approvePolicy.equals(..getCode()) && !approvePolicy.equals(..getCode())) {
            throw new XmlException("Invalid approve policy '" + approvePolicy + "'");
        }
        Integer priorityNumber = Integer.valueOf(priority);
        responsibility.setActionRequestedCd(actionRequested);
        responsibility.setPriority(priorityNumber);
        responsibility.setApprovePolicy(approvePolicy);
        
        RuleResponsibilityBo responsibilityNameAndType = CommonXmlParser.parseResponsibilityNameAndType(element);
        if (responsibilityNameAndType == null) {
        	throw new XmlException("Could not locate a valid responsibility declaration on a responsibility on rule with description '" + rule.getDescription() + "'");
        }
        if (responsibilityNameAndType.getRuleResponsibilityType().equals(.)
        		&& responsibility.getApprovePolicy().equals(..getCode())) {
        	throw new XmlException("Invalid approve policy '" + approvePolicy + "'.  This policy is not supported with Groups.");
        }
        responsibility.setRuleResponsibilityName(responsibilityNameAndType.getRuleResponsibilityName());
        responsibility.setRuleResponsibilityType(responsibilityNameAndType.getRuleResponsibilityType());
        
        return responsibility;
    }
    
    
Attempts to reconcile the given RuleResponsibility with the list of existing responsibilities (in the case of a rule being updated via the XML). This goal of this code is to copy responsibility ids from existing responsibilities to the new responsibility where appropriate. The code will attempt to find exact matches based on the values found on the responsibilities.
    private void reconcileWithExistingResponsibility(RuleResponsibilityBo responsibilityList<RuleResponsibilityBoexistingResponsibilities) {
    	if (existingResponsibilities == null || existingResponsibilities.isEmpty()) {
    		return;
    	}
    	RuleResponsibilityBo exactMatch = null;
    	for (RuleResponsibilityBo existingResponsibility : existingResponsibilities) {
    		if (isExactResponsibilityMatch(responsibilityexistingResponsibility)) {
    			exactMatch = existingResponsibility;
    			break;
    		}
    	}
    	if (exactMatch != null) {
    		responsibility.setResponsibilityId(exactMatch.getResponsibilityId());
    	}
    }
    
    
Checks if the given responsibilities are exact matches of one another.
    private boolean isExactResponsibilityMatch(RuleResponsibilityBo newResponsibilityRuleResponsibilityBo existingResponsibility) {
    	if (existingResponsibility.getResponsibilityId().equals(newResponsibility.getResponsibilityId())) {
    		return true;
    	}
    	if (existingResponsibility.getRuleResponsibilityName().equals(newResponsibility.getRuleResponsibilityName()) &&
    			existingResponsibility.getRuleResponsibilityType().equals(newResponsibility.getRuleResponsibilityType()) &&
    			existingResponsibility.getApprovePolicy().equals(newResponsibility.getApprovePolicy()) &&
    			existingResponsibility.getActionRequestedCd().equals(newResponsibility.getActionRequestedCd()) &&
    			existingResponsibility.getPriority().equals(newResponsibility.getPriority())) {
    		return true;
    	}
    	return false;
    }
    private List parseRuleExtensions(Element elementRuleBaseValues rulethrows XmlException {
        if (element == null) {
            return new ArrayList();
        }
        RuleExtensionXmlParser parser = new RuleExtensionXmlParser();
        return parser.parseRuleExtensions(elementrule);
    }
    
    public Timestamp formatDate(String dateLabelString dateStringthrows XmlException {
    	if (StringUtils.isBlank(dateString)) {
    		return null;
    	}
    	try {
    		return new Timestamp(RiceConstants.getDefaultDateFormat().parse(dateString).getTime());
    	} catch (ParseException e) {
    		throw new XmlException(dateLabel + " is not in the proper format.  Should have been: " + .);
    	}
    }
    
New to GrepCode? Check out our FAQ X