001 /** 002 * Copyright 2005-2014 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.krms.impl.repository; 017 018 019 import org.apache.commons.lang.StringUtils; 020 import org.kuali.rice.core.api.exception.RiceIllegalStateException; 021 import org.kuali.rice.krad.service.BusinessObjectService; 022 import org.kuali.rice.krms.api.repository.rule.RuleDefinition; 023 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition; 024 import org.kuali.rice.krms.impl.util.KrmsImplConstants.PropertyNames; 025 026 import java.util.*; 027 028 public final class RuleBoServiceImpl implements RuleBoService { 029 030 private BusinessObjectService businessObjectService; 031 private KrmsAttributeDefinitionService attributeDefinitionService; 032 033 /** 034 * This overridden creates a KRMS Rule in the repository 035 * 036 * @see org.kuali.rice.krms.impl.repository.RuleBoService#createRule(org.kuali.rice.krms.api.repository.rule.RuleDefinition) 037 */ 038 @Override 039 public RuleDefinition createRule(RuleDefinition rule) { 040 if (rule == null){ 041 throw new IllegalArgumentException("rule is null"); 042 } 043 final String nameKey = rule.getName(); 044 final String namespaceKey = rule.getNamespace(); 045 final RuleDefinition existing = getRuleByNameAndNamespace(nameKey, namespaceKey); 046 if (existing != null){ 047 throw new IllegalStateException("the rule to create already exists: " + rule); 048 } 049 RuleBo ruleBo = RuleBo.from(rule); 050 businessObjectService.save(ruleBo); 051 return RuleBo.to(ruleBo); 052 } 053 054 /** 055 * This overridden updates an existing Rule in the Repository 056 * 057 * @see org.kuali.rice.krms.impl.repository.RuleBoService#updateRule(org.kuali.rice.krms.api.repository.rule.RuleDefinition) 058 */ 059 @Override 060 public void updateRule(RuleDefinition rule) { 061 if (rule == null){ 062 throw new IllegalArgumentException("rule is null"); 063 } 064 065 // must already exist to be able to update 066 final String ruleIdKey = rule.getId(); 067 final RuleBo existing = businessObjectService.findBySinglePrimaryKey(RuleBo.class, ruleIdKey); 068 if (existing == null) { 069 throw new IllegalStateException("the rule does not exist: " + rule); 070 } 071 final RuleDefinition toUpdate; 072 if (!existing.getId().equals(rule.getId())){ 073 // if passed in id does not match existing id, correct it 074 final RuleDefinition.Builder builder = RuleDefinition.Builder.create(rule); 075 builder.setId(existing.getId()); 076 toUpdate = builder.build(); 077 } else { 078 toUpdate = rule; 079 } 080 081 // copy all updateable fields to bo 082 RuleBo boToUpdate = RuleBo.from(toUpdate); 083 084 // delete any old, existing attributes 085 Map<String,String> fields = new HashMap<String,String>(1); 086 fields.put(PropertyNames.Rule.RULE_ID, toUpdate.getId()); 087 businessObjectService.deleteMatching(RuleAttributeBo.class, fields); 088 089 // update the rule and create new attributes 090 businessObjectService.save(boToUpdate); 091 } 092 093 @Override 094 public void deleteRule(String ruleId) { 095 if (ruleId == null){ throw new IllegalArgumentException("ruleId is null"); } 096 final RuleDefinition existing = getRuleByRuleId(ruleId); 097 if (existing == null){ throw new IllegalStateException("the Rule to delete does not exists: " + ruleId);} 098 businessObjectService.delete(from(existing)); 099 } 100 101 /** 102 * This method retrieves a rule from the repository given the rule id. 103 * 104 * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleByRuleId(java.lang.String) 105 */ 106 @Override 107 public RuleDefinition getRuleByRuleId(String ruleId) { 108 if (StringUtils.isBlank(ruleId)){ 109 throw new IllegalArgumentException("rule id is null"); 110 } 111 RuleBo bo = businessObjectService.findBySinglePrimaryKey(RuleBo.class, ruleId); 112 return RuleBo.to(bo); 113 } 114 115 /** 116 * This method retrieves a rule from the repository given the name of the rule 117 * and namespace. 118 * 119 * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleByRuleId(java.lang.String) 120 */ 121 @Override 122 public RuleDefinition getRuleByNameAndNamespace(String name, String namespace) { 123 if (StringUtils.isBlank(name)) { 124 throw new IllegalArgumentException("name is blank"); 125 } 126 if (StringUtils.isBlank(namespace)) { 127 throw new IllegalArgumentException("namespace is blank"); 128 } 129 130 final Map<String, Object> map = new HashMap<String, Object>(); 131 map.put("name", name); 132 map.put("namespace", namespace); 133 134 RuleBo myRule = businessObjectService.findByPrimaryKey(RuleBo.class, Collections.unmodifiableMap(map)); 135 return RuleBo.to(myRule); 136 } 137 138 // /** 139 // * This overridden method ... 140 // * 141 // * @see org.kuali.rice.krms.impl.repository.RuleBoService#createRuleAttribute(org.kuali.rice.krms.api.repository.rule.RuleAttribute) 142 // */ 143 // @Override 144 // public void createRuleAttribute(RuleAttribute attribute) { 145 // if (attribute == null){ 146 // throw new IllegalArgumentException("rule attribute is null"); 147 // } 148 // final String attrIdKey = attribute.getId(); 149 // final RuleAttribute existing = getRuleAttributeById(attrIdKey); 150 // if (existing != null){ 151 // throw new IllegalStateException("the rule attribute to create already exists: " + attribute); 152 // } 153 // 154 // businessObjectService.save(RuleAttributeBo.from(attribute)); 155 // } 156 // 157 // /** 158 // * This overridden method ... 159 // * 160 // * @see org.kuali.rice.krms.impl.repository.RuleBoService#updateRuleAttribute(org.kuali.rice.krms.api.repository.rule.RuleAttribute) 161 // */ 162 // @Override 163 // public void updateRuleAttribute(RuleAttribute attribute) { 164 // if (attribute == null){ 165 // throw new IllegalArgumentException("rule attribute is null"); 166 // } 167 // final String attrIdKey = attribute.getId(); 168 // final RuleAttribute existing = getRuleAttributeById(attrIdKey); 169 // if (existing == null) { 170 // throw new IllegalStateException("the rule attribute does not exist: " + attribute); 171 // } 172 // final RuleAttribute toUpdate; 173 // if (!existing.getId().equals(attribute.getRuleId())){ 174 // final RuleAttribute.Builder builder = RuleAttribute.Builder.create(attribute); 175 // builder.setId(existing.getId()); 176 // toUpdate = builder.build(); 177 // } else { 178 // toUpdate = attribute; 179 // } 180 // 181 // businessObjectService.save(RuleAttributeBo.from(toUpdate)); 182 // } 183 // 184 /** 185 * This method ... 186 * 187 * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleAttributeById(java.lang.String) 188 */ 189 public RuleAttributeBo getRuleAttributeById(String attrId) { 190 if (StringUtils.isBlank(attrId)){ 191 return null; 192 } 193 RuleAttributeBo bo = businessObjectService.findBySinglePrimaryKey(RuleAttributeBo.class, attrId); 194 return bo; 195 } 196 197 /** 198 * Converts a immutable {@link RuleDefinition} to its mutable {@link RuleBo} counterpart. 199 * @param rule the immutable object. 200 * @return a {@link RuleBo} the mutable RuleBo. 201 * 202 */ 203 public RuleBo from(RuleDefinition rule) { 204 if (rule == null) { return null; } 205 RuleBo ruleBo = new RuleBo(); 206 ruleBo.setName(rule.getName()); 207 ruleBo.setDescription(rule.getDescription()); 208 ruleBo.setNamespace(rule.getNamespace()); 209 ruleBo.setTypeId(rule.getTypeId()); 210 ruleBo.setPropId(rule.getPropId()); 211 ruleBo.setProposition(PropositionBo.from(rule.getProposition())); 212 ruleBo.setId(rule.getId()); 213 ruleBo.setActive(rule.isActive()); 214 ruleBo.setVersionNumber(rule.getVersionNumber()); 215 // TODO collections, etc. 216 // Set<RuleAttributeBo> attributes = buildAttributeBo(rule); 217 ruleBo.setAttributeBos(buildAttributeBoList(rule)); 218 return ruleBo; 219 } 220 221 private Set<RuleAttributeBo> buildAttributeBo(RuleDefinition im) { 222 Set<RuleAttributeBo> attributes = new HashSet<RuleAttributeBo>(); 223 224 // build a map from attribute name to definition 225 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>(); 226 227 List<KrmsAttributeDefinition> attributeDefinitions = getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId()); 228 229 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) { 230 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition); 231 } 232 233 // for each entry, build a RuleAttributeBo and add it to the set 234 if (im.getAttributes() != null) { 235 for (Map.Entry<String,String> entry : im.getAttributes().entrySet()) { 236 KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey()); 237 238 if (attrDef != null) { 239 RuleAttributeBo attributeBo = new RuleAttributeBo(); 240 attributeBo.setRuleId( im.getId() ); 241 attributeBo.setAttributeDefinitionId(attrDef.getId()); 242 attributeBo.setValue(entry.getValue()); 243 attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef)); 244 attributes.add( attributeBo ); 245 } else { 246 throw new RiceIllegalStateException("there is no attribute definition with the name '" + 247 entry.getKey() + "' that is valid for the rule type with id = '" + im.getTypeId() +"'"); 248 } 249 } 250 } 251 return attributes; 252 } 253 254 private List<RuleAttributeBo> buildAttributeBoList(RuleDefinition im) { 255 List<RuleAttributeBo> attributes = new LinkedList<RuleAttributeBo>(); 256 257 // build a map from attribute name to definition 258 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>(); 259 260 List<KrmsAttributeDefinition> attributeDefinitions = getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId()); 261 262 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) { 263 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition); 264 } 265 266 // for each entry, build a RuleAttributeBo and add it to the set 267 if (im.getAttributes() != null) { 268 for (Map.Entry<String,String> entry : im.getAttributes().entrySet()) { 269 KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey()); 270 271 if (attrDef != null) { 272 RuleAttributeBo attributeBo = new RuleAttributeBo(); 273 attributeBo.setRuleId( im.getId() ); 274 attributeBo.setAttributeDefinitionId(attrDef.getId()); 275 attributeBo.setValue(entry.getValue()); 276 attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef)); 277 attributes.add( attributeBo ); 278 } else { 279 throw new RiceIllegalStateException("there is no attribute definition with the name '" + 280 entry.getKey() + "' that is valid for the rule type with id = '" + im.getTypeId() +"'"); 281 } 282 } 283 } 284 return attributes; 285 } 286 /** 287 * Sets the businessObjectService attribute value. 288 * 289 * @param businessObjectService The businessObjectService to set. 290 */ 291 public void setBusinessObjectService(final BusinessObjectService businessObjectService) { 292 this.businessObjectService = businessObjectService; 293 } 294 295 /** 296 * Converts a List<RuleBo> to an Unmodifiable List<Rule> 297 * 298 * @param ruleBos a mutable List<RuleBo> to made completely immutable. 299 * @return An unmodifiable List<Rule> 300 */ 301 public List<RuleDefinition> convertListOfBosToImmutables(final Collection<RuleBo> ruleBos) { 302 ArrayList<RuleDefinition> rules = new ArrayList<RuleDefinition>(); 303 for (RuleBo bo : ruleBos) { 304 RuleDefinition rule = RuleBo.to(bo); 305 rules.add(rule); 306 } 307 return Collections.unmodifiableList(rules); 308 } 309 310 311 protected KrmsAttributeDefinitionService getAttributeDefinitionService() { 312 if (attributeDefinitionService == null) { 313 attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService(); 314 } 315 return attributeDefinitionService; 316 } 317 318 }