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    }