001/** 002 * Copyright 2005-2017 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.impl.rule; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.log4j.Logger; 020import org.joda.time.DateTime; 021import org.kuali.rice.core.api.criteria.Predicate; 022import org.kuali.rice.core.api.criteria.QueryByCriteria; 023import org.kuali.rice.core.api.criteria.QueryResults; 024import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 025import org.kuali.rice.core.api.exception.RiceIllegalStateException; 026import org.kuali.rice.kew.api.KewApiServiceLocator; 027import org.kuali.rice.kew.api.doctype.DocumentTypeService; 028import org.kuali.rice.kew.api.rule.Rule; 029import org.kuali.rice.kew.api.rule.RuleDelegation; 030import org.kuali.rice.kew.api.rule.RuleQueryResults; 031import org.kuali.rice.kew.api.rule.RuleReportCriteria; 032import org.kuali.rice.kew.api.rule.RuleResponsibility; 033import org.kuali.rice.kew.api.rule.RuleService; 034import org.kuali.rice.kew.api.rule.RuleTemplate; 035import org.kuali.rice.kew.api.rule.RuleTemplateQueryResults; 036import org.kuali.rice.kew.rule.RuleBaseValues; 037import org.kuali.rice.kew.rule.RuleDelegationBo; 038import org.kuali.rice.kew.rule.RuleResponsibilityBo; 039import org.kuali.rice.kew.rule.bo.RuleTemplateBo; 040import org.kuali.rice.kew.service.KEWServiceLocator; 041import org.kuali.rice.kim.impl.common.attribute.AttributeTransform; 042import org.kuali.rice.krad.data.DataObjectService; 043 044import javax.jws.WebParam; 045import java.util.ArrayList; 046import java.util.Collection; 047import java.util.List; 048 049import static org.kuali.rice.core.api.criteria.PredicateFactory.*; 050 051 052/** 053 * 054 * @author Kuali Rice Team (rice.collab@kuali.org) 055 * 056 */ 057public class RuleServiceImpl implements RuleService { 058 059 private static final Logger LOG = Logger.getLogger(RuleServiceImpl.class); 060 061 private DataObjectService dataObjectService; 062 063 @Override 064 public Rule getRule(String id) throws RiceIllegalArgumentException, RiceIllegalStateException{ 065 incomingParamCheck("id", id); 066 RuleBaseValues rbv = getDataObjectService().find(RuleBaseValues.class, id); 067 if (rbv == null) { 068 throw new RiceIllegalStateException("Rule with specified id: " + id + " does not exist"); 069 } 070 return RuleBaseValues.to(rbv); 071 } 072 073 @Override 074 public Rule getRuleByName(String name) { 075 incomingParamCheck("name", name); 076 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(); 077 builder.setPredicates( 078 equal("name", name), 079 equal("currentInd", Boolean.TRUE) 080 ); 081 QueryResults<RuleBaseValues> results = getDataObjectService().findMatching(RuleBaseValues.class, builder.build()); 082 if (results.getResults().isEmpty()) { 083 throw new RiceIllegalStateException("Rule with specified name: " + name + " does not exist"); 084 } 085 if (results.getResults().size() > 1) { 086 throw new RiceIllegalStateException("Found more than one current rule with specified name " + name); 087 } 088 return RuleBaseValues.to(results.getResults().get(0)); 089 } 090 091 @Override 092 public List<Rule> getRulesByTemplateId( 093 @WebParam(name = "templateId") String templateId) throws RiceIllegalArgumentException { 094 incomingParamCheck("templateId", templateId); 095 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(); 096 builder.setPredicates(equal("ruleTemplateId", templateId), equal("currentInd", Boolean.TRUE)); 097 QueryResults<RuleBaseValues> results = getDataObjectService().findMatching(RuleBaseValues.class, builder.build()); 098 final List<Rule> rules = new ArrayList<Rule>(); 099 for (RuleBaseValues bo : results.getResults()) { 100 rules.add(Rule.Builder.create(bo).build()); 101 } 102 return rules; 103 } 104 105 @Override 106 public List<Rule> getRulesByTemplateNameAndDocumentTypeName(String templateName, String documentTypeName) { 107 return getRulesByTemplateNameAndDocumentTypeNameAndEffectiveDate(templateName, documentTypeName, null); 108 } 109 110 @Override 111 public List<Rule> getRulesByTemplateNameAndDocumentTypeNameAndEffectiveDate(String templateName, String documentTypeName, 112 DateTime effectiveDate) 113 throws RiceIllegalArgumentException { 114 QueryByCriteria.Builder query = QueryByCriteria.Builder.create(); 115 List<Predicate> predicates = new ArrayList<Predicate>(); 116 predicates.add(equal("ruleTemplate.name", templateName)); 117 118 // Check all document types in ancestry 119 DocumentTypeService documentTypeService = KewApiServiceLocator.getDocumentTypeService(); 120 org.kuali.rice.kew.api.doctype.DocumentType dt = documentTypeService.getDocumentTypeByName(documentTypeName); 121 List<String> documentTypeAncestryNames = new ArrayList<String>(); 122 while (dt != null) { 123 documentTypeAncestryNames.add(dt.getName()); 124 dt = dt.getParentId() == null ? null : documentTypeService.getDocumentTypeById(dt.getParentId()); 125 } 126 predicates.add(in("docTypeName", documentTypeAncestryNames.toArray( 127 new String[documentTypeAncestryNames.size()]))); 128 DateTime currentTime = new DateTime(); 129 predicates.add(and( 130 or(isNull("fromDateValue"), lessThanOrEqual("fromDateValue", currentTime)), 131 or(isNull("toDateValue"), greaterThan("toDateValue", currentTime)) 132 )); 133 predicates.add(equal("active", Boolean.TRUE)); 134 predicates.add(equal("delegateRule", Boolean.FALSE)); 135 predicates.add(equal("templateRuleInd", Boolean.FALSE)); 136 if (effectiveDate != null) { 137 predicates.add( 138 and( 139 or(isNull("activationDate"), lessThanOrEqual("activationDate", effectiveDate)), 140 or(isNull("deactivationDate"), greaterThan("deactivationDate", effectiveDate)) 141 )); 142 } else { 143 predicates.add(equal("currentInd", Boolean.TRUE)); 144 } 145 Predicate p = and(predicates.toArray(new Predicate[]{})); 146 query.setPredicates(p); 147 return KewApiServiceLocator.getRuleService().findRules(query.build()).getResults(); 148 } 149 150 @Override 151 public RuleQueryResults findRules(QueryByCriteria queryByCriteria) { 152 if (queryByCriteria == null) { 153 throw new RiceIllegalArgumentException("queryByCriteria is null"); 154 } 155 156 QueryResults<RuleBaseValues> results = dataObjectService.findMatching(RuleBaseValues.class, 157 AttributeTransform.getInstance().apply(queryByCriteria)); 158 159 RuleQueryResults.Builder builder = RuleQueryResults.Builder.create(); 160 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 161 builder.setTotalRowCount(results.getTotalRowCount()); 162 163 final List<Rule.Builder> ims = new ArrayList<Rule.Builder>(); 164 for (RuleBaseValues bo : results.getResults()) { 165 ims.add(Rule.Builder.create(RuleBaseValues.to(bo))); 166 } 167 168 builder.setResults(ims); 169 return builder.build(); 170 } 171 172 @Override 173 public List<Rule> ruleReport(RuleReportCriteria ruleReportCriteria) { 174 incomingParamCheck(ruleReportCriteria, "ruleReportCriteria"); 175 if ( LOG.isDebugEnabled() ) { 176 LOG.debug("Executing rule report [responsibleUser=" + ruleReportCriteria.getResponsiblePrincipalId() + ", responsibleWorkgroup=" + 177 ruleReportCriteria.getResponsibleGroupId() + "]"); 178 } 179 Collection<RuleBaseValues> rulesFound = KEWServiceLocator.getRuleService().searchByTemplate( 180 ruleReportCriteria.getDocumentTypeName(), ruleReportCriteria.getRuleTemplateName(), 181 ruleReportCriteria.getRuleDescription(), ruleReportCriteria.getResponsibleGroupId(), 182 ruleReportCriteria.getResponsiblePrincipalId(), Boolean.valueOf(ruleReportCriteria.isConsiderGroupMembership()), 183 Boolean.valueOf(ruleReportCriteria.isIncludeDelegations()), Boolean.valueOf(ruleReportCriteria.isActive()), ruleReportCriteria.getRuleExtensions(), 184 ruleReportCriteria.getActionRequestCodes()); 185 List<org.kuali.rice.kew.api.rule.Rule> returnableRules = new ArrayList<Rule>(rulesFound.size()); 186 for (RuleBaseValues rule : rulesFound) { 187 returnableRules.add(RuleBaseValues.to(rule)); 188 } 189 return returnableRules; 190 } 191 192 @Override 193 public RuleTemplate getRuleTemplate(@WebParam(name = "id") String id) { 194 incomingParamCheck("id", id); 195 RuleTemplateBo template = dataObjectService.find(RuleTemplateBo.class, id); 196 if (template == null) { 197 throw new RiceIllegalStateException("RuleTemplate with specified id: " + id + " does not exist"); 198 } 199 return RuleTemplateBo.to(template); 200 } 201 202 @Override 203 public RuleTemplate getRuleTemplateByName(@WebParam(name = "name") String name) { 204 incomingParamCheck("name", name); 205 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(); 206 builder.setPredicates(equal("name", name)); 207 QueryResults<RuleTemplateBo> results = dataObjectService.findMatching(RuleTemplateBo.class, builder.build()); 208 if (results.getResults().isEmpty()) { 209 throw new RiceIllegalStateException("Rule Template with specified name: " + name + " does not exist"); 210 } 211 if (results.getResults().size() > 1) { 212 throw new RiceIllegalStateException("Found more than one rule template with specified name " + name); 213 } 214 return RuleTemplateBo.to(results.getResults().get(0)); 215 } 216 217 @Override 218 public RuleTemplateQueryResults findRuleTemplates( 219 @WebParam(name = "query") QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException { 220 if (queryByCriteria == null) { 221 throw new RiceIllegalArgumentException("queryByCriteria is null"); 222 } 223 224 QueryResults<RuleTemplateBo> results = dataObjectService.findMatching(RuleTemplateBo.class, 225 AttributeTransform.getInstance().apply(queryByCriteria)); 226 227 RuleTemplateQueryResults.Builder builder = RuleTemplateQueryResults.Builder.create(); 228 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 229 builder.setTotalRowCount(results.getTotalRowCount()); 230 231 final List<RuleTemplate.Builder> ims = new ArrayList<RuleTemplate.Builder>(); 232 for (RuleTemplateBo bo : results.getResults()) { 233 ims.add(RuleTemplate.Builder.create(RuleTemplateBo.to(bo))); 234 } 235 236 builder.setResults(ims); 237 return builder.build(); 238 } 239 240 @Override 241 public RuleResponsibility getRuleResponsibility(String responsibilityId) { 242 incomingParamCheck("responsibilityId", responsibilityId); 243 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(); 244 builder.setPredicates(equal("responsibilityId", responsibilityId)); 245 QueryResults<RuleResponsibilityBo> results = dataObjectService.findMatching(RuleResponsibilityBo.class, builder.build()); 246 if (results.getResults().isEmpty()) { 247 throw new RiceIllegalStateException("RuleResponsibility with specified id: " + responsibilityId + " does not exist"); 248 } 249 if (results.getResults().size() > 1) { 250 throw new RiceIllegalStateException("Found more than one rule responsibility with responsibility id: " + responsibilityId); 251 } 252 return RuleResponsibilityBo.to(results.getResults().get(0)); 253 } 254 255 @Override 256 public List<RuleDelegation> getRuleDelegationsByResponsibiltityId( 257 @WebParam(name = "id") String id) throws RiceIllegalArgumentException, RiceIllegalStateException { 258 incomingParamCheck("id", id); 259 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(); 260 builder.setPredicates( 261 equal("responsibilityId", id), 262 equal("delegationRule.currentInd", Boolean.TRUE) 263 ); 264 QueryResults<RuleDelegationBo> results = dataObjectService.findMatching(RuleDelegationBo.class, builder.build()); 265 List<RuleDelegation> ruleDelegations = new ArrayList<RuleDelegation>(); 266 for (RuleDelegationBo bo : results.getResults()) { 267 ruleDelegations.add(RuleDelegationBo.to(bo)); 268 } 269 return ruleDelegations; 270 } 271 272 private void incomingParamCheck(Object object, String name) { 273 if (object == null) { 274 throw new RiceIllegalArgumentException(name + " was null"); 275 } else if (object instanceof String 276 && StringUtils.isBlank((String) object)) { 277 throw new RiceIllegalArgumentException(name + " was blank"); 278 } 279 } 280 281 public DataObjectService getDataObjectService() { 282 return dataObjectService; 283 } 284 285 public void setDataObjectService(DataObjectService dataObjectService) { 286 this.dataObjectService = dataObjectService; 287 } 288 289}