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