View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    Copyright (c) 2005, University of Innsbruck, Austria
4    This library is free software; you can redistribute it and/or modify it under
5    the terms of the GNU Lesser General Public License as published by the Free
6    Software Foundation; either version 2.1 of the License, or (at your option)
7    any later version.
8    This library is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11   details.
12   You should have received a copy of the GNU Lesser General Public License along
13   with this library; if not, write to the Free Software Foundation, Inc.,
14   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15   */
16  package org.deri.wsmo4j.io.parser.xml;
17  
18  
19  import java.math.*;
20  import java.util.*;
21  
22  import org.deri.wsmo4j.logicalexpression.*;
23  import org.omwg.logicalexpression.*;
24  import org.omwg.logicalexpression.terms.*;
25  import org.omwg.ontology.Variable;
26  import org.w3c.dom.*;
27  import org.wsmo.common.*;
28  import org.wsmo.factory.*;
29  import org.wsmo.wsml.*;
30  
31  
32  /**
33   * @author retkru
34   * @see org.deri.wsmo4j.io.parser.xml.LogExprParserImpl
35   */
36  public class XMLExprParser {
37  
38      DataFactory df;
39      LogicalExpressionFactory leFactory;
40      WsmoFactory factory;
41  
42      public XMLExprParser(WsmoFactory factory, 
43              LogicalExpressionFactory leFactory,  DataFactory df){
44          this.df=df;
45          this.leFactory=leFactory;
46          this.factory=factory;
47      }
48      
49      /**
50       * Recursively builds logical expressions
51       * @param exprNode SableCC Node that will be parsed, it expects a Node of the
52       *                 type "PLogExpr"
53       * @return logical expression object model
54       * @throws ParserException in case exprNode is an invalid node or in case
55       * a wrong element name for a term is submitted to the evaluateXMLTerm method
56       * @see org.deri.wsmo4j.io.parser.xml.LogExprParserImpl#parse(Object)
57       */
58      public LogicalExpression evaluateXML(Element exprNode)
59              throws ParserException {
60          String exprName = exprNode.getNodeName();
61          LogicalExpression logExpr = null;
62          //resolve all non-text child nodes, in that way we can ensure not
63          //to fall into the trap of whitespace text
64          List exprs = null;
65          if (exprName.equals("and")) {
66              exprs = childElements(exprNode.getChildNodes());
67              logExpr = evaluateXMLAnd(exprs);
68          }
69          else if (exprName.equals("or")) {
70              exprs = childElements(exprNode.getChildNodes());
71              logExpr = evaluateXMLOr(exprs);
72          }
73          else if (exprName.equals("forall")) {
74              exprs = childElements(exprNode.getChildNodes());
75              logExpr = evaluateXMLForAll(exprs);
76          }
77          else if (exprName.equals("exists")) {
78              exprs = childElements(exprNode.getChildNodes());
79              logExpr = evaluateXMLExists(exprs);
80          }
81          else if (exprName.equals("equivalent")) {
82              exprs = childElements(exprNode.getChildNodes());
83              logExpr = evaluateXMLEquals(exprs);
84          }
85          else if (exprName.equals("impliedBy")) {
86              exprs = childElements(exprNode.getChildNodes());
87              logExpr = evaluateXMLImpliedBy(exprs);
88          }
89          else if (exprName.equals("implies")) {
90              exprs = childElements(exprNode.getChildNodes());
91              logExpr = evaluateXMLImplies(exprs);
92          }
93          else if (exprName.equals("impliedByLP")) {
94              exprs = childElements(exprNode.getChildNodes());
95              logExpr = evaluateXMLImpliesLP(exprs);
96          }
97          else if (exprName.equals("naf")) {
98              exprs = childElements(exprNode.getChildNodes());
99              logExpr = evaluateXMLNaf(exprs);
100         }
101         else if (exprName.equals("neg")) {
102             exprs = childElements(exprNode.getChildNodes());
103             logExpr = evaluateXMLNeg(exprs);
104         }
105         else if (exprName.equals("constraint")) {
106             exprs = childElements(exprNode.getChildNodes());
107             logExpr = evaluateXMLConstraing(exprs);
108         }
109         else if (exprName.equals("molecule")) {
110             NodeList cptE = exprNode.getElementsByTagName("isa");
111             NodeList attrValue = exprNode.getElementsByTagName("attributeValue");
112             NodeList attrDef = exprNode.getElementsByTagName("attributeDefinition");
113 
114             Term t = evaluateXMLTerm((Element)exprNode.getElementsByTagName("term").item(0));
115             List <Molecule> molecules = new Vector <Molecule>();
116 
117             if (attrValue.getLength() > 0 || attrDef.getLength() > 0) {
118                 if (attrValue.getLength() > 0) {
119                     molecules.addAll(evaluateXMLAttrValue(attrValue, t));
120                 }
121                 if (attrDef.getLength() > 0) {
122                     molecules.addAll(evaluateXMLAttrDef(attrDef, t));
123                 }
124             }
125             if (cptE.getLength() > 0) {
126                 Node isa = cptE.item(0);
127                 String type = isa.getAttributes().getNamedItem("type").getNodeValue();
128                 if (type.equals("memberOf")) {
129                     Iterator types = evaluateXMLIsa(cptE).iterator();
130                     while (types.hasNext()){
131                         molecules.add(leFactory.createMemberShipMolecule(
132                                 t,(Term)types.next()));
133                     }
134                 }
135                 else if (type.equals("subConceptOf")) {
136                     Iterator types = evaluateXMLIsa(cptE).iterator();
137                     while (types.hasNext()){
138                         molecules.add(leFactory.createSubConceptMolecule(
139                                 t,(Term)types.next()));
140                     }
141                 }
142             }
143             if (molecules.size()==0){
144                 throw new ParserException("XML Parse Error: Molecule element without content detected! ("+t+")", null);
145             }
146             else if (molecules.size()==1){
147                 logExpr = molecules.remove(0);
148             }
149             else {
150                 logExpr = leFactory.createCompoundMolecule(molecules);
151             }
152         }
153         else if (exprName.equals("atom")) {
154             logExpr = evaluateXMLConstructed(exprNode, factory.createIRI(exprNode.getAttribute("name")));
155 
156             /*} else if (exprName.equals("term")) {
157                 args.add(_().createLEIRI(exprNode.getAttribute("name")));
158                 logExpr = _().createLogExpression(Operator.ATOM,pOp,args);*/
159         }
160         else {
161             throw new ParserException("XML Parse Error... : " + exprName, null);
162         }
163         return logExpr;
164     }
165 
166     /**
167      * Creates Variables or basic terms
168      * @param exprNode Element
169      * @return a Term
170      * @throws ParserException in case the Element name is wrong
171      */
172     private Term evaluateXMLTerm(Element exprNode)
173             throws ParserException {
174         String exprName = exprNode.getNodeName();
175         Term t = null;
176         if (exprName.equals("variable")) {
177             try {
178                 t = leFactory.createVariable(exprNode.getAttribute("name").substring(1));
179             }
180             catch (IllegalArgumentException e) {
181                 throw new ParserException("XML Parse Error: Zero-length variable not allowed.", e);
182             }
183             //FIXME: ADD COMPLEX DATAVALUES!
184         }
185         else if (exprName.equals("term") ||
186                  exprName.equals("name") ||
187                  exprName.equals("arg") ||
188                  exprName.equals("value")) {
189             String iriStr = exprNode.getAttribute("name");
190             String notation = ConstantTransformer.getInstance().findNotation(iriStr);
191             if (notation != null && notation.equals("_integer")) {
192                 t = df.createWsmlInteger(new BigInteger(exprNode.getFirstChild().getNodeValue()));
193             }
194             else if (notation != null && notation.equals("_decimal")) {
195                 t = df.createWsmlDecimal(new BigDecimal(exprNode.getFirstChild().getNodeValue()));
196             }
197             else if (notation != null && notation.equals("_string")) {
198                 t = df.createWsmlString(exprNode.getFirstChild().getNodeValue());
199             }
200             else if (iriStr.equals(Constants.ANONYMOUS_ID)) {
201                 t = factory.createAnonymousID();
202             }
203             else if (iriStr.startsWith(Constants.ANONYMOUS_ID)) {
204                 //numberedID
205                 t = leFactory.createAnonymousID(Byte.parseByte(iriStr.substring(iriStr.lastIndexOf("ID") + 2)));
206             }
207             else {
208                 t = helpEvaluateTerm(exprNode, iriStr);
209             }
210         }
211         else if (exprName.equals("type")) {
212             t = factory.createIRI(exprNode.getAttributes().getNamedItem("name").getNodeValue());
213         }
214         else {
215             throw new ParserException("XML Parse Error: wrong element name: " + exprName + " for a term", null);
216         }
217         return t;
218     }
219 
220     /**
221      * Creates a variable, an IRI or a ConstructedTerm
222      * @param exprNode Node
223      * @param iriStr
224      * @return a Term
225      * @throws ParserException in case a wrong element name for a term is submitted
226      * to the evaluateXMLTerm method
227      */
228     private Term helpEvaluateTerm(Element exprNode, String iriStr)
229             throws ParserException {
230         Term t;
231         if (iriStr.startsWith("?")) {
232             try {
233                 t = leFactory.createVariable(iriStr.substring(1));
234             }
235             catch (IllegalArgumentException e) {
236                 throw new ParserException("XML Parse Error: Zero-length variable not allowed.", e);
237             }
238         }
239         else {
240             IRI iri = factory.createIRI(iriStr);
241             if (exprNode.getChildNodes().getLength() > 1) {
242                 Element e;
243                 Vector <Term> ll = new Vector <Term>();
244                 NodeList nl = exprNode.getChildNodes();
245                 for (int i = 0; i < nl.getLength(); i++) {
246                     Node n = nl.item(i);
247                     if (n instanceof Element) {
248                         e = (Element)n;
249                         ll.add(evaluateXMLTerm(e));
250                     }
251                 }
252                 t = leFactory.createConstructedTerm(iri, ll);
253             }
254             else {
255                 t = iri;
256             }
257         }
258         return t;
259     }
260 
261     /**
262      * Builds a Quantified LogicalExpression
263      * @param exprs a list of child elements of a specified Node
264      * @param op type of operator
265      * @return Quantified Logical Expression
266      * @throws ParserException in case an invalid node is submitted to the
267      * evaluateXML method
268      */
269     private LogicalExpression evaluateXMLExists(List exprs)
270             throws ParserException {
271         HashSet <Variable> hs = new HashSet <Variable>();
272         for (int i = 0; i < exprs.size() - 1; i++) {
273             hs.add((Variable) evaluateXMLTerm((Element)exprs.get(i)));
274         }
275         return leFactory.createExistentialQuantification(hs, evaluateXML((Element)exprs.get(exprs.size() - 1)));
276     }
277 
278     private LogicalExpression evaluateXMLForAll(List exprs)
279             throws ParserException {
280         HashSet  <Variable> hs = new HashSet <Variable> ();
281         for (int i = 0; i < exprs.size() - 1; i++) {
282             hs.add((Variable) evaluateXMLTerm((Element)exprs.get(i)));
283         }
284         return leFactory.createUniversalQuantification(hs, evaluateXML((Element)exprs.get(exprs.size() - 1)));
285     }
286 
287     /**
288      * Builds a Binary LogicalExpression
289      * @param exprs a list of child elements of a specified Node
290      * @param op type of operator
291      * @return Binary Logical Expression
292      * @throws ParserException in case an invalid node is submitted to the
293      * evaluateXML method
294      */
295     private LogicalExpression evaluateXMLAnd(List exprs)
296             throws ParserException {
297         return leFactory.createConjunction(evaluateXML((Element)exprs.get(0)), evaluateXML((Element)exprs.get(1)));
298     }
299 
300     private LogicalExpression evaluateXMLOr(List exprs)
301             throws ParserException {
302         return leFactory.createDisjunction(evaluateXML((Element)exprs.get(0)), evaluateXML((Element)exprs.get(1)));
303     }
304 
305     private LogicalExpression evaluateXMLImplies(List exprs)
306             throws ParserException {
307         return leFactory.createImplication(evaluateXML((Element)exprs.get(0)), evaluateXML((Element)exprs.get(1)));
308     }
309 
310     private LogicalExpression evaluateXMLImpliesLP(List exprs)
311             throws ParserException {
312         return leFactory.createLogicProgrammingRule(evaluateXML((Element)exprs.get(0)),
313                 evaluateXML((Element)exprs.get(1)));
314     }
315 
316     private LogicalExpression evaluateXMLImpliedBy(List exprs)
317             throws ParserException {
318         return leFactory.createInverseImplication(evaluateXML((Element)exprs.get(0)), evaluateXML((Element)exprs.get(1)));
319     }
320 
321     private LogicalExpression evaluateXMLEquals(List exprs)
322             throws ParserException {
323         return leFactory.createEquivalence(evaluateXML((Element)exprs.get(0)), evaluateXML((Element)exprs.get(1)));
324     }
325 
326     /**
327      * Builds an Unary LogicalExpression
328      * @param exprs a list of child elements of a specified Node
329      * @param op type of operator
330      * @return Unary Logical Expression
331      * @throws ParserException in case an invalid node is submitted to the
332      * evaluateXML method
333      */
334     private LogicalExpression evaluateXMLNeg(List exprs)
335             throws ParserException {
336         return leFactory.createNegation(evaluateXML((Element)exprs.get(0)));
337     }
338 
339     private LogicalExpression evaluateXMLNaf(List exprs)
340             throws ParserException {
341         return leFactory.createNegationAsFailure(evaluateXML((Element)exprs.get(0)));
342     }
343 
344     private LogicalExpression evaluateXMLConstraing(List exprs)
345             throws ParserException {
346         return leFactory.createConstraint(evaluateXML((Element)exprs.get(0)));
347     }
348 
349     private Set <Molecule> evaluateXMLAttrValue(NodeList attValue, Term id)
350             throws ParserException {
351         Set <Molecule> molecules = new HashSet <Molecule> ();
352         for (int i = 0; i < attValue.getLength(); i++) {
353             Node singleAttVal = attValue.item(i);
354             Term attributeName = evaluateXMLTerm((Element)childElements(((Element)singleAttVal).getElementsByTagName("name")).get(0));
355             List  attValContent = childElements(((Element)singleAttVal).getElementsByTagName("value"));
356             for (int j = 0; j < attValContent.size(); j++) {
357                 Term value = evaluateXMLTerm((Element)attValContent.get(j));
358                 molecules.add(leFactory.createAttributeValue(id, attributeName, value));
359             }
360         }
361         return molecules;
362     }
363 
364     /**
365      * Put the Attribute Definitions of a Molecule (contained in the NodeList attDef)
366      * into a Set. A NodeList contains all children of a specified Node.
367      * @param attDef a list of child elements of a specified Node
368      * @param id id of the molecule
369      * @return a Set of molecules
370      * @throws ParserException in case a wrong element name for a term is submitted
371      * to the evaluateXMLTerm method
372      */
373     private Set <Molecule> evaluateXMLAttrDef(NodeList attDef, Term id)
374             throws ParserException {
375         Set <Molecule> molecules = new HashSet <Molecule> ();
376         for (int i = 0; i < attDef.getLength(); i++) {
377             Node singleAttDef = attDef.item(i);
378             Term attributeName = evaluateXMLTerm((Element)childElements(((Element)singleAttDef).getElementsByTagName("name")).get(0));
379             List attDefContent = childElements(((Element)singleAttDef).getElementsByTagName("type"));
380             for (int j = 0; j < attDefContent.size(); j++) {
381                 Term type = evaluateXMLTerm((Element)attDefContent.get(j));
382                 if (singleAttDef.getAttributes().getNamedItem("type").getNodeValue().equals("constraining")) {
383                     molecules.add(leFactory.createAttributeConstraint(
384                             id, attributeName,  type));
385                 }else{
386                     molecules.add(leFactory.createAttributeInference(
387                             id, attributeName,  type));
388                 }
389             }
390         }
391         return molecules;
392     }
393 
394     private List <Term> evaluateXMLIsa(NodeList cptE)
395             throws ParserException {
396         NodeList isaTerms;
397         List <Term> set = new Vector <Term> ();
398         for (int i = 0; i < cptE.getLength(); i++) {
399             isaTerms = ((Element)cptE.item(i)).getElementsByTagName("term");
400             for (int j = 0; j < isaTerms.getLength(); j++) {
401                 set.add(evaluateXMLTerm((Element)isaTerms.item(j)));
402             }
403         }
404         return set;
405     }
406 
407     /**
408      * Creates an Atom
409      * @param exprNode exprNode SableCC Node that will be parsed, it expects a Node of the
410      *                 type "PLogExpr"
411      * @param identifier identifier of the Atom
412      * @return Atom
413      * @throws ParserException in case a wrong element name for a term is submitted
414      * to the evaluateXMLTerm method
415      */
416     private LogicalExpression evaluateXMLConstructed(Node exprNode, IRI identifier)
417             throws ParserException {
418         Element e;
419         Vector <Term> ll = new Vector <Term> ();
420         NodeList nl = exprNode.getChildNodes();
421         for (int i = 0; i < nl.getLength(); i++) {
422             Node n = nl.item(i);
423 
424             if (n instanceof Element) {
425                 e = (Element)n;
426                 ll.add(evaluateXMLTerm(e));
427             }
428         }
429         return leFactory.createAtom(identifier, ll);
430     }
431 
432     /**
433      * A NodeList contains all children of a specified Node. If there are no
434      * children, this is a NodeList containing no nodes. The children
435      * from the NodeList are put into a LinkedList
436      *
437      * @param nodes a list of child elements of a specified Node.
438      * @return a list of child elements of a specified Node
439      */
440     private List <Node> childElements(NodeList nodes) {
441         List <Node> list = new LinkedList <Node>();
442         for (int i = 0; i < nodes.getLength(); i++) {
443             if (nodes.item(i)instanceof Element) {
444                 list.add(nodes.item(i));
445             }
446         }
447         return list;
448     }
449 }