001: package org.mandarax.reference;
002:
003: /*
004: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
005: *
006: * This library 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 library 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: import java.util.Collections;
021: import java.util.Hashtable;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Vector;
025:
026: import org.mandarax.kernel.Clause;
027: import org.mandarax.kernel.ClauseSet;
028: import org.mandarax.kernel.ClauseSetChangeEvent;
029: import org.mandarax.kernel.KnowledgeBaseChangeEvent;
030: import org.mandarax.kernel.KnowledgeBaseFeatureDescriptions;
031:
032: /**
033: * Default implementation of a knowledge base.
034: * New methods for adding/removing plugins to the knowledgebase are added since 3.3.1 (by Adrian Paschke).
035: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
036: * @version 3.4 <7 March 05>
037: * @since 1.0
038: */
039: public final class KnowledgeBase extends AbstractKnowledgeBase {
040:
041: // the container. change this to a sorted collection !
042: private java.util.Vector container = new java.util.Vector();
043:
044: // indexed container
045: private java.util.Hashtable indexed = new java.util.Hashtable();
046:
047: // the feature descriptor
048: private static KnowledgeBaseFeatureDescriptions featureDescriptions = null;
049:
050: // event listener
051: private transient Vector knowledgeBaseListener = new Vector();
052:
053: /**
054: * Constructor.
055: */
056: public KnowledgeBase() {
057: super ();
058: }
059:
060: /**
061: * Add plugin to knowledgebase
062: * @parameter plugin a KnowledgeBase
063: * @parameter id String - the URI of the plugin
064: * @since 3.3.1 added by Adrian Paschke
065: */
066: public synchronized void addPlugIn(
067: org.mandarax.kernel.KnowledgeBase plugin, String id)
068: throws IllegalArgumentException {
069: if (plugin == null)
070: throw new IllegalArgumentException();
071: // check if plugin already in knowledgebase
072: List clauses1 = getClauseSets();
073: for (Iterator it1 = clauses1.iterator(); it1.hasNext();) {
074: ClauseSet cs1 = (ClauseSet) it1.next();
075: String id1 = cs1.getProperty("ID");
076: if (id1 != null)
077: if (id1.equals(id))
078: throw new IllegalArgumentException("PlugIn " + id
079: + " already exists");
080: }
081:
082: // add new clause set (axiom) to knowledgebase
083: List clauses = plugin.getClauseSets();
084: for (Iterator it = clauses.iterator(); it.hasNext();) {
085: ClauseSet cs = (ClauseSet) it.next();
086: cs.setProperty("ID", id);
087: add(cs);
088: }
089: }
090:
091: /**
092: * Add plugin to knowledgebase
093: * @parameter plugin a ClauseSet list
094: * @parameter id String - the URI of the plugin
095: * @since 3.3.1 added by Adrian Paschke
096: */
097: public synchronized void addPlugIn(List plugin, String id)
098: throws IllegalArgumentException {
099: if (plugin == null)
100: throw new IllegalArgumentException();
101: // check if plugin already in knowledgebase
102: List clauses1 = getClauseSets();
103: for (Iterator it1 = clauses1.iterator(); it1.hasNext();) {
104: ClauseSet cs1 = (ClauseSet) it1.next();
105: String id1 = cs1.getProperty("ID");
106: if (id1 != null)
107: if (id1.equals(id))
108: throw new IllegalArgumentException("PlugIn " + id
109: + " already exists");
110: }
111:
112: // add new clause set (axiom) to knowledgebase
113: for (Iterator it = plugin.iterator(); it.hasNext();) {
114: try {
115: ClauseSet cs = (ClauseSet) it.next();
116: cs.setProperty("ID", id);
117: add(cs);
118: } catch (Exception ex) {
119: throw new IllegalArgumentException("PlugIn " + id
120: + " contains no ClauseSets");
121: }
122: }
123: }
124:
125: /**
126: * Add plugin to knowledgebase
127: * @parameter plugin a ClauseSet[] array
128: * @parameter id String - the URI of the plugin
129: * @since 3.3.1 added by Adrian Paschke
130: */
131: public synchronized void addPlugIn(ClauseSet[] plugin, String id)
132: throws IllegalArgumentException {
133: if (plugin == null)
134: throw new IllegalArgumentException();
135: // check if plugin already in knowledgebase
136: List clauses1 = getClauseSets();
137: for (Iterator it1 = clauses1.iterator(); it1.hasNext();) {
138: ClauseSet cs1 = (ClauseSet) it1.next();
139: String id1 = cs1.getProperty("ID");
140: if (id1 != null)
141: if (id1.equals(id))
142: throw new IllegalArgumentException("PlugIn " + id
143: + " already exists");
144: }
145:
146: // add new clause set (axiom) to knowledgebase
147: for (int i = 0; i <= plugin.length; i++) {
148: ClauseSet cs = (ClauseSet) plugin[i];
149: cs.setProperty("ID", id);
150: add(cs);
151: }
152: }
153:
154: /**
155: * Remove plugin with id from knowledgebase
156: * @parameter id String - the plugin URI
157: * @since 3.3.1 added by Adrian Paschke
158: */
159: public synchronized void removePlugIn(String id) {
160: List clauses = getClauseSets();
161: for (Iterator it = clauses.iterator(); it.hasNext();) {
162: ClauseSet cs = (ClauseSet) it.next();
163: String id1 = cs.getProperty("ID");
164: if (id1 != null)
165: if (id.equals(id))
166: remove(cs);
167: }
168: }
169:
170: /**
171: * Add a clause set.
172: * @param c org.mandarax.kernel.ClauseSet
173: */
174: public synchronized void add(ClauseSet c) {
175: boolean logEnabled = LOG_KB_ADD.isDebugEnabled();
176:
177: container.addElement(c);
178: c.addClauseSetChangeListener(this );
179:
180: if (logEnabled) {
181: LOG_KB_ADD.debug("Added clause "
182: + ((c == null) ? "null" : c.toString())
183: + " to knowledge base " + toString());
184: }
185:
186: Object key = c.getKey();
187:
188: if (key != null) {
189: if (key.getClass().isArray()) {
190: Object[] keys = (Object[]) key;
191:
192: for (int i = 0; i < keys.length; i++) {
193: getOrAddIndexed(keys[i]).addElement(c);
194:
195: if (logEnabled) {
196: LOG_KB_ADD.debug("Register clause "
197: + ((c == null) ? "null" : c.toString())
198: + " with index " + keys[i].toString());
199: }
200: }
201: } else {
202: getOrAddIndexed(key).addElement(c);
203:
204: if (logEnabled) {
205: LOG_KB_ADD.debug(("Register clause "
206: + ((c == null) ? "null" : c.toString())
207: + " with index " + key == null) ? "null"
208: : key.toString());
209: }
210: }
211: }
212:
213: fireKnowledgeBaseChanged(KnowledgeBaseChangeEvent.CLAUSE_ADDED,
214: c);
215: }
216:
217: /**
218: * Iterate over all clauses.
219: * @return a clause iterator
220: */
221: public synchronized org.mandarax.util.ClauseIterator clauses() {
222: return new org.mandarax.util.MultipleClauseSetIterator(
223: container);
224: }
225:
226: /**
227: * Iterate over all clauses found for a certain key.
228: * @return org.mandarax.util.ClauseIterator
229: * @param query a query
230: * @param additionalParameter an additional parameter
231: */
232: public org.mandarax.util.ClauseIterator clauses(Clause query,
233: Object additionalParameter) {
234: Object key = query.getKey();
235:
236: if (key instanceof org.mandarax.kernel.Predicate) {
237: return new org.mandarax.util.MultipleClauseSetIterator(
238: getOrAddIndexed(key), query, additionalParameter);
239: } else {
240: return new org.mandarax.util.MultipleClauseSetIterator(
241: new Vector(0));
242: }
243: }
244:
245: /**
246: * Handle a clause set change event.
247: * @param e an event
248: */
249: public void clauseSetChanged(ClauseSetChangeEvent e) {
250:
251: // if the predicate has changed, reregister changed clause
252: if ((e.getType() == ClauseSetChangeEvent.KEY_CHANGED)
253: && (e.getSource() instanceof ClauseSet)) {
254: ClauseSet cs = (ClauseSet) e.getSource();
255:
256: remove(cs);
257: add(cs);
258:
259: if (LOG_KB_EVENT.isDebugEnabled()) {
260: LOG_KB_EVENT.debug(("Knowledge base " + toString()
261: + " has handled event " + e == null) ? "" : e
262: .toString());
263: }
264: }
265: }
266:
267: /**
268: * Get a list containing all clause sets.
269: * Note that the collection returned is a read only copy of the
270: * internal collection of clause sets.
271: * @return a list containing all clause sets
272: */
273: public java.util.List getClauseSets() {
274: return Collections.unmodifiableList(container);
275: }
276:
277: /**
278: * Get a list containing all clause sets that have the key.
279: * @param the key object
280: * @return a list containing all clause sets
281: */
282: public java.util.List getClauseSets(Object key) {
283: return (List) indexed.get(key);
284: }
285:
286: /**
287: * Get the feature descriptions.
288: * @return the feature descriptions
289: */
290: public KnowledgeBaseFeatureDescriptions getFeatureDescriptions() {
291: if (featureDescriptions == null) {
292: featureDescriptions = new KnowledgeBaseFeatureDescriptions() {
293: protected void initialize() {
294: super .initialize();
295: }
296: };
297: }
298:
299: return featureDescriptions;
300: }
301:
302: /**
303: * Get the keys.
304: * @return the keys
305: */
306: public java.util.Collection getKeys() {
307: return indexed.keySet();
308: }
309:
310: /**
311: * Either get or add an indexed container for the clause c.
312: * @return a collection containing clauses with this key
313: * @param k a key object
314: */
315: private java.util.Vector getOrAddIndexed(Object k) {
316: java.util.Vector v = (java.util.Vector) indexed.get(k);
317:
318: if (v == null) {
319: v = new java.util.Vector();
320:
321: indexed.put(k, v);
322: }
323:
324: return v;
325: }
326:
327: /**
328: * Either get or add an indexed container for the clause set c.
329: * @return a collection where to add the clause set
330: * @param c a clause set
331: */
332: private java.util.Vector getOrAddIndexed(ClauseSet c) {
333: return getOrAddIndexed(c.getKey());
334: }
335:
336: /**
337: * Remove a clause set.
338: * @return true if the object has been found, false otherwise
339: * @param c the clause set
340: */
341: public synchronized boolean remove(ClauseSet c) {
342: boolean logEnabled = LOG_KB_REMOVE.isDebugEnabled();
343: boolean success = container.removeElement(c);
344:
345: c.removeClauseSetChangeListener(this );
346:
347: if (logEnabled) {
348: LOG_KB_REMOVE.debug("Removed clause "
349: + ((c == null) ? "null" : c.toString())
350: + " from knowledge base " + toString());
351: }
352:
353: Object key = c.getKey();
354:
355: if (key != null) {
356: if (key.getClass().isArray()) {
357: Object[] keys = (Object[]) key;
358:
359: for (int i = 0; i < keys.length; i++) {
360: success = success
361: & getOrAddIndexed(keys[i]).removeElement(c);
362:
363: if (logEnabled) {
364: LOG_KB_REMOVE
365: .debug(("Unregister clause "
366: + ((c == null) ? "null" : c
367: .toString())
368: + " from index " + key == null) ? "null"
369: : key.toString());
370: }
371: }
372: } else {
373: success = success
374: & getOrAddIndexed(key).removeElement(c);
375: }
376: }
377:
378: fireKnowledgeBaseChanged(
379: KnowledgeBaseChangeEvent.CLAUSE_REMOVED, c);
380:
381: return success;
382: }
383:
384: /**
385: * Remove all clauses.
386: */
387: public synchronized void removeAll() {
388: indexed = new Hashtable();
389:
390: for (Iterator it = container.iterator(); it.hasNext();) {
391: ((ClauseSet) it.next()).removeClauseSetChangeListener(this );
392: }
393:
394: if (LOG_KB_REMOVE.isDebugEnabled()) {
395: LOG_KB_REMOVE
396: .debug("Remove all clauses from knowledge base "
397: + toString());
398: }
399:
400: fireKnowledgeBaseChanged(
401: KnowledgeBaseChangeEvent.CLAUSE_REMOVED, Collections
402: .unmodifiableList(container));
403:
404: container = new Vector();
405: }
406: }
|