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.document;
017
018import org.apache.commons.lang3.StringUtils;
019import org.kuali.rice.core.api.uif.RemotableAttributeError;
020import org.kuali.rice.core.api.util.RiceKeyConstants;
021import org.kuali.rice.kew.api.KEWPropertyConstants;
022import org.kuali.rice.kew.api.KewApiConstants;
023import org.kuali.rice.kew.api.KewApiServiceLocator;
024import org.kuali.rice.kew.api.rule.RuleTemplate;
025import org.kuali.rice.kew.api.rule.RuleTemplateAttribute;
026import org.kuali.rice.kew.doctype.service.DocumentTypeService;
027import org.kuali.rice.kew.rule.GroupRuleResponsibility;
028import org.kuali.rice.kew.rule.PersonRuleResponsibility;
029import org.kuali.rice.kew.rule.RuleBaseValues;
030import org.kuali.rice.kew.rule.RuleResponsibilityBo;
031import org.kuali.rice.kew.rule.WorkflowRuleAttributeRows;
032import org.kuali.rice.kew.rule.bo.RuleAttribute;
033import org.kuali.rice.kew.rule.web.WebRuleUtils;
034import org.kuali.rice.kew.service.KEWServiceLocator;
035import org.kuali.rice.kns.document.MaintenanceDocument;
036import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
037import org.kuali.rice.krad.bo.PersistableBusinessObject;
038
039import java.util.List;
040import java.util.Map;
041
042/**
043 * This is a description of what this class does - Garey don't forget to fill this in.
044 *
045 * @author Kuali Rice Team (rice.collab@kuali.org)
046 *
047 */
048public class RoutingRuleMaintainableBusRule extends MaintenanceDocumentRuleBase {
049
050        /**
051         * This overridden method ...
052         *
053         * @see org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.krad.maintenance.MaintenanceDocument)
054         */
055        @Override
056        protected boolean processCustomSaveDocumentBusinessRules(
057                        MaintenanceDocument document) {
058
059                boolean isValid = true;
060
061                RuleBaseValues ruleBaseValues = this.getRuleBaseValues(document);
062                RuleBaseValues oldRuleBaseValues = this.getOldRuleBaseValues(document);
063                
064                isValid &= this.populateErrorMap(ruleBaseValues);
065
066
067                return isValid;
068        }
069
070        protected RuleBaseValues getRuleBaseValues(MaintenanceDocument document){
071                return (RuleBaseValues)document.getNewMaintainableObject().getBusinessObject();
072        }
073        
074        protected RuleBaseValues getOldRuleBaseValues(MaintenanceDocument document){
075                return (RuleBaseValues)document.getOldMaintainableObject().getBusinessObject();
076        }
077        
078
079        protected void populateErrorMap(Map<String,String> errorMap){
080                for(Map.Entry<String, String> entry : errorMap.entrySet()){
081                        this.putFieldError(entry.getKey(), entry.getValue());
082                }
083        }
084
085        /**
086         * This overridden method ...
087         *
088         * @see org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.krad.maintenance.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
089         */
090        @Override
091        public boolean processCustomAddCollectionLineBusinessRules(
092                        MaintenanceDocument document, String collectionName,
093                        PersistableBusinessObject line) {
094
095                boolean isValid = true;
096
097                if(getPersonSectionName().equals(collectionName)){
098                        PersonRuleResponsibility pr = (PersonRuleResponsibility)line;
099                        String name = pr.getPrincipalName();
100
101                        if(!personExists(name)){
102                                isValid &= false;
103                                this.putFieldError(getPersonSectionName(), "error.document.personResponsibilities.principleDoesNotExist");
104                        }
105                }else if(getGroupSectionName().equals(collectionName)){
106                        GroupRuleResponsibility gr = (GroupRuleResponsibility)line;
107                        if(!groupExists(gr.getNamespaceCode(), gr.getName())){
108                                isValid &= false;
109                                this.putFieldError(getGroupSectionName(), "error.document.personResponsibilities.groupDoesNotExist");
110                        }
111                }
112
113                return isValid;
114        }
115
116        protected String getPersonSectionName(){
117                return KEWPropertyConstants.PERSON_RESP_SECTION;
118        }
119        protected String getGroupSectionName(){
120                return KEWPropertyConstants.GROUP_RESP_SECTION;
121        }
122
123        protected boolean personExists(String principalName){
124                boolean bRet = false;
125                try{
126                        KEWServiceLocator.getIdentityHelperService().getIdForPrincipalName(principalName);
127                        bRet = true;
128                }catch(Exception ex){
129                        bRet = false;
130                        //ex.printStackTrace();
131                }
132
133                return bRet;
134        }
135
136        protected boolean groupExists(String namespaceCode, String groupName){
137                boolean bRet = false;
138                try{
139                        KEWServiceLocator.getIdentityHelperService().getGroupByName(namespaceCode, groupName);
140                        bRet = true;
141                }catch(Exception ex){
142                        bRet = false;
143                        //ex.printStackTrace();
144                }
145                return bRet;
146        }
147
148        protected boolean populateErrorMap(RuleBaseValues ruleBaseValues){
149
150                boolean isValid = true;
151
152                if (getDocumentTypeService().findByName(ruleBaseValues.getDocTypeName()) == null) {
153            putFieldError("docTypeName", "doctype.documenttypeservice.doctypename.required");
154            isValid = false;
155        }
156        if(ruleBaseValues.getName() != null){
157                if(ruleExists(ruleBaseValues)){
158                        putFieldError("name", "routetemplate.ruleservice.name.unique");
159                isValid = false;
160                }
161        }
162
163        /*
164         * Logic: If both from and to dates exist, make sure toDate is after fromDate
165         */
166        if(ruleBaseValues.getToDateValue() != null && ruleBaseValues.getFromDateValue() != null){
167                if (ruleBaseValues.getToDateValue().before(ruleBaseValues.getFromDateValue())) {
168                        putFieldError("toDate", "error.document.maintainableItems.toDate");
169                        isValid = false;
170            }
171        }
172
173                if(!setRuleAttributeErrors(ruleBaseValues)){
174                        isValid = false;
175                }
176
177                // This doesn't map directly to a single field. It's either the person or the group tab
178                if ( ruleBaseValues.getPersonResponsibilities().isEmpty()
179                        && ruleBaseValues.getGroupResponsibilities().isEmpty()
180                        && ruleBaseValues.getRoleResponsibilities().isEmpty() ) {
181            putFieldError("Persons", "error.document.responsibility.required");
182            isValid = false;                
183        } else {
184            for (PersonRuleResponsibility responsibility : ruleBaseValues.getPersonResponsibilities()) {
185                if ( StringUtils.isBlank( responsibility.getPrincipalName() ) || KEWServiceLocator.getIdentityHelperService().getIdForPrincipalName(responsibility.getPrincipalName()) == null ) {
186                    putFieldError("Persons", "routetemplate.ruleservice.user.invalid");
187                    isValid = false;
188                    break;
189                }
190            }
191            for (GroupRuleResponsibility responsibility : ruleBaseValues.getGroupResponsibilities()) {
192                if ( StringUtils.isBlank( responsibility.getNamespaceCode() ) 
193                        || StringUtils.isBlank( responsibility.getName() )
194                        || getGroupService().getGroupByNamespaceCodeAndName(responsibility.getNamespaceCode(), responsibility.getName() ) == null ) {
195                        putFieldError("Groups", "routetemplate.ruleservice.workgroup.invalid");
196                        isValid = false;
197                        break;
198                }
199            }
200        }
201
202        return isValid;
203        }
204
205        protected boolean ruleExists(RuleBaseValues rule){
206                boolean bRet = false;
207
208                RuleBaseValues tmp = KEWServiceLocator.getRuleService().getRuleByName(rule.getName());
209
210                if(tmp != null) {
211                    if ((rule.getPreviousRuleId() == null)
212                         || (rule.getPreviousRuleId() != null
213                            && !rule.getPreviousRuleId().equals(tmp.getId()))) {
214                            bRet = true;
215                    }
216                }
217
218                return bRet;
219        }
220
221        protected DocumentTypeService getDocumentTypeService() {
222        return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
223    }
224
225
226        protected boolean setRuleAttributeErrors(RuleBaseValues rule){
227
228                boolean isValid = true;
229
230                RuleTemplate ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplate(rule.getRuleTemplateId());
231
232                /** Populate rule extension values * */
233                for (RuleTemplateAttribute ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
234            if (!RuleAttribute.isWorkflowAttribute(ruleTemplateAttribute.getRuleAttribute().getType())) {
235                continue;
236            }
237            Map<String, String> parameterMap = WebRuleUtils.getFieldMapForRuleTemplateAttribute(rule, ruleTemplateAttribute);
238            WorkflowRuleAttributeRows rows =
239                    KEWServiceLocator.getWorkflowRuleAttributeMediator().getRuleRows(parameterMap, ruleTemplateAttribute);
240
241                        // TODO hook validation of rule data into PreRules
242            List<RemotableAttributeError> errors = rows.getValidationErrors();
243                        if (!errors.isEmpty()) {
244                isValid = false;
245                                for(RemotableAttributeError error: errors){
246                                    this.putFieldError("RuleAttributes", RiceKeyConstants.ERROR_CUSTOM, error.getMessage());
247                                }
248                        }
249                }
250                return isValid;
251
252        }
253
254}