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 }