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.api.engine;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.mo.ModelObjectComplete;
20
21 import java.io.Serializable;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 /**
27 * <p>Parameter object for the {@link org.kuali.rice.krms.api.engine.Engine} used to pass in mappings from Term to value
28 * (aka facts). In rule parlance, a fact is a concrete value of a term. Intuitively this relationship is one of
29 * definition and instance, similar to a parameter definition (e.g. int count) for a function (or method) in a
30 * programming language and a parameter value (e.g. 5).</p>
31 *
32 * <p>{@link Facts} is immutable, and has a private constructor. Use the inner {@link Builder} class to construct.</p>
33 *
34 * @author Kuali Rice Team (rice.collab@kuali.org)
35 */
36 public final class Facts implements ModelObjectComplete, Serializable {
37
38 private static final long serialVersionUID = -1448089944850300846L;
39
40 /**
41 * empty facts object
42 */
43 public static final Facts EMPTY_FACTS = new Facts(Builder.create());
44
45 private Map<Term, Object> factMap;
46
47 private Facts() {
48 // private no-args constructor forces use of builder
49 }
50
51 private Facts(Builder b) {
52 // copy the map to avoid surprises
53 this.factMap = new HashMap<Term, Object>(b.factMap);
54 }
55
56 /**
57 * @return the Map of Terms to fact values. May be empty, will never be null. The returned map is unmodifiable.
58 */
59 public Map<Term, Object> getFactMap() {
60 return Collections.unmodifiableMap(factMap);
61 }
62
63 @Override
64 public boolean equals(Object o) {
65 if (this == o) {
66 return true;
67 }
68 if (o == null || getClass() != o.getClass()) {
69 return false;
70 }
71
72 final Facts facts = (Facts) o;
73
74 if (factMap != null ? !factMap.equals(facts.factMap) : facts.factMap != null) {
75 return false;
76 }
77
78 return true;
79 }
80
81 @Override
82 public int hashCode() {
83 return factMap != null ? factMap.hashCode() : 0;
84 }
85
86 @Override
87 public String toString() {
88 return "Facts{" + "factMap=" + factMap + '}';
89 }
90
91 /**
92 * Builder for a {@link Facts} parameter object
93 */
94 public static class Builder {
95 private Map<Term, Object> factMap = new HashMap<Term, Object>();
96
97 private Builder() {
98 // private constructor forces use of static factory
99 }
100
101 /**
102 * Static factory method to produce instances of this {@link Builder} class
103 * @return
104 */
105 public static Builder create() {
106 return new Builder();
107 }
108
109 /**
110 * Add a fact mapping from the name and parameter map combination to the fact value
111 * @param termName the name of the term. Must not be empty or null.
112 * @param termParameters any parameters for the term. May be null or empty.
113 * @param factValue the concrete value for the term
114 */
115 public Builder addFact(String termName, Map<String, String> termParameters, Object factValue) {
116 if (StringUtils.isEmpty(termName)) {
117 throw new IllegalArgumentException("termName must not be null or empty");
118 }
119 factMap.put(new Term(termName, termParameters), factValue);
120 return this;
121 }
122
123 /**
124 * Add a fact mapping from the term name to the fact value
125 * @param termName the name of the term. Must not be empty or null.
126 * @param factValue the concrete value for the term
127 */
128 public Builder addFact(String termName, Object factValue) {
129 addFact(termName, null, factValue);
130 return this;
131 }
132
133 /**
134 * Add a fact mapping from the {@link Term} to the fact value
135 * @param term the term that this fact is a value for. Must not be null.
136 * @param factValue the fact value
137 */
138 public Builder addFact(Term term, Object factValue) {
139 if (term == null) {
140 throw new IllegalArgumentException("term must not be null");
141 }
142 factMap.put(term, factValue);
143 return this;
144 }
145
146 /**
147 * Add facts in bulk to this Facts parameter object
148 * @param facts the map of Terms to fact values. May be null, in that case this call is a no op.
149 */
150 public Builder addFactsByTerm(Map<Term, Object> facts) {
151 if (facts != null) {
152 factMap.putAll(facts);
153 }
154 return this;
155 }
156
157 /**
158 * Add facts in bulk to this Facts parameter object
159 * @param facts the map of term names to fact values. May be null, in that case this call is a no op.
160 */
161 public Builder addFactsByName(Map<String, Object> facts) {
162 if (facts != null) {
163 for (Map.Entry<String, Object> entry : facts.entrySet()) {
164 factMap.put(new Term(entry.getKey()), entry.getValue());
165 }
166 }
167 return this;
168 }
169
170 /**
171 * return a {@link Facts} parameter object spawned from this {@link Builder}
172 */
173 public Facts build() {
174 if (factMap.isEmpty()) {
175 return EMPTY_FACTS;
176 } else {
177 return new Facts(this);
178 }
179 }
180
181 }
182
183
184 }