001 /* 002 * Copyright 2007 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.removereplace.service.impl; 017 018 import java.util.ArrayList; 019 import java.util.List; 020 021 import org.apache.commons.lang.StringUtils; 022 import org.jdom.Element; 023 import org.kuali.rice.kew.exception.WorkflowException; 024 import org.kuali.rice.kew.exception.WorkflowRuntimeException; 025 import org.kuali.rice.kew.export.ExportDataSet; 026 import org.kuali.rice.kew.removereplace.RemoveReplaceDocument; 027 import org.kuali.rice.kew.removereplace.RuleTarget; 028 import org.kuali.rice.kew.removereplace.WorkgroupTarget; 029 import org.kuali.rice.kew.removereplace.dao.RemoveReplaceDocumentDAO; 030 import org.kuali.rice.kew.removereplace.service.RemoveReplaceDocumentService; 031 import org.kuali.rice.kew.rule.RuleBaseValues; 032 import org.kuali.rice.kew.rule.service.RuleService; 033 import org.kuali.rice.kew.service.KEWServiceLocator; 034 import org.kuali.rice.kew.service.WorkflowDocument; 035 import org.kuali.rice.kew.user.WorkflowUserId; 036 import org.kuali.rice.kew.web.session.UserSession; 037 import org.kuali.rice.kim.bo.Group; 038 import org.kuali.rice.kim.bo.Person; 039 import org.kuali.rice.kim.service.KIMServiceLocator; 040 041 042 public class RemoveReplaceDocumentServiceImpl implements RemoveReplaceDocumentService { 043 044 private RemoveReplaceDocumentDAO dao; 045 046 public void save(RemoveReplaceDocument document) { 047 if (document.getDocumentId() == null) { 048 throw new WorkflowRuntimeException("The given document has a null document ID. Please assign a document ID prior to saving."); 049 } 050 dao.save(document); 051 } 052 053 public RemoveReplaceDocument findById(Long documentId) { 054 return dao.findById(documentId); 055 } 056 057 public void blanketApprove(RemoveReplaceDocument document, UserSession user, String annotation) { 058 save(document); 059 try { 060 WorkflowDocument workflowDoc = new WorkflowDocument(user.getPrincipalId(), document.getDocumentId()); 061 constructTitle(document, workflowDoc); 062 attachDocumentContent(document, workflowDoc); 063 workflowDoc.blanketApprove(annotation); 064 } catch (WorkflowException e) { 065 throw new WorkflowRuntimeException(e); 066 } 067 } 068 069 public void route(RemoveReplaceDocument document, UserSession user, String annotation) { 070 save(document); 071 try { 072 WorkflowDocument workflowDoc = new WorkflowDocument(user.getPrincipalId(), document.getDocumentId()); 073 constructTitle(document, workflowDoc); 074 attachDocumentContent(document, workflowDoc); 075 workflowDoc.routeDocument(annotation); 076 } catch (WorkflowException e) { 077 throw new WorkflowRuntimeException(e); 078 } 079 } 080 081 protected void constructTitle(RemoveReplaceDocument document, WorkflowDocument workflowDoc) throws WorkflowException { 082 Person user = KIMServiceLocator.getPersonService().getPerson(document.getUserWorkflowId()); 083 StringBuffer title = new StringBuffer(); 084 if (document.getOperation().equals(RemoveReplaceDocument.REMOVE_OPERATION)) { 085 title.append("Removing " + user.getPrincipalName() + " from "); 086 } else if (document.getOperation().equals(RemoveReplaceDocument.REPLACE_OPERATION)) { 087 Person replaceWithUser = KIMServiceLocator.getPersonService().getPerson(document.getReplacementUserWorkflowId()); 088 title.append("Replacing " + user.getPrincipalName() + " with " + replaceWithUser.getPrincipalName() + " in "); 089 } 090 title.append(document.getRuleTargets().size() + " rules and " + document.getWorkgroupTargets().size() + " workgroups"); 091 workflowDoc.setTitle(title.toString()); 092 } 093 094 /** 095 * Attaches document content to the WorkflowDocument for the given RemoveReplaceDocument. 096 */ 097 protected void attachDocumentContent(RemoveReplaceDocument document, WorkflowDocument workflowDoc) { 098 try { 099 Person user = KIMServiceLocator.getPersonService().getPerson(document.getUserWorkflowId()); 100 Element rootElement = new Element("removeReplaceUserDocument"); 101 Element removeReplaceElement = null; 102 if (document.getOperation().equals(RemoveReplaceDocument.REMOVE_OPERATION)) { 103 removeReplaceElement = new Element("remove"); 104 Element userElement = new Element("user"); 105 userElement.setText(user.getPrincipalName()); 106 removeReplaceElement.addContent(userElement); 107 } else if (document.getOperation().equals(RemoveReplaceDocument.REPLACE_OPERATION)) { 108 removeReplaceElement = new Element("replace"); 109 Element userElement = new Element("user"); 110 userElement.setText(user.getPrincipalName()); 111 removeReplaceElement.addContent(userElement); 112 Element replaceWithElement = new Element("replaceWith"); 113 Person replaceWithUser = KIMServiceLocator.getPersonService().getPerson(document.getReplacementUserWorkflowId()); 114 replaceWithElement.setText(replaceWithUser.getPrincipalName()); 115 removeReplaceElement.addContent(replaceWithElement); 116 } else { 117 throw new WorkflowRuntimeException("Invalid remove/replace operation specified: " + document.getOperation()); 118 } 119 rootElement.addContent(removeReplaceElement); 120 121 // add rules 122 List<RuleBaseValues> rules = loadRules(document); 123 if (!rules.isEmpty()) { 124 ExportDataSet ruleDataSet = new ExportDataSet(); 125 ruleDataSet.getRules().addAll(rules); 126 Element rulesElement = KEWServiceLocator.getRuleService().export(ruleDataSet); 127 removeReplaceElement.addContent(rulesElement); 128 } 129 130 // add workgroups 131 List<? extends Group> workgroups = loadWorkgroups(document); 132 if (!workgroups.isEmpty()) { 133 ExportDataSet workgroupDataSet = new ExportDataSet(); 134 workgroupDataSet.getGroups().addAll(workgroups); 135 if (true) { 136 throw new UnsupportedOperationException("TODO: please implement this once we have xml export of groups working in KIM!"); 137 } 138 } 139 // Element workgroupsElement = KEWServiceLocator.getWorkgroupService().export(workgroupDataSet); 140 // removeReplaceElement.addContent(workgroupsElement); 141 // } 142 // workflowDoc.setApplicationContent(XmlHelper.jotNode(rootElement)); 143 } catch (Exception e) { 144 throw new WorkflowRuntimeException(e); 145 } 146 } 147 148 protected List<? extends Group> loadWorkgroups(RemoveReplaceDocument document) { 149 List<Group> workgroups = new ArrayList<Group>(); 150 for (WorkgroupTarget workgroupTarget : document.getWorkgroupTargets()) { 151 Group group = KIMServiceLocator.getIdentityManagementService().getGroup(workgroupTarget.getWorkgroupId()); 152 if (group == null) { 153 throw new WorkflowRuntimeException("Failed to locate workgroup to change with id " + workgroupTarget.getWorkgroupId()); 154 } 155 workgroups.add(group); 156 } 157 return workgroups; 158 } 159 160 protected List<RuleBaseValues> loadRules(RemoveReplaceDocument document) { 161 List<RuleBaseValues> rules = new ArrayList<RuleBaseValues>(); 162 for (RuleTarget ruleTarget : document.getRuleTargets()) { 163 RuleBaseValues rule = KEWServiceLocator.getRuleService().findRuleBaseValuesById(ruleTarget.getRuleId()); 164 if (rule == null) { 165 throw new WorkflowRuntimeException("Failed to locate rule to change with id " + ruleTarget.getRuleId()); 166 } 167 rules.add(rule); 168 } 169 return rules; 170 } 171 172 173 public void finalize(Long documentId) { 174 RemoveReplaceDocument document = findById(documentId); 175 176 if (document == null) { 177 throw new WorkflowRuntimeException("Failed to locate the RemoveReplaceDocument with id " + documentId); 178 } 179 if (StringUtils.isEmpty(document.getUserWorkflowId())) { 180 throw new WorkflowRuntimeException("RemoveReplaceDocument does not have a user id."); 181 } 182 183 List<Long> ruleIds = new ArrayList<Long>(); 184 if (document.getRuleTargets() != null) { 185 for (RuleTarget ruleTarget : document.getRuleTargets()) { 186 ruleIds.add(ruleTarget.getRuleId()); 187 } 188 } 189 190 List<String> workgroupIds = new ArrayList<String>(); 191 if (document.getWorkgroupTargets() != null) { 192 for (WorkgroupTarget workgroupTarget : document.getWorkgroupTargets()) { 193 workgroupIds.add(workgroupTarget.getWorkgroupId()); 194 } 195 } 196 197 RuleService ruleService = KEWServiceLocator.getRuleService(); 198 /** 199 * TODO re-implement replacing of group membership using KIM! 200 */ 201 //WorkgroupRoutingService workgroupRoutingService = KEWServiceLocator.getWorkgroupRoutingService(); 202 try { 203 if (RemoveReplaceDocument.REPLACE_OPERATION.equals(document.getOperation())) { 204 if (StringUtils.isEmpty(document.getReplacementUserWorkflowId())) { 205 throw new WorkflowRuntimeException("Replacement operation was indicated but RemoveReplaceDocument does not have a replacement user id."); 206 } 207 ruleService.replaceRuleInvolvement(new WorkflowUserId(document.getUserWorkflowId()), new WorkflowUserId(document.getReplacementUserWorkflowId()), ruleIds, documentId); 208 //workgroupRoutingService.replaceWorkgroupInvolvement(new WorkflowUserId(document.getUserWorkflowId()), new WorkflowUserId(document.getReplacementUserWorkflowId()), workgroupIds, documentId); 209 } else if (RemoveReplaceDocument.REMOVE_OPERATION.equals(document.getOperation())) { 210 ruleService.removeRuleInvolvement(new WorkflowUserId(document.getUserWorkflowId()), ruleIds, documentId); 211 //workgroupRoutingService.removeWorkgroupInvolvement(new WorkflowUserId(document.getUserWorkflowId()), workgroupIds, documentId); 212 } else { 213 throw new WorkflowRuntimeException("Invalid operation was specified on the RemoveReplaceDocument: " + document.getOperation()); 214 } 215 } catch (WorkflowException e) { 216 throw new WorkflowRuntimeException(e); 217 } 218 } 219 220 public void setRemoveReplaceDocumentDAO(RemoveReplaceDocumentDAO dao) { 221 this.dao = dao; 222 } 223 224 }