001    /**
002     * Copyright 2005-2011 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     */
016    package org.kuali.rice.kew.actionrequest.service.impl;
017    
018    import static org.junit.Assert.assertEquals;
019    import static org.junit.Assert.assertFalse;
020    import static org.junit.Assert.assertNotNull;
021    import static org.junit.Assert.assertTrue;
022    
023    import java.util.ArrayList;
024    import java.util.List;
025    
026    import mocks.MockDocumentRefreshQueueImpl;
027    import mocks.MockEmailNotificationService;
028    
029    import org.apache.commons.collections.CollectionUtils;
030    import org.apache.commons.lang.StringUtils;
031    import org.junit.Test;
032    import org.kuali.rice.core.api.config.CoreConfigHelper;
033    import org.kuali.rice.core.api.delegation.DelegationType;
034    import org.kuali.rice.kew.actionitem.ActionItem;
035    import org.kuali.rice.kew.actionrequest.ActionRequestValue;
036    import org.kuali.rice.kew.api.WorkflowDocument;
037    import org.kuali.rice.kew.api.WorkflowDocumentFactory;
038    import org.kuali.rice.kew.api.action.ActionRequest;
039    import org.kuali.rice.kew.engine.node.RouteNodeInstance;
040    import org.kuali.rice.kew.messaging.MessageServiceNames;
041    import org.kuali.rice.kew.rule.RuleBaseValues;
042    import org.kuali.rice.kew.rule.RuleDelegationBo;
043    import org.kuali.rice.kew.rule.RuleResponsibilityBo;
044    import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
045    import org.kuali.rice.kew.service.KEWServiceLocator;
046    import org.kuali.rice.kew.test.KEWTestCase;
047    import org.kuali.rice.kew.api.KewApiConstants;
048    
049    /**
050     * This is a description of what this class does - gilesp don't forget to fill this in.
051     * 
052     * @author Kuali Rice Team (rice.collab@kuali.org)
053     * 
054     */
055    public class NotificationSuppressionTest extends KEWTestCase {
056    
057        private static final String TEST_RULE_TEMPLATE = "WorkflowDocumentTemplate";
058    
059        protected void loadTestData() throws Exception {
060            loadXmlFile("NotificationSuppressionTestConfig.xml");
061        }
062    
063        private static final String TEST_DOC_TYPE = "NotificationSuppressionTestDocType";
064    
065        /**
066         * Tests that the notification suppression keys work equivalently for ActionRequestDTO and
067         * ActionRequestValue
068         * 
069         * @throws Exception
070         */
071        @Test
072        public void testNotificationSuppressionKeys() throws Exception {
073            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
074                    TEST_DOC_TYPE);
075            document.route("");
076            List<ActionRequest> requests = document.getRootActionRequests();
077            assertTrue("there must be ActionRequestDTOs to test!", requests != null && requests.size() > 0);
078    
079            NotificationSuppression notificationSuppression = new NotificationSuppression();
080    
081            boolean atLeastOne = false;
082            for (ActionRequest reqDTO : requests)
083                if (reqDTO.getParentActionRequestId() == null) {
084                    atLeastOne = true;
085                    ActionRequestValue reqVal = ActionRequestValue.from(reqDTO);
086                    assertTrue(CollectionUtils.isEqualCollection(
087                            notificationSuppression.getSuppressNotifyNodeStateKeys(reqVal),
088                            notificationSuppression.getSuppressNotifyNodeStateKeys(reqDTO)));
089    
090                    // test that changing the responsible party changes the key
091    
092                    ActionRequest.Builder builder = ActionRequest.Builder.create(reqDTO);
093                    builder.setPrincipalId("asdf");
094                    reqDTO = builder.build();
095                    assertFalse(CollectionUtils.isEqualCollection(
096                            notificationSuppression.getSuppressNotifyNodeStateKeys(reqVal),
097                            notificationSuppression.getSuppressNotifyNodeStateKeys(reqDTO)));
098                }
099            assertTrue(atLeastOne);
100    
101        }
102    
103        /**
104         * test that ActionItemS are filtered when a corresponding notification suppression NodeState is
105         * present in the related RouteNodeInstance
106         * 
107         * @throws Exception
108         */
109        @Test
110        public void testActionItemFiltering() throws Exception {
111            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
112                    TEST_DOC_TYPE);
113            document.route("");
114            List<ActionRequest> requests = document.getRootActionRequests();
115            assertTrue("there must be ActionRequestDTOs to test!", requests != null && requests.size() > 0);
116    
117            NotificationSuppression notificationSuppression = new NotificationSuppression();
118    
119            boolean atLeastOne = false;
120            for (ActionRequest reqDTO : requests) {
121                if (reqDTO.getParentActionRequestId() == null) {
122                    atLeastOne = true;
123    
124                    ActionRequestValue reqVal = ActionRequestValue.from(reqDTO);
125    
126                    List<ActionItem> actionItems = new ArrayList<ActionItem>();
127                    actionItems.add(KEWServiceLocator.getActionListService().createActionItemForActionRequest(reqVal));
128    
129                    RouteNodeInstance routeNodeInstance = new RouteNodeInstance();
130    
131                    // if there is no notification suppression state, nothing should be filtered
132                    int actionItemsCount = actionItems.size();
133                    notificationSuppression.filterNotificationSuppressedActionItems(actionItems, routeNodeInstance);
134                    assertTrue(actionItemsCount == actionItems.size());
135    
136                    // if there is a suppression state for this ActionRequestValue, the ActionItem(s) should be filtered
137                    notificationSuppression.addNotificationSuppression(routeNodeInstance, reqVal);
138                    notificationSuppression.filterNotificationSuppressedActionItems(actionItems, routeNodeInstance);
139                    assertTrue(actionItems.size() == 0);
140                }
141            }
142            assertTrue(atLeastOne);
143    
144        }
145    
146        /**
147         * This method tests email suppression soup to nuts by routing / requeueing documents and
148         * meddling with the responsible parties.
149         * 
150         * @throws Exception
151         */
152        @Test
153        public void testSuppression() throws Exception {
154            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
155                    TEST_DOC_TYPE);
156            document.route("");
157    
158            assertTrue("the responsible party should have been notified",
159                    1 == getMockEmailService().immediateReminderEmailsSent("user1", document.getDocumentId(),
160                            KewApiConstants.ACTION_REQUEST_COMPLETE_REQ));
161    
162            getMockEmailService().resetReminderCounts();
163    
164            List<RuleBaseValues> existingRules =
165                    KEWServiceLocator.getRuleService().fetchAllCurrentRulesForTemplateDocCombination(TEST_RULE_TEMPLATE,
166                            TEST_DOC_TYPE);
167            assertNotNull(existingRules);
168            assertEquals(1, existingRules.size());
169    
170            RuleBaseValues originalRule = existingRules.get(0);
171            assertTrue("Original rule should be current.", originalRule.getCurrentInd());
172    
173            List<RuleResponsibilityBo> originalResps = originalRule.getRuleResponsibilities();
174            assertEquals(1, originalResps.size());
175    
176            RuleResponsibilityBo originalResp = originalResps.get(0);
177    
178            RuleTemplateBo ruleTemplate = KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(
179                    TEST_RULE_TEMPLATE);
180            assertNotNull(ruleTemplate);
181            assertNotNull(ruleTemplate.getId());
182            assertFalse(StringUtils.isEmpty(ruleTemplate.getName()));
183    
184            // save a new rule delegation
185            RuleDelegationBo ruleDelegation = new RuleDelegationBo();
186            ruleDelegation.setResponsibilityId(originalResp.getResponsibilityId());
187            ruleDelegation.setDelegationType(DelegationType.PRIMARY);
188            RuleBaseValues rule = new RuleBaseValues();
189            ruleDelegation.setDelegationRule(rule);
190            rule.setDelegateRule(true);
191            rule.setActive(true);
192            rule.setCurrentInd(true);
193            rule.setDocTypeName(originalRule.getDocTypeName());
194            rule.setRuleTemplateId(ruleTemplate.getDelegationTemplateId());
195            rule.setRuleTemplate(ruleTemplate);
196            rule.setDescription("Description of this delegate rule");
197            rule.setForceAction(true);
198            RuleResponsibilityBo delegationResponsibility = new RuleResponsibilityBo();
199            rule.getRuleResponsibilities().add(delegationResponsibility);
200            delegationResponsibility.setRuleBaseValues(rule);
201            delegationResponsibility.setRuleResponsibilityName("user2");
202            delegationResponsibility.setRuleResponsibilityType(KewApiConstants.RULE_RESPONSIBILITY_WORKFLOW_ID);
203    
204            // reset mock service test data
205            getMockEmailService().resetReminderCounts();
206            MockDocumentRefreshQueueImpl.clearRequeuedDocumentIds();
207    
208            // this *SHOULD* requeue
209            KEWServiceLocator.getRuleService().saveRuleDelegation(ruleDelegation, true);
210    
211            assertTrue("document should have been requeued",
212                    MockDocumentRefreshQueueImpl.getRequeuedDocumentIds().contains(document.getDocumentId()));
213    
214            assertTrue("should have notified user2",
215                    1 == getMockEmailService().immediateReminderEmailsSent("user2", document.getDocumentId(),
216                            KewApiConstants.ACTION_REQUEST_COMPLETE_REQ));
217            assertTrue("the responsible party that is delegating should not be notified",
218                    0 == getMockEmailService().immediateReminderEmailsSent("user1", document.getDocumentId(),
219                            KewApiConstants.ACTION_REQUEST_COMPLETE_REQ));
220    
221            getMockEmailService().resetReminderCounts();
222    
223            // now if we requeue, nobody should get notified
224            MockDocumentRefreshQueueImpl.clearRequeuedDocumentIds();
225            String applicationId = KEWServiceLocator.getRouteHeaderService().getApplicationIdByDocumentId(
226                    document.getDocumentId());
227            MessageServiceNames.getDocumentRequeuerService(
228                    (applicationId != null) ? applicationId : CoreConfigHelper.getApplicationId(),
229                    document.getDocumentId(), 0).refreshDocument(document.getDocumentId());
230    
231            assertTrue("nobody should have been notified",
232                    0 == getMockEmailService().immediateReminderEmailsSent("user2", document.getDocumentId(),
233                            KewApiConstants.ACTION_REQUEST_COMPLETE_REQ));
234            assertTrue("nobody should have been notified",
235                    0 == getMockEmailService().immediateReminderEmailsSent("user1", document.getDocumentId(),
236                            KewApiConstants.ACTION_REQUEST_COMPLETE_REQ));
237    
238            getMockEmailService().resetReminderCounts();
239        }
240    
241        private MockEmailNotificationService getMockEmailService() {
242            return (MockEmailNotificationService) KEWServiceLocator.getActionListEmailService();
243        }
244    }