Coverage Report - org.kuali.rice.krms.impl.provider.repository.RepositoryToEngineTranslatorImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
RepositoryToEngineTranslatorImpl
0%
0/111
0%
0/60
3.053
 
 1  
 /*
 2  
  * Copyright 2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.provider.repository;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashMap;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 
 23  
 import org.apache.commons.collections.MapUtils;
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 import org.kuali.rice.krms.api.engine.TermResolver;
 26  
 import org.kuali.rice.krms.api.repository.RepositoryDataException;
 27  
 import org.kuali.rice.krms.api.repository.RuleRepositoryService;
 28  
 import org.kuali.rice.krms.api.repository.action.ActionDefinition;
 29  
 import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
 30  
 import org.kuali.rice.krms.api.repository.agenda.AgendaTreeDefinition;
 31  
 import org.kuali.rice.krms.api.repository.agenda.AgendaTreeEntryDefinition;
 32  
 import org.kuali.rice.krms.api.repository.agenda.AgendaTreeRuleEntry;
 33  
 import org.kuali.rice.krms.api.repository.agenda.AgendaTreeSubAgendaEntry;
 34  
 import org.kuali.rice.krms.api.repository.context.ContextDefinition;
 35  
 import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
 36  
 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
 37  
 import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
 38  
 import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
 39  
 import org.kuali.rice.krms.framework.engine.Action;
 40  
 import org.kuali.rice.krms.framework.engine.Agenda;
 41  
 import org.kuali.rice.krms.framework.engine.AgendaTree;
 42  
 import org.kuali.rice.krms.framework.engine.AgendaTreeEntry;
 43  
 import org.kuali.rice.krms.framework.engine.BasicAgenda;
 44  
 import org.kuali.rice.krms.framework.engine.BasicAgendaTree;
 45  
 import org.kuali.rice.krms.framework.engine.BasicAgendaTreeEntry;
 46  
 import org.kuali.rice.krms.framework.engine.BasicContext;
 47  
 import org.kuali.rice.krms.framework.engine.BasicRule;
 48  
 import org.kuali.rice.krms.framework.engine.Context;
 49  
 import org.kuali.rice.krms.framework.engine.Proposition;
 50  
 import org.kuali.rice.krms.framework.engine.Rule;
 51  
 import org.kuali.rice.krms.framework.engine.SubAgenda;
 52  
 import org.kuali.rice.krms.framework.type.TermResolverTypeService;
 53  
 import org.kuali.rice.krms.impl.repository.TermBoService;
 54  
 import org.kuali.rice.krms.impl.type.KrmsTypeResolver;
 55  
 import org.springframework.util.CollectionUtils;
 56  
 
 57  
 /**
 58  
  * TODO... 
 59  
  * 
 60  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 61  
  *
 62  
  */
 63  0
 public class RepositoryToEngineTranslatorImpl implements RepositoryToEngineTranslator {
 64  
 
 65  
         private RuleRepositoryService ruleRepositoryService;
 66  
         private KrmsTypeRepositoryService typeRepositoryService;
 67  
         private KrmsTypeResolver typeResolver;
 68  
         private TermBoService termBoService;
 69  
         
 70  
         @Override
 71  
         public Context translateContextDefinition(ContextDefinition contextDefinition) {
 72  0
                 if (contextDefinition == null) {
 73  0
                         return null;
 74  
                 }
 75  0
                 List<Agenda> agendas = new ArrayList<Agenda>();
 76  0
                 for (AgendaDefinition agendaDefinition : contextDefinition.getAgendas()) {
 77  0
                         Agenda agenda = translateAgendaDefinition(agendaDefinition);
 78  0
                         agendas.add(agenda);
 79  0
                 }
 80  
                 
 81  0
                 List<TermResolverDefinition> termResolverDefs = 
 82  
                         termBoService.getTermResolversByContextId(contextDefinition.getId());
 83  
                 
 84  0
                 List<TermResolver<?>> termResolvers = new ArrayList<TermResolver<?>>();
 85  
 
 86  0
                 if (!CollectionUtils.isEmpty(termResolverDefs)) for (TermResolverDefinition termResolverDef : termResolverDefs) {
 87  0
                         if (termResolverDef != null) {
 88  0
                                 TermResolver<?> termResolver = translateTermResolver(termResolverDef);
 89  0
                                 if (termResolver != null) termResolvers.add(termResolver);
 90  0
                         }
 91  
                 }
 92  
                 
 93  0
                 return new BasicContext(agendas, termResolvers); 
 94  
         }
 95  
 
 96  
         /**
 97  
          * This method translates a {@link TermResolverDefinition} into a {@link TermResolver}
 98  
          * 
 99  
          * @param termResolverDef
 100  
          * @return
 101  
          */
 102  
         private TermResolver<?> translateTermResolver(TermResolverDefinition termResolverDef) {
 103  0
                 if (termResolverDef == null) {
 104  0
                         throw new IllegalArgumentException("termResolverDef must not be null");
 105  
                 }
 106  0
                 TermResolverTypeService termResolverTypeService = 
 107  
                         typeResolver.getTermResolverTypeService(termResolverDef);
 108  
                 
 109  0
                 TermResolver<?> termResolver = termResolverTypeService.loadTermResolver(termResolverDef);
 110  
                 // TODO: log warning when termResolver comes back null? or throw exception?
 111  0
                 return termResolver;
 112  
         }
 113  
         
 114  
         @Override
 115  
         public Agenda translateAgendaDefinition(AgendaDefinition agendaDefinition) {
 116  0
             String eventName = MapUtils.getString(agendaDefinition.getAttributes(), AgendaDefinition.Constants.EVENT, StringUtils.EMPTY);
 117  
 
 118  
             // TODO: this limits an agenda to a single event.  Is that good enough?
 119  0
                 return new BasicAgenda(eventName, agendaDefinition.getAttributes(), new LazyAgendaTree(agendaDefinition, this));
 120  
         }
 121  
                 
 122  
         @Override
 123  
         public AgendaTree translateAgendaDefinitionToAgendaTree(AgendaDefinition agendaDefinition) {
 124  0
                 AgendaTreeDefinition agendaTreeDefinition = ruleRepositoryService.getAgendaTree(agendaDefinition.getId());
 125  0
                 return translateAgendaTreeDefinition(agendaTreeDefinition);
 126  
         }
 127  
         
 128  
         @Override
 129  
         public AgendaTree translateAgendaTreeDefinition(AgendaTreeDefinition agendaTreeDefinition) {
 130  
         
 131  0
                 List<String> ruleIds = new ArrayList<String>();
 132  0
                 List<String> subAgendaIds = new ArrayList<String>();
 133  0
                 for (AgendaTreeEntryDefinition entryDefinition : agendaTreeDefinition.getEntries()) {
 134  0
                         if (entryDefinition instanceof AgendaTreeRuleEntry) {
 135  0
                                 ruleIds.add(((AgendaTreeRuleEntry)entryDefinition).getRuleId());
 136  0
                         } else if (entryDefinition instanceof AgendaTreeSubAgendaEntry) {
 137  0
                                 subAgendaIds.add(((AgendaTreeSubAgendaEntry)entryDefinition).getSubAgendaId());
 138  
                         } else {
 139  0
                                 throw new IllegalStateException("Encountered invalid agenda tree entry definition class, did not understand type: " + entryDefinition);
 140  
                         }
 141  
                 }
 142  
                 
 143  0
                 Map<String, Rule> rules = loadRules(ruleIds);
 144  0
                 Map<String, SubAgenda> subAgendas = loadSubAgendas(subAgendaIds);
 145  
                 
 146  0
                 List<AgendaTreeEntry> entries = new ArrayList<AgendaTreeEntry>();
 147  
         
 148  0
                 for (AgendaTreeEntryDefinition entryDefinition : agendaTreeDefinition.getEntries()) {
 149  0
                         if (entryDefinition instanceof AgendaTreeRuleEntry) {
 150  0
                                 AgendaTreeRuleEntry ruleEntry = (AgendaTreeRuleEntry)entryDefinition;
 151  0
                                 AgendaTree ifTrue = null;
 152  0
                                 AgendaTree ifFalse = null;
 153  0
                                 if (ruleEntry.getIfTrue() != null) {
 154  0
                                         ifTrue = translateAgendaTreeDefinition(ruleEntry.getIfTrue());
 155  
                                 }
 156  0
                                 if (ruleEntry.getIfTrue() != null) {
 157  0
                                         ifFalse = translateAgendaTreeDefinition(ruleEntry.getIfFalse());
 158  
                                 }
 159  0
                                 Rule rule = rules.get(ruleEntry.getRuleId());
 160  0
                                 if (rule == null) {
 161  0
                                         throw new IllegalStateException("Failed to locate rule with id: " + ruleEntry.getRuleId());
 162  
                                 }
 163  0
                                 BasicAgendaTreeEntry agendaTreeEntry = new BasicAgendaTreeEntry(rule, ifTrue, ifFalse);
 164  0
                                 entries.add(agendaTreeEntry);
 165  0
                         } else if (entryDefinition instanceof AgendaTreeSubAgendaEntry) {
 166  0
                                 AgendaTreeSubAgendaEntry subAgendaEntry = (AgendaTreeSubAgendaEntry)entryDefinition;
 167  0
                                 SubAgenda subAgenda = subAgendas.get(subAgendaEntry.getSubAgendaId());
 168  0
                                 if (subAgenda == null) {
 169  0
                                         throw new IllegalStateException("Failed to locate sub agenda with id: " + subAgendaEntry.getSubAgendaId());
 170  
                                 }
 171  0
                                 BasicAgendaTreeEntry agendaTreeEntry = new BasicAgendaTreeEntry(subAgenda, null, null);
 172  0
                                 entries.add(agendaTreeEntry);
 173  0
                         } else {
 174  0
                                 throw new IllegalStateException("Encountered invalid agenda tree entry class, did not understand type: " + entryDefinition);
 175  
                         }
 176  
                 }
 177  0
                 return new BasicAgendaTree(entries);
 178  
         }
 179  
         
 180  
         protected Map<String, Rule> loadRules(List<String> ruleIds) {
 181  0
                 List<RuleDefinition> ruleDefinitions = ruleRepositoryService.getRules(ruleIds);
 182  0
                 validateRuleDefinitions(ruleIds, ruleDefinitions);
 183  0
                 Map<String, Rule> rules = new HashMap<String, Rule>();
 184  0
                 for (RuleDefinition ruleDefinition : ruleDefinitions) {
 185  0
                         rules.put(ruleDefinition.getId(), translateRuleDefinition(ruleDefinition));
 186  
                 }
 187  0
                 return rules;
 188  
         }
 189  
         
 190  
         /**
 191  
          * Ensures that there is a rule definition for every rule id in the original list.
 192  
          */
 193  
         private void validateRuleDefinitions(List<String> ruleIds, List<RuleDefinition> ruleDefinitions) {
 194  0
                 if (ruleIds.size() != ruleDefinitions.size()) {
 195  0
                         Map<String, RuleDefinition> indexedRuleDefinitions = indexRuleDefinitions(ruleDefinitions);
 196  0
                         for (String ruleId : ruleIds) {
 197  0
                                 if (!indexedRuleDefinitions.containsKey(ruleId)) {
 198  0
                                         throw new RepositoryDataException("Failed to locate a rule with id '" + ruleId + "' in the repository.");
 199  
                                 }
 200  
                         }
 201  
                 }
 202  0
         }
 203  
         
 204  
         private Map<String, RuleDefinition> indexRuleDefinitions(List<RuleDefinition> ruleDefinitions) {
 205  0
                 Map<String, RuleDefinition> ruleDefinitionMap = new HashMap<String, RuleDefinition>();
 206  0
                 for (RuleDefinition ruleDefinition : ruleDefinitions) {
 207  0
                         ruleDefinitionMap.put(ruleDefinition.getId(), ruleDefinition);
 208  
                 }
 209  0
                 return ruleDefinitionMap;
 210  
         }
 211  
         
 212  
         protected Map<String, SubAgenda> loadSubAgendas(List<String> subAgendaIds) {
 213  0
                 List<AgendaTreeDefinition> subAgendaDefinitions = ruleRepositoryService.getAgendaTrees(subAgendaIds);
 214  0
                 validateSubAgendaDefinitions(subAgendaIds, subAgendaDefinitions);
 215  0
                 Map<String, SubAgenda> subAgendas = new HashMap<String, SubAgenda>();
 216  0
                 for (AgendaTreeDefinition subAgendaDefinition : subAgendaDefinitions) {
 217  0
                         subAgendas.put(subAgendaDefinition.getAgendaId(), translateAgendaTreeDefinitionToSubAgenda(subAgendaDefinition));
 218  
                 }
 219  0
                 return subAgendas;
 220  
         }
 221  
         
 222  
         /**
 223  
          * Ensures that there is a rule definition for every rule id in the original list.
 224  
          */
 225  
         private void validateSubAgendaDefinitions(List<String> subAgendaIds, List<AgendaTreeDefinition> subAgendaDefinitions) {
 226  0
                 if (subAgendaIds.size() != subAgendaDefinitions.size()) {
 227  0
                         Map<String, AgendaTreeDefinition> indexedSubAgendaDefinitions = indexSubAgendaDefinitions(subAgendaDefinitions);
 228  0
                         for (String subAgendaId : subAgendaIds) {
 229  0
                                 if (!indexedSubAgendaDefinitions.containsKey(subAgendaId)) {
 230  0
                                         throw new RepositoryDataException("Failed to locate an agenda with id '" + subAgendaId + "' in the repository.");
 231  
                                 }
 232  
                         }
 233  
                 }
 234  0
         }
 235  
         
 236  
         private Map<String, AgendaTreeDefinition> indexSubAgendaDefinitions(List<AgendaTreeDefinition> subAgendaDefinitions) {
 237  0
                 Map<String, AgendaTreeDefinition> subAgendaDefinitionMap = new HashMap<String, AgendaTreeDefinition>();
 238  0
                 for (AgendaTreeDefinition subAgendaDefinition : subAgendaDefinitions) {
 239  0
                         subAgendaDefinitionMap.put(subAgendaDefinition.getAgendaId(), subAgendaDefinition);
 240  
                 }
 241  0
                 return subAgendaDefinitionMap;
 242  
         }
 243  
         
 244  
         @Override
 245  
         public Rule translateRuleDefinition(RuleDefinition ruleDefinition) {
 246  0
                 Proposition condition = translatePropositionDefinition(ruleDefinition.getProposition());
 247  0
                 List<Action> actions = new ArrayList<Action>();
 248  0
                 if (ruleDefinition.getActions() != null) {
 249  0
                         for (ActionDefinition actionDefinition : ruleDefinition.getActions()) {
 250  0
                                 actions.add(translateActionDefinition(actionDefinition));
 251  
                         }
 252  
                 }
 253  0
                 return new BasicRule(ruleDefinition.getName(), condition, actions);
 254  
         }
 255  
         
 256  
         @Override
 257  
         public Proposition translatePropositionDefinition(PropositionDefinition propositionDefinition) {
 258  0
                 return new LazyProposition(propositionDefinition, typeResolver);
 259  
         }
 260  
         
 261  
         @Override
 262  
         public Action translateActionDefinition(ActionDefinition actionDefinition) {
 263  0
                 if (actionDefinition.getTypeId() == null) {
 264  0
                         throw new RepositoryDataException("Given ActionDefinition does not have a typeId, actionId was: " + actionDefinition.getId());
 265  
                 }
 266  0
                 return new LazyAction(actionDefinition, typeResolver);
 267  
         }
 268  
         
 269  
         @Override
 270  
         public SubAgenda translateAgendaTreeDefinitionToSubAgenda(AgendaTreeDefinition subAgendaDefinition) {
 271  0
                 return new SubAgenda(translateAgendaTreeDefinition(subAgendaDefinition));
 272  
         }
 273  
         
 274  
         /**
 275  
          * @param ruleRepositoryService the ruleRepositoryService to set
 276  
          */
 277  
         public void setRuleRepositoryService(
 278  
                         RuleRepositoryService ruleRepositoryService) {
 279  0
                 this.ruleRepositoryService = ruleRepositoryService;
 280  0
         }
 281  
         
 282  
         /**
 283  
          * @param termBoService the termBoService to set
 284  
          */
 285  
         public void setTermBoService(TermBoService termBoService) {
 286  0
                 this.termBoService = termBoService;
 287  0
         }
 288  
         
 289  
         /**
 290  
          * @param typeRepositoryService the typeRepositoryService to set
 291  
          */
 292  
         public void setTypeRepositoryService(
 293  
                         KrmsTypeRepositoryService typeRepositoryService) {
 294  0
                 this.typeRepositoryService = typeRepositoryService;
 295  0
         }
 296  
         
 297  
         /**
 298  
          * @param typeResolver the typeResolver to set
 299  
          */
 300  
         public void setTypeResolver(KrmsTypeResolver typeResolver) {
 301  0
                 this.typeResolver = typeResolver;
 302  0
         }
 303  
 
 304  
 }