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.util.Collection;
025: import java.util.HashMap;
026: import java.util.HashSet;
027: import java.util.Iterator;
028: import java.util.Map;
029:
030: import biz.hammurapi.config.Component;
031: import biz.hammurapi.config.ComponentBase;
032: import biz.hammurapi.config.ConfigurationException;
033: import biz.hammurapi.config.RuntimeConfigurationException;
034:
035: /**
036: * Collection manager which holds collections in memory and
037: * can use storage to persist state.
038: * @author Pavel Vlasov
039: * @version ${Revision}
040: */
041: public class PojoCollectionManager extends ComponentBase implements
042: Component, CollectionManager {
043:
044: private Map collectionMap;
045: private Class collectionType = HashSet.class;
046: private String storageReference;
047:
048: /**
049: * Path to object storage.
050: * @param storageReference
051: */
052: public void setStorageReference(String storageReference) {
053: this .storageReference = storageReference;
054: }
055:
056: /**
057: * Starts collection manager. Loads collections from storage if storage reference is not null.
058: */
059: synchronized public void start() throws ConfigurationException {
060: if (storageReference == null) {
061: collectionMap = new HashMap();
062: } else {
063: collectionMap = (Map) ((ObjectStorage) get(storageReference))
064: .get("collection-manager");
065: if (collectionMap == null) {
066: collectionMap = new HashMap();
067: ((ObjectStorage) get(storageReference)).put(
068: "collection-manager", collectionMap);
069: }
070: }
071: }
072:
073: /**
074: * Empty method. Storage of collections is performed by object storage if storage reference is set.
075: */
076: synchronized public void stop() throws ConfigurationException {
077: // Nothing.
078: }
079:
080: private class CollectionEntry {
081: String ruleName;
082: String collectionName;
083: Object monitor;
084:
085: CollectionEntry(String ruleName, String collectionName,
086: Object monitor) {
087: this .ruleName = ruleName;
088: this .collectionName = collectionName;
089: this .monitor = monitor;
090: }
091:
092: public String toString() {
093: return "[Collection entry] Rule=" + ruleName
094: + ", Collection=" + collectionName;
095: }
096:
097: public boolean equals(Object obj) {
098: if (obj == this ) {
099: return true;
100: }
101:
102: if (obj instanceof CollectionEntry) {
103: CollectionEntry ce = (CollectionEntry) obj;
104:
105: return ruleName.equals(ce.ruleName)
106: && collectionName.equals(ce.collectionName);
107: }
108:
109: return false;
110: }
111:
112: public int hashCode() {
113: return ruleName.hashCode() ^ collectionName.hashCode();
114: }
115: }
116:
117: /**
118: * @see biz.hammurapi.rules.CollectionManager#getList(java.lang.String, java.lang.String)
119: */
120: synchronized public Collection get(String ruleName,
121: String listName, Object monitor) {
122: CollectionEntry ce = new CollectionEntry(ruleName, listName,
123: monitor);
124: Collection ret = (Collection) collectionMap.get(ce);
125: if (ret == null) {
126: try {
127: ret = (Collection) collectionType.newInstance();
128: collectionMap.put(ce, ret);
129: } catch (InstantiationException e) {
130: throw new RuntimeConfigurationException(
131: "Cannot instantiate " + collectionType + ": "
132: + e, e);
133: } catch (IllegalAccessException e) {
134: throw new RuntimeConfigurationException(
135: "Cannot instantiate " + collectionType + ": "
136: + e, e);
137: }
138: }
139: return ret;
140: }
141:
142: /* (non-Javadoc)
143: * @see biz.hammurapi.rules.CollectionManager#clear()
144: */
145: public synchronized void clear() {
146: Iterator it = collectionMap.values().iterator();
147: while (it.hasNext()) {
148: ((Collection) it.next()).clear();
149: }
150: }
151:
152: /**
153: * Iterates over all collections and removes negated facts.
154: * Collection operations are synchronized using monitor object passed in get() method for a given collection
155: * or collection itself if monitor is null.
156: */
157: public synchronized boolean isNegatedBy(Negator negator) {
158: Iterator it = collectionMap.entrySet().iterator();
159: while (it.hasNext()) {
160: Map.Entry entry = (Map.Entry) it.next();
161: CollectionEntry ce = (CollectionEntry) entry.getKey();
162: Collection col = (Collection) entry.getValue();
163: synchronized (ce.monitor == null ? col : ce.monitor) {
164: Iterator cit = col.iterator();
165: while (cit.hasNext()) {
166: Object o = cit.next();
167: if (o instanceof Conclusion) {
168: if (((Conclusion) o).isNegatedBy(negator)) {
169: cit.remove();
170: }
171: } else {
172: if (negator.negates(o)) {
173: cit.remove();
174: }
175: }
176: }
177: }
178: }
179: return false; // Return value has no meaning for collection manager.
180: }
181:
182: public void setCollectionType(String collectionType) {
183: try {
184: this .collectionType = Class.forName(collectionType);
185: } catch (ClassNotFoundException e) {
186: throw new RuntimeConfigurationException(
187: "Cannot load collection class: " + e, e);
188: }
189: }
190:
191: }
|