001: /**
002: * hammurapi-rules @mesopotamia.version@
003: * Hammurapi rules engine.
004: * Copyright (C) 2005 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://http://www.hammurapi.biz
021: * e-Mail: support@hammurapi.biz
022: */package biz.hammurapi.rules;
023:
024: import java.io.Serializable;
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.LinkedHashMap;
030: import java.util.Map;
031:
032: import javax.rules.Handle;
033:
034: import biz.hammurapi.config.Component;
035: import biz.hammurapi.config.ComponentBase;
036: import biz.hammurapi.config.ConfigurationException;
037:
038: /**
039: * Handle manager implementation which keeps handles in memory.
040: * Objects are compared by eqals().
041: * This handle manager doesn't hold facts which superced each other, but retains only superceeding fact
042: * (e.g. if Mother supercedes Parent then Parent will not be retained in the manager when Mother is added).
043: * @author Pavel Vlasov
044: * @version ${Revision}
045: */
046: public class KnowledgeMaximizingHandleManager extends ComponentBase
047: implements HandleManager, Component {
048:
049: private Map handleMap;
050:
051: private String storageReference;
052:
053: /**
054: * Path to object storage.
055: * @param storageReference
056: */
057: public void setStorageReference(String storageReference) {
058: this .storageReference = storageReference;
059: }
060:
061: private static class HandleImpl implements Handle, Serializable {
062: private static final long serialVersionUID = -6198273232968377370L;
063: private Object master;
064:
065: HandleImpl(Object master) {
066: this .master = master;
067: }
068:
069: public boolean equals(Object obj) {
070: return obj instanceof HandleImpl
071: && master.equals(((HandleImpl) obj).master);
072: }
073:
074: public int hashCode() {
075: return master == null ? 0 : master.hashCode();
076: }
077:
078: public String toString() {
079: return getClass().getName() + " -> " + master;
080: }
081: }
082:
083: /**
084: * Adds new object to the manager if this object is not already there and there is no superceding object.
085: * If object being added supercedes any objects in the manager these objects will be removed.
086: */
087: synchronized public Handle addObject(Object object) {
088: Iterator it = handleMap.keySet().iterator();
089: while (it.hasNext()) {
090: HandleImpl existingHandle = (HandleImpl) it.next();
091: if (existingHandle.master.equals(object)) {
092: // Merge derivations for equal conclusions.
093: if (object != existingHandle.master
094: && object instanceof Conclusion) {
095: ((Conclusion) existingHandle.master)
096: .mergeDerivations((Conclusion) object);
097: }
098: return existingHandle;
099: }
100:
101: if (object instanceof Supercedable
102: && existingHandle.master instanceof Supercedable) {
103: if (((Supercedable) existingHandle.master)
104: .super cedes(object)) {
105: return existingHandle;
106: }
107: }
108:
109: if (object instanceof Supercedable
110: && existingHandle.master instanceof Supercedable) {
111: if (((Supercedable) object)
112: .super cedes(existingHandle.master)) {
113: rebind(existingHandle, object);
114: return existingHandle;
115: }
116: }
117: }
118:
119: Handle newHandle = new HandleImpl(object);
120: handleMap.put(newHandle, newHandle);
121: return newHandle;
122: }
123:
124: synchronized public Object getObject(Handle handle) {
125: if (handle instanceof HandleImpl) {
126: return ((HandleImpl) handle).master;
127: }
128:
129: throw new IllegalArgumentException("Foreign handle: " + handle);
130: }
131:
132: public Collection getObjects() {
133: ArrayList ret = new ArrayList();
134: Iterator it = handleMap.keySet().iterator();
135: while (it.hasNext()) {
136: ret.add(((HandleImpl) it.next()).master);
137: }
138: return ret;
139: }
140:
141: public Collection getHandles() {
142: return handleMap.keySet();
143: }
144:
145: synchronized public void remove(Handle handle) {
146: handleMap.remove(handle);
147: }
148:
149: public boolean contains(Handle handle) {
150: return handleMap.containsKey(handle);
151: }
152:
153: synchronized public void rebind(Handle handle, Object object) {
154: if (handle instanceof HandleImpl) {
155: handleMap.remove(handle);
156: ((HandleImpl) handle).master = object;
157: handleMap.put(handle, handle);
158: } else {
159: throw new IllegalArgumentException("Foreign handle: "
160: + handle);
161: }
162: }
163:
164: public void remove(Object obj) {
165: handleMap.remove(new HandleImpl(obj));
166: }
167:
168: public synchronized void clear() {
169: handleMap.clear();
170: }
171:
172: public void start() throws ConfigurationException {
173: if (storageReference == null) {
174: handleMap = new LinkedHashMap();
175: } else {
176: handleMap = (Map) ((ObjectStorage) get(storageReference))
177: .get("handle-manager");
178: if (handleMap == null) {
179: handleMap = new HashMap();
180: ((ObjectStorage) get(storageReference)).put(
181: "handle-manager", handleMap);
182: }
183: }
184: }
185:
186: public void stop() throws ConfigurationException {
187: // Nothing
188: }
189:
190: public synchronized boolean isNegatedBy(Negator negator) {
191: Iterator it = handleMap.keySet().iterator();
192: while (it.hasNext()) {
193: HandleImpl handle = (HandleImpl) it.next();
194: if (Conclusion.object2Negator(handle.master, negator)) {
195: it.remove();
196: }
197: }
198:
199: return false;
200: }
201: }
|