001: package org.mandarax.zkb.framework;
002:
003: /**
004: * Copyright (C) 1999-2004 Jens Dietrich (mailto:mandarax@jbdietrich.com)
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:
021: import java.io.PrintWriter;
022: import java.util.Comparator;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import org.jdom.Comment;
027: import org.jdom.Element;
028: import org.mandarax.kernel.ClauseSet;
029: import org.mandarax.kernel.ExtendedKnowledgeBase;
030: import org.mandarax.kernel.Fact;
031: import org.mandarax.kernel.KnowledgeBase;
032: import org.mandarax.kernel.LogicFactory;
033: import org.mandarax.kernel.Query;
034: import org.mandarax.kernel.Rule;
035: import org.mandarax.sql.SQLClauseSet;
036: import org.mandarax.zkb.ObjectPersistencyService;
037: import org.mandarax.zkb.ZKBException;
038:
039: /**
040: * An adapter class for knowledge bases.
041: * @see org.mandarax.kernel.KnowledgeBase
042: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
043: * @version 3.4 <7 March 05>
044: * @since 2.2
045: */
046:
047: public class Adapter4KnowledgeBases extends AbstractAdapter {
048:
049: // constant for comparator attribute
050:
051: /**
052: * Export an object, i.e., convert it to an element in the DOM.
053: * @param obj an object
054: * @param driver the generic driver
055: * @param ops the object persistency service
056: * @exception a ZKBException is thrown if export fails
057: */
058: public Element exportObject(Object obj, GenericDriver driver,
059: ObjectPersistencyService ops) throws ZKBException {
060: check(obj, KnowledgeBase.class);
061: int ftl = driver.getFaultToleranceLevel();
062: PrintWriter out = driver.getLogWriter();
063: KnowledgeBase kb = (KnowledgeBase) obj;
064: Element e = new Element(RULE_BASE);
065:
066: e.setAttribute(CLASS, kb.getClass().getName());
067:
068: // export comparator
069: if (kb instanceof ExtendedKnowledgeBase) {
070: Comparator comp = ((ExtendedKnowledgeBase) kb)
071: .getComparator();
072: if (comp != null) {
073: e
074: .addContent(exportObject(comp, COMPARATOR,
075: driver, ops));
076: }
077: }
078:
079: // export knowledge
080: List clauseSets = kb.getClauseSets();
081: for (Iterator it = clauseSets.iterator(); it.hasNext();) {
082: ClauseSet cs = (ClauseSet) it.next();
083: String kindOfObject = getClauseSetType(cs);
084: if (kindOfObject == null) {
085: String msg = "Cannot figure out what kind of clause set the following object is: "
086: + cs;
087: if (ftl == GenericDriver.LOW_FAULT_TOLERANCE)
088: throw new ZKBException(msg);
089: // do nothing if (ftd==driver.HIGH_FAULT_TOLERANCE)
090: else {
091: out.println("Warning");
092: out.println(msg);
093: out.println("The clause is ignored");
094: LOG_XKB.warn(msg);
095: LOG_XKB.warn("The clause is ignored");
096: }
097: } else {
098: try {
099: Element el = exportObject(cs, kindOfObject, driver,
100: ops);
101: e.addContent(el);
102: } catch (ZKBException x) {
103: String msg = "Problems exporting the knowledge base, export failed for "
104: + cs;
105: if (ftl == GenericDriver.LOW_FAULT_TOLERANCE)
106: throw new ZKBException(msg);
107: // do nothing if (ftd==driver.HIGH_FAULT_TOLERANCE)
108: else {
109: out.println(msg);
110: out.println("See log for details");
111: e.addContent(new Comment(msg));
112: LOG_XKB.error(msg, x);
113: }
114: }
115:
116: }
117: }
118: // export queries
119: for (Iterator it = kb.queryNames(); it.hasNext();) {
120: Query q = kb.getQuery((String) it.next());
121: try {
122: Element el = exportObject(q, GenericDriver.QUERY,
123: driver, ops);
124: e.addContent(el);
125: } catch (ZKBException x) {
126: String msg = "Problems exporting the knowledge base, export failed for query "
127: + q;
128: if (ftl == GenericDriver.LOW_FAULT_TOLERANCE)
129: throw new ZKBException(msg);
130: // do nothing if (ftd==driver.HIGH_FAULT_TOLERANCE)
131: else {
132: out.println(msg);
133: out.println("See log for details");
134: e.addContent(new Comment(msg));
135: LOG_XKB.error(msg, x);
136: }
137: }
138: }
139: return e;
140: }
141:
142: /**
143: * Get the type of clause set, e.g. GenericDriver.FACT or GenericDriver.RULE.
144: * @param cs a clause set
145: * @return a string
146: */
147: protected String getClauseSetType(ClauseSet cs) {
148: if (cs instanceof Rule)
149: return RULE;
150: else if (cs instanceof Fact)
151: return FACT;
152: else if (cs instanceof SQLClauseSet)
153: return SQL_CLAUSE_SET;
154: else
155: return CUSTOM_CLAUSE_SET;
156: }
157:
158: /**
159: * Build an object from an XML element.
160: * @param e an element
161: * @param driver the generic driver
162: * @param ops the object persistency service
163: * @param lfactory the logic factory used to create objects
164: * @exception a ZKBException is thrown if export fails
165: */
166: public Object importObject(Element e, GenericDriver driver,
167: ObjectPersistencyService ops, LogicFactory lfactory)
168: throws ZKBException {
169: // try to instanciate saved class
170: KnowledgeBase kb = null;
171: String implClassName = e.getAttributeValue(CLASS);
172: if (implClassName != null) {
173: try {
174: Class implClass = Class.forName(implClassName);
175: kb = (KnowledgeBase) implClass.newInstance();
176: } catch (ClassNotFoundException x) {
177: LOG_ZKB.error("Cannot find class " + implClassName
178: + ", will use default", x);
179: } catch (IllegalAccessException x) {
180: LOG_ZKB.error("Cannot instanciate class "
181: + implClassName + ", will use default", x);
182: } catch (InstantiationException x) {
183: LOG_ZKB.error("Cannot instanciate class "
184: + implClassName + ", will use default", x);
185: }
186: }
187: if (kb == null)
188: kb = new org.mandarax.reference.AdvancedKnowledgeBase();
189:
190: int ftl = driver.getFaultToleranceLevel();
191: PrintWriter out = driver.getLogWriter();
192: List children = e.getChildren();
193: for (Iterator it = children.iterator(); it.hasNext();) {
194: Element child = (Element) it.next();
195: Adapter adapter = driver.getAdapter(child.getName());
196: if (child.getName().equals(COMPARATOR)) {
197: Comparator comp = (Comparator) adapter.importObject(
198: child, driver, ops, lfactory);
199: if (kb instanceof ExtendedKnowledgeBase)
200: ((ExtendedKnowledgeBase) kb).setComparator(comp);
201: } else {
202: try {
203: Object obj = adapter.importObject(child, driver,
204: ops, lfactory);
205: if (obj instanceof ClauseSet)
206: kb.add((ClauseSet) obj);
207: else if (obj instanceof Query)
208: kb.addQuery((Query) obj);
209: else
210: throw new ZKBException(
211: "Can only import clause sets and queries into repository, import for object failed: "
212: + obj);
213: } catch (ZKBException x) {
214: String msg = "Problems importing the knowledge base, import failed for element "
215: + e.getText();
216: if (ftl == GenericDriver.LOW_FAULT_TOLERANCE)
217: throw new ZKBException(msg);
218: // do nothing if (ftd==driver.HIGH_FAULT_TOLERANCE)
219: else {
220: out.println(msg);
221: out.println("See log for details");
222: LOG_XKB.error(msg, x);
223: }
224: }
225: }
226: }
227: return kb;
228: }
229:
230: /**
231: * Get the name of the associated tag (element).
232: * @return a string
233: */
234: public String getTagName() {
235: return RULE_BASE;
236: }
237:
238: /**
239: * Get the kind of object the adapter can export/import.
240: * @return a string
241: */
242: public String getKindOfObject() {
243: return RULE_BASE;
244: }
245:
246: /**
247: * Print the DTD associated with this adapter on a string buffer.
248: * @param out the buffer to print on.
249: */
250: public void printDTD(StringBuffer out) {
251: out
252: .append("<!ELEMENT rulebase (comparator?,(atom|rule|sql_clause_set|custom_clause_set|query)*)>\n");
253: out.append("<!ATTLIST rulebase class CDATA #IMPLIED>\n");
254: }
255:
256: }
|