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