View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krms.impl.repository;
17  
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.exception.RiceIllegalStateException;
21  import org.kuali.rice.krad.service.BusinessObjectService;
22  import org.kuali.rice.krms.api.repository.action.ActionDefinition;
23  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
24  import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
25  import org.kuali.rice.krms.impl.util.KrmsImplConstants.PropertyNames;
26  
27  import java.util.*;
28  
29  public final class KSRuleBoServiceImpl implements RuleBoService {
30  
31      private BusinessObjectService businessObjectService;
32      private KrmsAttributeDefinitionService attributeDefinitionService;
33  
34      /**
35       * This overridden creates a KRMS Rule in the repository
36       *
37       * @see org.kuali.rice.krms.impl.repository.RuleBoService#createRule(org.kuali.rice.krms.api.repository.rule.RuleDefinition)
38       */
39      @Override
40      public RuleDefinition createRule(RuleDefinition rule) {
41          if (rule == null) {
42              throw new IllegalArgumentException("rule is null");
43          }
44          final String nameKey = rule.getName();
45          final String namespaceKey = rule.getNamespace();
46          final RuleDefinition existing = getRuleByNameAndNamespace(nameKey, namespaceKey);
47          if (existing != null) {
48              throw new IllegalStateException("the rule to create already exists: " + rule);
49          }
50          RuleBo ruleBo = RuleBo.from(rule);
51          businessObjectService.save(ruleBo);
52          return RuleBo.to(ruleBo);
53      }
54  
55      /**
56       * This overridden updates an existing Rule in the Repository
57       *
58       * @see org.kuali.rice.krms.impl.repository.RuleBoService#updateRule(org.kuali.rice.krms.api.repository.rule.RuleDefinition)
59       */
60      @Override
61      public void updateRule(RuleDefinition rule) {
62          if (rule == null) {
63              throw new IllegalArgumentException("rule is null");
64          }
65  
66          // must already exist to be able to update
67          final String ruleIdKey = rule.getId();
68          final RuleBo existing = businessObjectService.findBySinglePrimaryKey(RuleBo.class, ruleIdKey);
69          if (existing == null) {
70              throw new IllegalStateException("the rule does not exist: " + rule);
71          }
72          final RuleDefinition toUpdate;
73          if (!existing.getId().equals(rule.getId())) {
74              // if passed in id does not match existing id, correct it
75              final RuleDefinition.Builder builder = RuleDefinition.Builder.create(rule);
76              builder.setId(existing.getId());
77              toUpdate = builder.build();
78          } else {
79              toUpdate = rule;
80          }
81  
82          // copy all updateable fields to bo
83          RuleBo boToUpdate = RuleBo.from(toUpdate);
84          updateActionAttributes(boToUpdate.getActions());
85  
86          // delete any old, existing attributes
87          Map<String, String> fields = new HashMap<String, String>(1);
88          fields.put(PropertyNames.Rule.RULE_ID, toUpdate.getId());
89          businessObjectService.deleteMatching(RuleAttributeBo.class, fields);
90  
91          // update the rule and create new attributes
92          businessObjectService.save(boToUpdate);
93      }
94  
95      @Override
96      public void deleteRule(String ruleId) {
97          if (ruleId == null) {
98              throw new IllegalArgumentException("ruleId is null");
99          }
100         final RuleDefinition existing = getRuleByRuleId(ruleId);
101         if (existing == null) {
102             throw new IllegalStateException("the Rule to delete does not exists: " + ruleId);
103         }
104         businessObjectService.delete(from(existing));
105     }
106 
107     /**
108      * This method retrieves a rule from the repository given the rule id.
109      *
110      * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleByRuleId(java.lang.String)
111      */
112     @Override
113     public RuleDefinition getRuleByRuleId(String ruleId) {
114         if (StringUtils.isBlank(ruleId)) {
115             throw new IllegalArgumentException("rule id is null");
116         }
117         RuleBo bo = businessObjectService.findBySinglePrimaryKey(RuleBo.class, ruleId);
118         return RuleBo.to(bo);
119     }
120 
121     /**
122      * This method retrieves a rule from the repository given the name of the rule
123      * and namespace.
124      *
125      * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleByRuleId(java.lang.String)
126      */
127     @Override
128     public RuleDefinition getRuleByNameAndNamespace(String name, String namespace) {
129         if (StringUtils.isBlank(name)) {
130             throw new IllegalArgumentException("name is null or blank");
131         }
132         if (StringUtils.isBlank(namespace)) {
133             throw new IllegalArgumentException("namespace is null or blank");
134         }
135 
136         final Map<String, Object> map = new HashMap<String, Object>();
137         map.put("name", name);
138         map.put("namespace", namespace);
139 
140         RuleBo myRule = businessObjectService.findByPrimaryKey(RuleBo.class, Collections.unmodifiableMap(map));
141         return RuleBo.to(myRule);
142     }
143 
144 //	/**
145 //	 * This overridden method ...
146 //	 * 
147 //	 * @see org.kuali.rice.krms.impl.repository.RuleBoService#createRuleAttribute(org.kuali.rice.krms.api.repository.rule.RuleAttribute)
148 //	 */
149 //	@Override
150 //	public void createRuleAttribute(RuleAttribute attribute) {
151 //		if (attribute == null){
152 //			throw new IllegalArgumentException("rule attribute is null");
153 //		}
154 //		final String attrIdKey = attribute.getId();
155 //		final RuleAttribute existing = getRuleAttributeById(attrIdKey);
156 //		if (existing != null){
157 //			throw new IllegalStateException("the rule attribute to create already exists: " + attribute);			
158 //		}
159 //
160 //		businessObjectService.save(RuleAttributeBo.from(attribute));		
161 //	}
162 //
163 //	/**
164 //	 * This overridden method ...
165 //	 * 
166 //	 * @see org.kuali.rice.krms.impl.repository.RuleBoService#updateRuleAttribute(org.kuali.rice.krms.api.repository.rule.RuleAttribute)
167 //	 */
168 //	@Override
169 //	public void updateRuleAttribute(RuleAttribute attribute) {
170 //		if (attribute == null){
171 //			throw new IllegalArgumentException("rule attribute is null");
172 //		}
173 //		final String attrIdKey = attribute.getId();
174 //		final RuleAttribute existing = getRuleAttributeById(attrIdKey);
175 //		if (existing == null) {
176 //			throw new IllegalStateException("the rule attribute does not exist: " + attribute);
177 //		}
178 //		final RuleAttribute toUpdate;
179 //		if (!existing.getId().equals(attribute.getRuleId())){
180 //			final RuleAttribute.Builder builder = RuleAttribute.Builder.create(attribute);
181 //			builder.setId(existing.getId());
182 //			toUpdate = builder.build();
183 //		} else {
184 //			toUpdate = attribute;
185 //		}
186 //
187 //		businessObjectService.save(RuleAttributeBo.from(toUpdate));
188 //	}
189 //
190 
191     /**
192      * This method ...
193      *
194      * @see org.kuali.rice.krms.impl.repository.RuleBoService#getRuleAttributeById(java.lang.String)
195      */
196     public RuleAttributeBo getRuleAttributeById(String attrId) {
197         if (StringUtils.isBlank(attrId)) {
198             return null;
199         }
200         RuleAttributeBo bo = businessObjectService.findBySinglePrimaryKey(RuleAttributeBo.class, attrId);
201         return bo;
202     }
203 
204     /**
205      * Converts a immutable {@link RuleDefinition} to its mutable {@link RuleBo} counterpart.
206      *
207      * @param rule the immutable object.
208      * @return a {@link RuleBo} the mutable RuleBo.
209      */
210     public RuleBo from(RuleDefinition rule) {
211         if (rule == null) {
212             return null;
213         }
214         RuleBo ruleBo = new RuleBo();
215         ruleBo.setName(rule.getName());
216         ruleBo.setDescription(rule.getDescription());
217         ruleBo.setNamespace(rule.getNamespace());
218         ruleBo.setTypeId(rule.getTypeId());
219         ruleBo.setPropId(rule.getPropId());
220         ruleBo.setProposition(PropositionBo.from(rule.getProposition()));
221         ruleBo.setId(rule.getId());
222         ruleBo.setActive(rule.isActive());
223         ruleBo.setVersionNumber(rule.getVersionNumber());
224 //        Set<RuleAttributeBo> attributes = buildAttributeBo(rule);
225         ruleBo.setActions(buildActionBoList(rule));
226         ruleBo.setAttributeBos(buildAttributeBoList(rule));
227         return ruleBo;
228     }
229 
230     private Set<RuleAttributeBo> buildAttributeBo(RuleDefinition im) {
231         Set<RuleAttributeBo> attributes = new HashSet<RuleAttributeBo>();
232 
233         // build a map from attribute name to definition
234         Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
235 
236         List<KrmsAttributeDefinition> attributeDefinitions = getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId());
237 
238         for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
239             attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
240         }
241 
242         // for each entry, build a RuleAttributeBo and add it to the set
243         if (im.getAttributes() != null) {
244             for (Map.Entry<String, String> entry : im.getAttributes().entrySet()) {
245                 KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey());
246 
247                 if (attrDef != null) {
248                     RuleAttributeBo attributeBo = new RuleAttributeBo();
249                     attributeBo.setRuleId(im.getId());
250                     attributeBo.setAttributeDefinitionId(attrDef.getId());
251                     attributeBo.setValue(entry.getValue());
252                     attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef));
253                     attributes.add(attributeBo);
254                 } else {
255                     throw new RiceIllegalStateException("there is no attribute definition with the name '" +
256                             entry.getKey() + "' that is valid for the rule type with id = '" + im.getTypeId() + "'");
257                 }
258             }
259         }
260         return attributes;
261     }
262 
263     private List<RuleAttributeBo> buildAttributeBoList(RuleDefinition im) {
264         List<RuleAttributeBo> attributes = new LinkedList<RuleAttributeBo>();
265 
266         // build a map from attribute name to definition
267         Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
268 
269         List<KrmsAttributeDefinition> attributeDefinitions = getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId());
270 
271         for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
272             attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
273         }
274 
275         // for each entry, build a RuleAttributeBo and add it to the set
276         if (im.getAttributes() != null) {
277             for (Map.Entry<String, String> entry : im.getAttributes().entrySet()) {
278                 KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey());
279 
280                 if (attrDef != null) {
281                     RuleAttributeBo attributeBo = new RuleAttributeBo();
282                     attributeBo.setRuleId(im.getId());
283                     attributeBo.setAttributeDefinitionId(attrDef.getId());
284                     attributeBo.setValue(entry.getValue());
285                     attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef));
286                     attributes.add(attributeBo);
287                 } else {
288                     throw new RiceIllegalStateException("there is no attribute definition with the name '" +
289                             entry.getKey() + "' that is valid for the rule type with id = '" + im.getTypeId() + "'");
290                 }
291             }
292         }
293         return attributes;
294     }
295 
296     private List<ActionBo> buildActionBoList(RuleDefinition im) {
297         List<ActionBo> actions = new LinkedList<ActionBo>();
298 
299         for (ActionDefinition actionDefinition : im.getActions()) {
300             actions.add(ActionBo.from(actionDefinition));
301         }
302         updateActionAttributes(actions);
303 
304         return actions;
305     }
306 
307     private void updateActionAttributes(List<ActionBo> actionBos) {
308         for (ActionBo action : actionBos) {
309             for (ActionAttributeBo aa : action.getAttributeBos()) {
310                 final Map<String, Object> map = new HashMap<String, Object>();
311                 map.put("actionId", action.getId());
312 
313                 List<ActionAttributeBo> aaBos = (List<ActionAttributeBo>) businessObjectService.findMatching(ActionAttributeBo.class, Collections.unmodifiableMap(map));
314                 for (ActionAttributeBo aaBo : aaBos) {
315                     if (aaBo.getAttributeDefinitionId().equals(aa.getAttributeDefinitionId())) {
316                         aa.setId(aaBo.getId());
317                         aa.setVersionNumber(aaBo.getVersionNumber());
318                     }
319                 }
320             }
321         }
322     }
323 
324     /**
325      * Sets the businessObjectService attribute value.
326      *
327      * @param businessObjectService The businessObjectService to set.
328      */
329     public void setBusinessObjectService(final BusinessObjectService businessObjectService) {
330         this.businessObjectService = businessObjectService;
331     }
332 
333     /**
334      * Converts a List<RuleBo> to an Unmodifiable List<Rule>
335      *
336      * @param ruleBos a mutable List<RuleBo> to made completely immutable.
337      * @return An unmodifiable List<Rule>
338      */
339     public List<RuleDefinition> convertListOfBosToImmutables(final Collection<RuleBo> ruleBos) {
340         ArrayList<RuleDefinition> rules = new ArrayList<RuleDefinition>();
341         for (RuleBo bo : ruleBos) {
342             RuleDefinition rule = RuleBo.to(bo);
343             rules.add(rule);
344         }
345         return Collections.unmodifiableList(rules);
346     }
347 
348 
349     protected KrmsAttributeDefinitionService getAttributeDefinitionService() {
350         if (attributeDefinitionService == null) {
351             attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
352         }
353         return attributeDefinitionService;
354     }
355 
356 }