001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.kew.xml.export; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.ObjectUtils; 020import org.apache.commons.lang.StringUtils; 021import org.jdom.Element; 022import org.jdom.Namespace; 023import org.kuali.rice.core.api.exception.RiceRuntimeException; 024import org.kuali.rice.core.api.impex.ExportDataSet; 025import org.kuali.rice.core.api.util.xml.XmlRenderer; 026import org.kuali.rice.core.framework.impex.xml.XmlExporter; 027import org.kuali.rice.kew.export.KewExportDataSet; 028import org.kuali.rice.kew.rule.RuleBaseValues; 029import org.kuali.rice.kew.rule.RuleDelegationBo; 030import org.kuali.rice.kew.rule.RuleExtensionBo; 031import org.kuali.rice.kew.rule.RuleExtensionValue; 032import org.kuali.rice.kew.rule.RuleResponsibilityBo; 033import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo; 034import org.kuali.rice.kew.rule.web.WebRuleUtils; 035import org.kuali.rice.kew.service.KEWServiceLocator; 036import org.kuali.rice.kim.api.group.Group; 037import org.kuali.rice.kim.api.identity.principal.Principal; 038 039import java.util.ArrayList; 040import java.util.Collection; 041import java.util.Collections; 042import java.util.Comparator; 043import java.util.HashSet; 044import java.util.Iterator; 045import java.util.List; 046import java.util.Set; 047 048import static org.kuali.rice.core.api.impex.xml.XmlConstants.*; 049 050/** 051 * Exports rules to XML. 052 * 053 * @see RuleBaseValues 054 * 055 * @author Kuali Rice Team (rice.collab@kuali.org) 056 */ 057public class RuleXmlExporter implements XmlExporter { 058 059 protected final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(getClass()); 060 061 private XmlRenderer renderer; 062 063 public RuleXmlExporter(Namespace namespace) { 064 this.renderer = new XmlRenderer(namespace); 065 } 066 067 @Override 068 public boolean supportPrettyPrint() { 069 return true; 070 } 071 072 public Element export(ExportDataSet exportDataSet) { 073 KewExportDataSet dataSet = KewExportDataSet.fromExportDataSet(exportDataSet); 074 if (!dataSet.getRules().isEmpty()) { 075 Element rootElement = renderer.renderElement(null, RULES); 076 rootElement.setAttribute(SCHEMA_LOCATION_ATTR, RULE_SCHEMA_LOCATION, SCHEMA_NAMESPACE); 077 for (Iterator iterator = dataSet.getRules().iterator(); iterator.hasNext();) { 078 RuleBaseValues rule = (RuleBaseValues) iterator.next(); 079 exportRule(rootElement, rule); 080 //turn below on if need export delegates in rule exportation 081// if(rule.getDelegateRule().booleanValue()){ 082// exportRuleDelegations(rootElement, rule); 083// } 084 } 085 return rootElement; 086 } 087 return null; 088 } 089 090 public void exportRule(Element parent, RuleBaseValues rule) { 091 Element ruleElement = renderer.renderElement(parent, RULE); 092 if (rule.getName() != null) { 093 renderer.renderTextElement(ruleElement, NAME, rule.getName()); 094 } 095 renderer.renderTextElement(ruleElement, DOCUMENT_TYPE, rule.getDocTypeName()); 096 if (rule.getRuleTemplateName() != null) { 097 renderer.renderTextElement(ruleElement, RULE_TEMPLATE, rule.getRuleTemplateName()); 098 } 099 renderer.renderTextElement(ruleElement, DESCRIPTION, rule.getDescription()); 100 if(rule.getFromDateString() != null){ 101 renderer.renderTextElement(ruleElement, FROM_DATE, rule.getFromDateString()); 102 } 103 if(rule.getToDateString() != null){ 104 renderer.renderTextElement(ruleElement, TO_DATE, rule.getToDateString()); 105 } 106 if (rule.getRuleExpressionDef() != null) { 107 Element expressionElement = renderer.renderTextElement(ruleElement, EXPRESSION, rule.getRuleExpressionDef().getExpression()); 108 if (rule.getRuleExpressionDef().getType() != null) { 109 expressionElement.setAttribute("type", rule.getRuleExpressionDef().getType()); 110 } 111 } 112 renderer.renderBooleanElement(ruleElement, FORCE_ACTION, rule.isForceAction(), false); 113 114 if (CollectionUtils.isEmpty(rule.getRuleExtensions()) && 115 /* field values is not empty */ 116 !(rule.getFieldValues() == null || rule.getFieldValues().size() == 0)) { 117 // the rule is in the wrong state (as far as we are concerned). 118 // translate it 119 WebRuleUtils.translateResponsibilitiesForSave(rule); 120 WebRuleUtils.translateFieldValuesForSave(rule); 121 122 // do our exports 123 exportRuleExtensions(ruleElement, rule.getRuleExtensions()); 124 125 // translate it back 126 WebRuleUtils.populateRuleMaintenanceFields(rule); 127 } else { 128 exportRuleExtensions(ruleElement, rule.getRuleExtensions()); 129 } 130 131 // put responsibilities in a single collection 132 Set<RuleResponsibilityBo> responsibilities = new HashSet<RuleResponsibilityBo>(); 133 responsibilities.addAll(rule.getRuleResponsibilities()); 134 responsibilities.addAll(rule.getPersonResponsibilities()); 135 responsibilities.addAll(rule.getGroupResponsibilities()); 136 responsibilities.addAll(rule.getRoleResponsibilities()); 137 138 exportResponsibilities(ruleElement, responsibilities); 139 } 140 141 private void exportRuleExtensions(Element parent, List ruleExtensions) { 142 if (!ruleExtensions.isEmpty()) { 143 Element extsElement = renderer.renderElement(parent, RULE_EXTENSIONS); 144 for (Iterator iterator = ruleExtensions.iterator(); iterator.hasNext();) { 145 RuleExtensionBo extension = (RuleExtensionBo) iterator.next(); 146 Element extElement = renderer.renderElement(extsElement, RULE_EXTENSION); 147 RuleTemplateAttributeBo attribute = extension.getRuleTemplateAttribute(); 148 renderer.renderTextElement(extElement, ATTRIBUTE, attribute.getRuleAttribute().getName()); 149 renderer.renderTextElement(extElement, RULE_TEMPLATE, attribute.getRuleTemplate().getName()); 150 exportRuleExtensionValues(extElement, extension.getExtensionValues()); 151 } 152 } 153 } 154 155 // sorts by rule extension value key in order to establish a deterministic order 156 private void exportRuleExtensionValues(Element parent, List<RuleExtensionValue> extensionValues) { 157 if (!extensionValues.isEmpty()) { 158 List<RuleExtensionValue> sorted = new ArrayList<RuleExtensionValue>(extensionValues); 159 // establish deterministic ordering of keys 160 Collections.sort(sorted, new Comparator<RuleExtensionValue>() { 161 @Override 162 public int compare(RuleExtensionValue o1, RuleExtensionValue o2) { 163 if (o1 == null) return -1; 164 if (o2 == null) return 1; 165 return ObjectUtils.compare(o1.getKey(), o2.getKey()); 166 } 167 }); 168 Element extValuesElement = renderer.renderElement(parent, RULE_EXTENSION_VALUES); 169 for (Iterator iterator = sorted.iterator(); iterator.hasNext();) { 170 RuleExtensionValue extensionValue = (RuleExtensionValue) iterator.next(); 171 Element extValueElement = renderer.renderElement(extValuesElement, RULE_EXTENSION_VALUE); 172 renderer.renderTextElement(extValueElement, KEY, extensionValue.getKey()); 173 renderer.renderTextElement(extValueElement, VALUE, extensionValue.getValue()); 174 } 175 } 176 } 177 178 private void exportResponsibilities(Element parent, Collection<? extends RuleResponsibilityBo> responsibilities) { 179 if (responsibilities != null && !responsibilities.isEmpty()) { 180 Element responsibilitiesElement = renderer.renderElement(parent, RESPONSIBILITIES); 181 for (RuleResponsibilityBo ruleResponsibility : responsibilities) { 182 Element respElement = renderer.renderElement(responsibilitiesElement, RESPONSIBILITY); 183 //KULRICE-12282: commenting out the responsibility Id from the exported xml. 184 // renderer.renderTextElement(respElement, RESPONSIBILITY_ID, "" + ruleResponsibility.getResponsibilityId()); 185 if (ruleResponsibility.isUsingPrincipal()) { 186 renderer.renderTextElement(respElement, PRINCIPAL_NAME, ruleResponsibility.getPrincipal().getPrincipalName()); 187 } else if (ruleResponsibility.isUsingGroup()) { 188 Group group = ruleResponsibility.getGroup(); 189 Element groupElement = renderer.renderTextElement(respElement, GROUP_NAME, group.getName()); 190 groupElement.setAttribute(NAMESPACE, group.getNamespaceCode()); 191 } else if (ruleResponsibility.isUsingRole()) { 192 renderer.renderTextElement(respElement, ROLE, ruleResponsibility.getRuleResponsibilityName()); 193 renderer.renderTextElement(respElement, APPROVE_POLICY, ruleResponsibility.getApprovePolicy()); 194 } 195 if (!StringUtils.isBlank(ruleResponsibility.getActionRequestedCd())) { 196 renderer.renderTextElement(respElement, ACTION_REQUESTED, ruleResponsibility.getActionRequestedCd()); 197 } 198 if (ruleResponsibility.getPriority() != null) { 199 renderer.renderTextElement(respElement, PRIORITY, ruleResponsibility.getPriority().toString()); 200 } 201 } 202 } 203 } 204 205 //below are for exporting rule delegations in rule exportation 206 private void exportRuleDelegations(Element rootElement, RuleBaseValues rule){ 207 List<RuleDelegationBo> ruleDelegationDefaults = KEWServiceLocator.getRuleDelegationService().findByDelegateRuleId(rule.getId()); 208 for(RuleDelegationBo dele : ruleDelegationDefaults){ 209 if (LOG.isInfoEnabled()) { 210 LOG.info("*******delegates********\t" + dele.getRuleDelegationId()) ; 211 } 212 exportRuleDelegation(rootElement, dele); 213 } 214 } 215 216 private void exportRuleDelegation(Element parent, RuleDelegationBo ruleDelegation) { 217 Element ruleDelegationElement = renderer.renderElement(parent, RULE_DELEGATION); 218 exportRuleDelegationParentResponsibility(ruleDelegationElement, ruleDelegation); 219 renderer.renderTextElement(ruleDelegationElement, DELEGATION_TYPE, ruleDelegation.getDelegationType().getCode()); 220 exportRule(ruleDelegationElement, ruleDelegation.getDelegationRule()); 221 } 222 223 private void exportRuleDelegationParentResponsibility(Element parent, RuleDelegationBo delegation) { 224 Element parentResponsibilityElement = renderer.renderElement(parent, PARENT_RESPONSIBILITY); 225 RuleResponsibilityBo ruleResponsibility = KEWServiceLocator.getRuleService().findRuleResponsibility(delegation.getResponsibilityId()); 226 renderer.renderTextElement(parentResponsibilityElement, PARENT_RULE_NAME, ruleResponsibility.getRuleBaseValues().getName()); 227 if (ruleResponsibility.isUsingPrincipal()) { 228 Principal principal = ruleResponsibility.getPrincipal(); 229 renderer.renderTextElement(parentResponsibilityElement, PRINCIPAL_NAME, principal.getPrincipalName()); 230 } else if (ruleResponsibility.isUsingGroup()) { 231 Group group = ruleResponsibility.getGroup(); 232 Element groupElement = renderer.renderElement(parentResponsibilityElement, GROUP_NAME); 233 groupElement.setText(group.getName()); 234 groupElement.setAttribute(NAMESPACE, group.getNamespaceCode()); 235 } else if (ruleResponsibility.isUsingRole()) { 236 renderer.renderTextElement(parentResponsibilityElement, ROLE, ruleResponsibility.getRuleResponsibilityName()); 237 } else { 238 throw new RiceRuntimeException("Encountered a rule responsibility when exporting with an invalid type of '" + ruleResponsibility.getRuleResponsibilityType()); 239 } 240 } 241 242}