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 public void setCollectionType(Class collectionType) { 180 this.collectionType = collectionType; 181 } 182 }