View Javadoc

1   /**
2    * Copyright 2005-2012 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  public final class BasicExecutionEnvironment implements ExecutionEnvironment {
38  
39  	private final SelectionCriteria selectionCriteria;
40  	private final Map<Term, Object> facts;
41  	private final ExecutionOptions executionOptions;
42  	private final EngineResults engineResults;
43  	private final TermResolutionEngine termResolutionEngine;
44  	private Map<Object, Set<Term>> termPropositionMap;
45  		
46  	public BasicExecutionEnvironment(SelectionCriteria selectionCriteria, Map<Term, Object> facts, ExecutionOptions executionOptions, TermResolutionEngine termResolutionEngine) {
47  		if (selectionCriteria == null) {
48  			throw new IllegalArgumentException("Selection criteria must not be null.");
49  		}
50  		if (facts == null) {
51  			throw new IllegalArgumentException("Facts must not be null.");
52  		}
53  		this.selectionCriteria = selectionCriteria;
54  		this.executionOptions = new ExecutionOptions(executionOptions);
55  		this.engineResults = new EngineResultsImpl();
56  				
57  		this.termResolutionEngine = new TermResolutionEngineImpl();
58  		
59  		// Add facts
60  		this.facts = new HashMap<Term, Object>(facts.size());
61  		this.facts.putAll(facts);
62  		
63  		for (Entry<Term, Object> factsEntry : facts.entrySet()) {
64  			this.termResolutionEngine.addTermValue(factsEntry.getKey(), factsEntry.getValue());
65  		}
66  	}
67  	
68  	@Override
69  	public SelectionCriteria getSelectionCriteria() {
70  		return this.selectionCriteria;
71  	}
72  	
73  	@Override
74  	public Map<Term, Object> getFacts() {
75  		return Collections.unmodifiableMap(facts);
76  	}
77  	
78  	@Override
79  	public void addTermResolver(TermResolver<?> termResolver) {
80  		termResolutionEngine.addTermResolver(termResolver);
81  	}
82  	
83  	@Override
84  	public <T> T resolveTerm(Term term, Object caller) throws TermResolutionException {
85  		T value;
86  		
87  		// This looks funny, but works around a javac bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954
88  		// Specifically, using <T> below works around it.
89  		value = termResolutionEngine.<T>resolveTerm(term);
90  		
91  		if (caller != null) {
92  		    if(termPropositionMap == null) {
93  		        termPropositionMap = new HashMap<Object, Set<Term>>();
94  		    }
95  
96  		    // update the Proposition-Term mapping
97  		    if(termPropositionMap.containsKey(caller)) {
98  		        termPropositionMap.get(caller).add(term);
99  		    } else {
100 		        termPropositionMap.put(caller, new HashSet<Term>());
101 		        termPropositionMap.get(caller).add(term);
102 		    }
103 		}
104 		
105 		publishFact(term, value);		
106 		
107 		return value;
108 	}
109 
110 	public Set<Term> getTermsForCaller(Object caller) {
111 		return termPropositionMap.get(caller);
112 	}
113 	
114 	@Override
115 	public boolean publishFact(Term factName, Object factValue) {
116 		if (facts.containsKey(factName) && ObjectUtils.equals(facts.get(factName), factValue)) {
117 			return false;
118 		}
119 		facts.put(factName, factValue);
120 		termResolutionEngine.addTermValue(factName, factValue);
121 		return true;
122 	}
123 
124 	@Override
125 	public ExecutionOptions getExecutionOptions() {
126 		return executionOptions;
127 	}
128 	
129 	@Override
130 	public EngineResults getEngineResults() {
131 		return engineResults;
132 	}
133 	
134 
135 }