001/** 002 * Copyright 2005-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krms.api.engine; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.mo.ModelObjectComplete; 020 021import java.io.Serializable; 022import java.util.Collections; 023import java.util.HashMap; 024import java.util.Map; 025 026/** 027 * <p>Parameter object for the {@link org.kuali.rice.krms.api.engine.Engine} used to pass in mappings from Term to value 028 * (aka facts). In rule parlance, a fact is a concrete value of a term. Intuitively this relationship is one of 029 * definition and instance, similar to a parameter definition (e.g. int count) for a function (or method) in a 030 * programming language and a parameter value (e.g. 5).</p> 031 * 032 * <p>{@link Facts} is immutable, and has a private constructor. Use the inner {@link Builder} class to construct.</p> 033 * 034 * @author Kuali Rice Team (rice.collab@kuali.org) 035 */ 036public final class Facts implements ModelObjectComplete, Serializable { 037 038 private static final long serialVersionUID = -1448089944850300846L; 039 040 /** 041 * empty facts object 042 */ 043 public static final Facts EMPTY_FACTS = new Facts(Builder.create()); 044 045 private Map<Term, Object> factMap; 046 047 private Facts() { 048 // private no-args constructor forces use of builder 049 } 050 051 private Facts(Builder b) { 052 // copy the map to avoid surprises 053 this.factMap = new HashMap<Term, Object>(b.factMap); 054 } 055 056 /** 057 * @return the Map of Terms to fact values. May be empty, will never be null. The returned map is unmodifiable. 058 */ 059 public Map<Term, Object> getFactMap() { 060 return Collections.unmodifiableMap(factMap); 061 } 062 063 @Override 064 public boolean equals(Object o) { 065 if (this == o) { 066 return true; 067 } 068 if (o == null || getClass() != o.getClass()) { 069 return false; 070 } 071 072 final Facts facts = (Facts) o; 073 074 if (factMap != null ? !factMap.equals(facts.factMap) : facts.factMap != null) { 075 return false; 076 } 077 078 return true; 079 } 080 081 @Override 082 public int hashCode() { 083 return factMap != null ? factMap.hashCode() : 0; 084 } 085 086 @Override 087 public String toString() { 088 return "Facts{" + "factMap=" + factMap + '}'; 089 } 090 091 /** 092 * Builder for a {@link Facts} parameter object 093 */ 094 public static class Builder { 095 private Map<Term, Object> factMap = new HashMap<Term, Object>(); 096 097 private Builder() { 098 // private constructor forces use of static factory 099 } 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}