001/** 002 * Copyright 2005-2014 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.lang.StringUtils; 019import org.apache.commons.lang.time.DateUtils; 020import org.junit.Test; 021import org.kuali.rice.core.api.CoreApiServiceLocator; 022import org.kuali.rice.core.api.util.ClasspathOrFileResourceLoader; 023import org.kuali.rice.kew.export.KewExportDataSet; 024import org.kuali.rice.kew.rule.RuleBaseValues; 025import org.kuali.rice.kew.rule.RuleDelegationBo; 026import org.kuali.rice.kew.rule.RuleExtensionBo; 027import org.kuali.rice.kew.rule.RuleExtensionValue; 028import org.kuali.rice.kew.rule.RuleResponsibilityBo; 029import org.kuali.rice.kew.rule.web.WebRuleUtils; 030import org.kuali.rice.kew.service.KEWServiceLocator; 031import org.kuali.rice.test.BaselineTestCase; 032import org.kuali.rice.test.ClearDatabaseLifecycle; 033 034import java.io.BufferedInputStream; 035import java.io.ByteArrayInputStream; 036import java.util.ArrayList; 037import java.util.Calendar; 038import java.util.HashSet; 039import java.util.Iterator; 040import java.util.List; 041import java.util.Set; 042 043import static org.junit.Assert.*; 044 045 046/** 047 * Tests the RuleXmlExporter by importing XML, exporting it, and then re-importing the xml.<br><br> 048 * 049 * NOTE: It's important to note that the success of this test depends on all of the Rules in any 050 * XML having unique descriptions as this is the only way for the test to identify 051 * the rules from the original imported XML and the XML imported from the export. 052 * 053 * @author Kuali Rice Team (rice.collab@kuali.org) 054 */ 055@BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE) 056public class RuleXmlExporterTest extends XmlExporterTestCase { 057 058 @Test public void testExport() throws Exception { 059 ClasspathOrFileResourceLoader rl = new ClasspathOrFileResourceLoader(); 060 loadXmlFile("org/kuali/rice/kew/actions/ActionsConfig.xml"); 061 loadXmlStream(rl.getResource("classpath:org/kuali/rice/kew/batch/data/RuleAttributeContent.xml").getInputStream()); 062 loadXmlStream(rl.getResource("classpath:org/kuali/rice/kew/batch/data/RuleTemplateContent.xml").getInputStream()); 063 loadXmlStream(rl.getResource("classpath:org/kuali/rice/kew/batch/data/DocumentTypeContent.xml").getInputStream()); 064 loadXmlStream(rl.getResource("classpath:org/kuali/rice/kew/batch/data/RuleContent.xml").getInputStream()); 065 assertRuleBaseValuesStateIndependence(); 066 assertExport(); 067 } 068 069 /** 070 * Note that the assertion here will fail if you have multiple rules with the same description. 071 */ 072 protected void assertExport() throws Exception { 073 // export all existing rules and their dependencies (document types, rule templates, rule attributes) 074 List oldRules = KEWServiceLocator.getRuleService().fetchAllRules(true); 075 assertAllRulesHaveUniqueNames(oldRules); 076 List oldRuleDelegations = KEWServiceLocator.getRuleDelegationService().findAllCurrentRuleDelegations(); 077 assertAllRuleDelegationsHaveUniqueNames(oldRuleDelegations); 078 079 KewExportDataSet dataSet = new KewExportDataSet(); 080 dataSet.getRules().addAll(oldRules); 081 dataSet.getRuleDelegations().addAll(oldRuleDelegations); 082 dataSet.getDocumentTypes().addAll(KEWServiceLocator.getDocumentTypeService().findAllCurrent()); 083 dataSet.getRuleTemplates().addAll(KEWServiceLocator.getRuleTemplateService().findAll()); 084 dataSet.getRuleAttributes().addAll(KEWServiceLocator.getRuleAttributeService().findAll()); 085 byte[] xmlBytes = CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet()); 086 assertTrue("XML should be non empty.", xmlBytes != null && xmlBytes.length > 0); 087 088 // now clear the tables 089 ClearDatabaseLifecycle clearLifeCycle = new ClearDatabaseLifecycle(); 090 clearLifeCycle.getTablesToClear().add("KREW_RULE_T"); 091 clearLifeCycle.getTablesToClear().add("KREW_RULE_RSP_T"); 092 clearLifeCycle.getTablesToClear().add("KREW_DLGN_RSP_T"); 093 clearLifeCycle.getTablesToClear().add("KREW_RULE_ATTR_T"); 094 clearLifeCycle.getTablesToClear().add("KREW_RULE_TMPL_T"); 095 clearLifeCycle.getTablesToClear().add("KREW_DOC_TYP_T"); 096 clearLifeCycle.start(); 097 new ClearCacheLifecycle().stop(); 098 099 // import the exported xml 100 loadXmlStream(new BufferedInputStream(new ByteArrayInputStream(xmlBytes))); 101 102 List newRules = KEWServiceLocator.getRuleService().fetchAllRules(true); 103 assertEquals("Should have same number of old and new Rules.", oldRules.size(), newRules.size()); 104 for (Iterator iterator = oldRules.iterator(); iterator.hasNext();) { 105 RuleBaseValues oldRule = (RuleBaseValues) iterator.next(); 106 boolean foundRule = false; 107 for (Iterator iterator2 = newRules.iterator(); iterator2.hasNext();) { 108 RuleBaseValues newRule = (RuleBaseValues) iterator2.next(); 109 if (oldRule.getDescription().equals(newRule.getDescription())) { 110 assertRuleExport(oldRule, newRule); 111 foundRule = true; 112 } 113 } 114 assertTrue("Could not locate the new rule for description " + oldRule.getDescription(), foundRule); 115 } 116 117 List newRuleDelegations = KEWServiceLocator.getRuleDelegationService().findAllCurrentRuleDelegations(); 118 assertDelegations(oldRuleDelegations, newRuleDelegations); 119 } 120 121 /** 122 * verifies that rule exports are the same regardless of whether the rule is ready for render, or 123 * for persistance. 124 */ 125 protected void assertRuleBaseValuesStateIndependence() throws Exception { 126 for (Object o : KEWServiceLocator.getRuleService().fetchAllRules(true)) { 127 RuleBaseValues rule = (RuleBaseValues)o; 128 KewExportDataSet dataSet = new KewExportDataSet(); 129 dataSet.getRules().add(rule); 130 131 // first, do a conversion in the just-loaded state: 132 byte[] saveXmlBytes = CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet()); 133 String saveStr = new String(saveXmlBytes); 134 135 // now, convert for render: 136 WebRuleUtils.populateRuleMaintenanceFields(rule); 137 138 // do another conversion in the ready-for-render state: 139 byte[] loadXmlBytes = CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet()); 140 String loadStr = new String(loadXmlBytes); 141 142 // FIXME: currently failing due to: 143 // * WebRuleUtils.populateRuleMaintenanceFields clears rule extensions 144 // * RuleXmlExporter detects missing extensions and re-adds them: but in a different order... 145 146 // check that the results are identical: 147 assertTrue("The load/render state of the RuleBaseValues shouldn't effect the export: \n" + 148 saveStr + "\n\n != \n\n" + loadStr, 149 StringUtils.equals(saveStr, loadStr)); 150 } 151 } 152 153 private void assertRuleExport(RuleBaseValues oldRule, RuleBaseValues newRule) { 154 assertFalse("Ids should be different.", oldRule.getId().equals(newRule.getId())); 155 assertEquals(oldRule.isActive(), newRule.isActive()); 156 assertEquals(DateUtils.round(oldRule.getActivationDate(), Calendar.DATE), DateUtils.round(newRule.getActivationDate(), Calendar.DATE)); 157 assertEquals(oldRule.getName(), newRule.getName()); 158 assertEquals(oldRule.getCurrentInd(), newRule.getCurrentInd()); 159 assertEquals(oldRule.getDeactivationDate(), newRule.getDeactivationDate()); 160 assertEquals(oldRule.getDelegateRule(), newRule.getDelegateRule()); 161 assertEquals(oldRule.getDescription(), newRule.getDescription()); 162 assertEquals(oldRule.getDocTypeName(), newRule.getDocTypeName()); 163 164 if (oldRule.getFromDateValue() == null) { 165 assertNull(newRule.getFromDateValue()); 166 } else { 167 assertEquals(DateUtils.round(oldRule.getFromDateValue(), Calendar.DATE), DateUtils.round(newRule.getFromDateValue(), Calendar.DATE)); 168 } 169 if (oldRule.getToDateValue() == null) { 170 assertNull(newRule.getToDateValue()); 171 } else { 172 assertEquals(DateUtils.round(oldRule.getToDateValue(), Calendar.DATE), DateUtils.round(newRule.getToDateValue(), Calendar.DATE)); 173 } 174 assertEquals(oldRule.getFromDateString(),newRule.getFromDateString() ); 175 assertEquals(oldRule.getToDateString(),newRule.getToDateString() ); 176 177 assertEquals(oldRule.isForceAction(), newRule.isForceAction()); 178 179 if(!oldRule.getDelegateRule().booleanValue()) 180 assertEquals(oldRule.getPreviousRuleId(), newRule.getPreviousRuleId()); 181 182 assertEquals(oldRule.getDocumentId(), newRule.getDocumentId()); 183 184 if (oldRule.getRuleTemplate() == null) { 185 assertNull(newRule.getRuleTemplate()); 186 } else { 187 assertEquals(oldRule.getRuleTemplate().getName(), newRule.getRuleTemplate().getName()); 188 } 189 if (oldRule.getRuleExpressionDef() == null) { 190 assertNull(newRule.getRuleExpressionDef()); 191 } else { 192 assertEquals(oldRule.getRuleExpressionDef().getExpression(), newRule.getRuleExpressionDef().getExpression()); 193 assertEquals(oldRule.getRuleExpressionDef().getType(), newRule.getRuleExpressionDef().getType()); 194 } 195 if(!oldRule.getDelegateRule().booleanValue()) 196 assertEquals(oldRule.getVersionNbr(), newRule.getVersionNbr()); 197 198 assertRuleExtensions(oldRule.getRuleExtensions(), newRule.getRuleExtensions()); 199 assertResponsibilities(oldRule.getRuleResponsibilities(), newRule.getRuleResponsibilities()); 200 201 202 } 203 204 private void assertRuleExtensions(List oldRuleExtensions, List newRuleExtensions) { 205 assertEquals(oldRuleExtensions.size(), newRuleExtensions.size()); 206 for (Iterator iterator = oldRuleExtensions.iterator(); iterator.hasNext();) { 207 RuleExtensionBo oldExtension = (RuleExtensionBo) iterator.next(); 208 boolean foundExtension = false; 209 for (Iterator iterator2 = newRuleExtensions.iterator(); iterator2.hasNext();) { 210 RuleExtensionBo newExtension = (RuleExtensionBo) iterator2.next(); 211 if (oldExtension.getRuleTemplateAttribute().getRuleAttribute().getName().equals(newExtension.getRuleTemplateAttribute().getRuleAttribute().getName()) && 212 oldExtension.getRuleTemplateAttribute().getRuleTemplate().getName().equals(newExtension.getRuleTemplateAttribute().getRuleTemplate().getName())) { 213 assertExtensionValues(oldExtension.getExtensionValues(), newExtension.getExtensionValues()); 214 foundExtension = true; 215 break; 216 } 217 } 218 assertTrue("Could not locate rule extension.", foundExtension); 219 } 220 } 221 222 private void assertExtensionValues(List oldExtensionValues, List newExtensionValues) { 223 assertEquals(oldExtensionValues.size(), newExtensionValues.size()); 224 for (Iterator iterator = oldExtensionValues.iterator(); iterator.hasNext();) { 225 RuleExtensionValue oldValue = (RuleExtensionValue) iterator.next(); 226 boolean foundValue = false; 227 for (Iterator iterator2 = oldExtensionValues.iterator(); iterator2.hasNext();) { 228 RuleExtensionValue newValue = (RuleExtensionValue) iterator2.next(); 229 if (oldValue.getKey().equals(newValue.getKey())) { 230 assertEquals(oldValue.getValue(), newValue.getValue()); 231 foundValue = true; 232 break; 233 } 234 } 235 assertTrue("Could not locate extension value.", foundValue); 236 } 237 } 238 239 private void assertResponsibilities(List oldResps, List newResps) { 240 assertEquals(oldResps.size(), newResps.size()); 241 for (Iterator iterator = oldResps.iterator(); iterator.hasNext();) { 242 RuleResponsibilityBo oldResp = (RuleResponsibilityBo) iterator.next(); 243 boolean foundResp = false; 244 for (Iterator iterator2 = newResps.iterator(); iterator2.hasNext();) { 245 RuleResponsibilityBo newResp = (RuleResponsibilityBo) iterator2.next(); 246 if (oldResp.getRuleResponsibilityName().equals(newResp.getRuleResponsibilityName())) { 247 assertEquals(oldResp.getActionRequestedCd(), newResp.getActionRequestedCd()); 248 assertEquals(oldResp.getApprovePolicy(), newResp.getApprovePolicy()); 249 assertEquals(oldResp.getResolvedRoleName(), newResp.getResolvedRoleName()); 250 assertEquals(oldResp.getRole(), newResp.getRole()); 251 assertEquals(oldResp.getRuleResponsibilityType(), newResp.getRuleResponsibilityType()); 252 assertEquals(oldResp.getPriority(), newResp.getPriority()); 253 foundResp = true; 254 break; 255 } 256 } 257 assertTrue("Could not locate responsibility "+oldResp.getRuleResponsibilityName()+" on rule "+oldResp.getRuleBaseValues().getDescription(), foundResp); 258 } 259 } 260 261 private void assertDelegations(List oldDelegations, List newDelegations) { 262 assertEquals(oldDelegations.size(), newDelegations.size()); 263 for (Iterator iterator = oldDelegations.iterator(); iterator.hasNext();) { 264 RuleDelegationBo oldDelegation = (RuleDelegationBo) iterator.next(); 265 boolean foundDelegation = false; 266 for (Iterator iterator2 = newDelegations.iterator(); iterator2.hasNext();) { 267 RuleDelegationBo newDelegation = (RuleDelegationBo) iterator2.next(); 268 if (oldDelegation.getDelegationRule().getName().equals(newDelegation.getDelegationRule().getName())) { 269 assertEquals(oldDelegation.getDelegationType(), newDelegation.getDelegationType()); 270 assertFalse(oldDelegation.getResponsibilityId().equals(newDelegation.getResponsibilityId())); 271 assertRuleExport(oldDelegation.getDelegationRule(), newDelegation.getDelegationRule()); 272 foundDelegation = true; 273 break; 274 } 275 } 276 assertTrue("Could not locate delegation.", foundDelegation); 277 } 278 } 279 280 private void assertAllRulesHaveUniqueNames(List rules) throws Exception { 281 Set<String> ruleDescriptions = new HashSet<String>(); 282 for (Iterator iterator = rules.iterator(); iterator.hasNext();) { 283 RuleBaseValues rule = (RuleBaseValues) iterator.next(); 284 assertFalse("Found 2 rules with the same description '" + rule.getDescription() + "'. " + 285 "In order for this test to work, all rules in the configuration files must have unique descriptions.", 286 ruleDescriptions.contains(rule.getDescription())); 287 ruleDescriptions.add(rule.getDescription()); 288 } 289 } 290 291 private void assertAllRuleDelegationsHaveUniqueNames(List<RuleDelegationBo> ruleDelegations) throws Exception { 292 List<RuleBaseValues> rules = new ArrayList<RuleBaseValues>(); 293 for (RuleDelegationBo ruleDelegation : ruleDelegations) { 294 rules.add(ruleDelegation.getDelegationRule()); 295 } 296 assertAllRulesHaveUniqueNames(rules); 297 } 298 299}