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