View Javadoc
1   /**
2    * Copyright 2005-2014 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.framework.engine;
17  
18  import java.util.Collections;
19  import java.util.HashMap;
20  import java.util.Map;
21  import java.util.Map.Entry;
22  import java.util.Set;
23  import java.util.HashSet;
24  
25  import org.apache.commons.lang.ObjectUtils;
26  import org.kuali.rice.krms.api.engine.EngineResults;
27  import org.kuali.rice.krms.api.engine.ExecutionEnvironment;
28  import org.kuali.rice.krms.api.engine.ExecutionOptions;
29  import org.kuali.rice.krms.api.engine.SelectionCriteria;
30  import org.kuali.rice.krms.api.engine.Term;
31  import org.kuali.rice.krms.api.engine.TermResolutionEngine;
32  import org.kuali.rice.krms.api.engine.TermResolutionException;
33  import org.kuali.rice.krms.api.engine.TermResolver;
34  import org.kuali.rice.krms.api.engine.ResultEvent;
35  
36  /**
37   * An implementation of {@link ExecutionEnvironment} given {@link SelectionCriteria}, facts (Map<{@link Term}, Object> ), {@link ExecutionOptions} and {@link TermResolutionEngine}.
38   * @author Kuali Rice Team (rice.collab@kuali.org)
39   */
40  public final class BasicExecutionEnvironment implements ExecutionEnvironment {
41  
42  	private final SelectionCriteria selectionCriteria;
43  	private final Map<Term, Object> facts;
44  	private final ExecutionOptions executionOptions;
45  	private final EngineResults engineResults;
46  	private final TermResolutionEngine termResolutionEngine;
47  	private Map<Object, Set<Term>> termPropositionMap;
48  
49      /**
50       * Constructor for a BasicExecutionEnvironment with the given {@link SelectionCriteria}, facts, {@link ExecutionOptions} and {@link TermResolutionEngine}
51       * @param selectionCriteria to set selectionCriteria to, cannot be null
52       * @param facts to set facts to, cannot be null
53       * @param executionOptions to set executionOptions to
54       * @param termResolutionEngine to set termResolutionEngine to
55       * @throws IllegalArgumentException if the selectionCriteria or facts are null
56       */
57  	public BasicExecutionEnvironment(SelectionCriteria selectionCriteria, Map<Term, Object> facts, ExecutionOptions executionOptions, TermResolutionEngine termResolutionEngine) {
58  		if (selectionCriteria == null) {
59  			throw new IllegalArgumentException("Selection criteria must not be null.");
60  		}
61  		if (facts == null) {
62  			throw new IllegalArgumentException("Facts must not be null.");
63  		}
64  		this.selectionCriteria = selectionCriteria;
65  		this.executionOptions = new ExecutionOptions(executionOptions);
66  		this.engineResults = new EngineResultsImpl();
67  				
68  		this.termResolutionEngine = new TermResolutionEngineImpl();
69  		
70  		// Add facts
71  		this.facts = new HashMap<Term, Object>(facts.size());
72  		this.facts.putAll(facts);
73  		
74  		for (Entry<Term, Object> factsEntry : facts.entrySet()) {
75  			this.termResolutionEngine.addTermValue(factsEntry.getKey(), factsEntry.getValue());
76  		}
77  	}
78  	
79  	@Override
80  	public SelectionCriteria getSelectionCriteria() {
81  		return this.selectionCriteria;
82  	}
83  	
84  	@Override
85  	public Map<Term, Object> getFacts() {
86  		return Collections.unmodifiableMap(facts);
87  	}
88  	
89  	@Override
90  	public void addTermResolver(TermResolver<?> termResolver) {
91  		termResolutionEngine.addTermResolver(termResolver);
92  	}
93  	
94  	@Override
95  	public <T> T resolveTerm(Term term, Object caller) throws TermResolutionException {
96  		T value;
97  		
98  		// This looks funny, but works around a javac bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954
99  		// Specifically, using <T> below works around it.
100 		value = termResolutionEngine.<T>resolveTerm(term);
101 		
102 		if (caller != null) {
103 		    if(termPropositionMap == null) {
104 		        termPropositionMap = new HashMap<Object, Set<Term>>();
105 		    }
106 
107 		    // update the Proposition-Term mapping
108 		    if(termPropositionMap.containsKey(caller)) {
109 		        termPropositionMap.get(caller).add(term);
110 		    } else {
111 		        termPropositionMap.put(caller, new HashSet<Term>());
112 		        termPropositionMap.get(caller).add(term);
113 		    }
114 		}
115 		
116 		publishFact(term, value);		
117 		
118 		return value;
119 	}
120 
121     @Override
122 	public Set<Term> getTermsForCaller(Object caller) {
123 		return termPropositionMap.get(caller);
124 	}
125 	
126 	@Override
127 	public boolean publishFact(Term factName, Object factValue) {
128 		if (facts.containsKey(factName) && ObjectUtils.equals(facts.get(factName), factValue)) {
129 			return false;
130 		}
131 		facts.put(factName, factValue);
132 		termResolutionEngine.addTermValue(factName, factValue);
133 		return true;
134 	}
135 
136 	@Override
137 	public ExecutionOptions getExecutionOptions() {
138 		return executionOptions;
139 	}
140 	
141 	@Override
142 	public EngineResults getEngineResults() {
143 		return engineResults;
144 	}
145 	
146 
147 }