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.validator;
17  
18  
19  import java.util.List;
20  
21  import org.deri.wsmo4j.io.serializer.wsml.LogExprSerializerWSML;
22  import org.deri.wsmo4j.logicalexpression.ConstantTransformer;
23  import org.omwg.logicalexpression.Atom;
24  import org.omwg.logicalexpression.AttributeConstraintMolecule;
25  import org.omwg.logicalexpression.AttributeInferenceMolecule;
26  import org.omwg.logicalexpression.AttributeValueMolecule;
27  import org.omwg.logicalexpression.Binary;
28  import org.omwg.logicalexpression.CompoundMolecule;
29  import org.omwg.logicalexpression.Conjunction;
30  import org.omwg.logicalexpression.Constants;
31  import org.omwg.logicalexpression.Constraint;
32  import org.omwg.logicalexpression.Disjunction;
33  import org.omwg.logicalexpression.Equivalence;
34  import org.omwg.logicalexpression.ExistentialQuantification;
35  import org.omwg.logicalexpression.Implication;
36  import org.omwg.logicalexpression.InverseImplication;
37  import org.omwg.logicalexpression.LogicProgrammingRule;
38  import org.omwg.logicalexpression.LogicalExpression;
39  import org.omwg.logicalexpression.MembershipMolecule;
40  import org.omwg.logicalexpression.Negation;
41  import org.omwg.logicalexpression.NegationAsFailure;
42  import org.omwg.logicalexpression.SubConceptMolecule;
43  import org.omwg.logicalexpression.Unary;
44  import org.omwg.logicalexpression.UniversalQuantification;
45  import org.omwg.logicalexpression.Visitor;
46  import org.omwg.ontology.Axiom;
47  import org.wsmo.common.WSML;
48  import org.wsmo.validator.ValidationError;
49  
50  
51  /**
52   * Checks logical expressions for wsml-rule validity.
53   *
54   * @author nathalie.steinmetz@deri.org
55   */
56  public class WsmlRuleExpressionValidator
57          implements Visitor {
58      
59      private LogExprSerializerWSML leSerializer = null;
60      
61      private WsmlFullValidator validator = null;
62  
63      private Axiom axiom = null;
64      
65      private List <ValidationError> errors = null;
66      
67      private boolean body = false;
68      
69      /**
70       * @param axiom whose logical expression is checked
71       * @param errors list that will be filled with error messages of found variant violations
72       */
73      public WsmlRuleExpressionValidator(Axiom axiom, List <ValidationError> errors, WsmlFullValidator val) {
74          this.axiom = axiom;
75          this.errors = errors;
76          this.validator = val;
77          leSerializer = validator.leSerializer;
78      }
79  
80      public void setup() {
81          body = false;
82      }
83      
84      /**
85       * Checks if an Atom is valid to wsml-rule.
86       * 
87       * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitAtom(org.omwg.logicalexpression.Atom)
88       */
89      public void visitAtom(Atom expr) {
90          if (!body) {
91              boolean infix = false;
92              String iri = expr.getIdentifier().toString();
93              infix = ConstantTransformer.getInstance().isInfix(iri);
94  
95              if (infix) {
96                  if (iri.indexOf(Constants.INEQUAL) != -1) {
97                      addError(expr, ValidationError.AX_HEAD_ERR + ": Must not contain the " +
98                               "inequality symbol \"!=\":\n" + leSerializer.serialize(expr));
99                  }
100                 else if (iri.indexOf(Constants.EQUAL) != -1) {
101                     addError(expr, ValidationError.AX_HEAD_ERR + ": Must not contain the " +
102                              "equality symbol \"=\":\n" + leSerializer.serialize(expr));
103                 }
104                 else if (iri.indexOf(Constants.STRONG_EQUAL) != -1) {
105                     addError(expr, ValidationError.AX_HEAD_ERR + ": Must not contain the " +
106                              "strong equality symbol \":=:\":\n" +
107                              leSerializer.serialize(expr));
108                 }
109             }
110         }
111         else {
112             boolean infix = false;
113             String iri = expr.getIdentifier().toString();
114             infix = ConstantTransformer.getInstance().isInfix(iri);
115 
116             if (infix) {
117                 if (iri.indexOf(Constants.STRONG_EQUAL) != -1) {
118                     addError(expr, ValidationError.AX_BODY_ERR + ": Must " +
119                              "not contain the strong equality symbol \":=:\":\n" +
120                              leSerializer.serialize(expr));
121                 }
122             }
123         }
124     }
125 
126     /**
127      * Checks if an AttributeConstraintMolecule is valid to wsml-rule.
128      * 
129      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitAttributeContraintMolecule(org.omwg.logicalexpression.AttributeConstraintMolecule)
130      */
131     public void visitAttributeContraintMolecule(AttributeConstraintMolecule expr) {
132 
133     }
134 
135     /**
136      * Checks if an AttributeInferenceMolecule is valid to wsml-rule.
137      * 
138      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitAttributeInferenceMolecule(org.omwg.logicalexpression.AttributeInferenceMolecule)
139      */
140     public void visitAttributeInferenceMolecule(AttributeInferenceMolecule expr) {
141 
142     }
143 
144     /**
145      * Checks if an AttributeValueMolecule is valid to wsml-rule.
146      * 
147      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitAttributeValueMolecule(org.omwg.logicalexpression.AttributeValueMolecule)
148      */
149     public void visitAttributeValueMolecule(AttributeValueMolecule expr) {
150 
151     }
152 
153     /**
154      * Checks if an CompoundMolecule is valid to wsml-rule.
155      * 
156      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitCompoundMolecule(org.omwg.logicalexpression.CompoundMolecule)
157      */
158     public void visitCompoundMolecule(CompoundMolecule expr) {
159 
160     }
161 
162     /**
163      * Checks if an MembershipMolecule is valid to wsml-rule.
164      * 
165      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitMemberShipMolecule(org.omwg.logicalexpression.MembershipMolecule)
166      */
167     public void visitMemberShipMolecule(MembershipMolecule expr) {
168 
169     }
170 
171     /**
172      * Checks if an SubConceptMolecule is valid to wsml-rule.
173      * 
174      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitSubConceptMolecule(org.omwg.logicalexpression.SubConceptMolecule)
175      */
176     public void visitSubConceptMolecule(SubConceptMolecule expr) {
177 
178     }
179 
180     
181     /**
182      * Checks if a NegationAsFailure is valid to wsml-rule.
183      * 
184      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitNegationAsFailure(org.omwg.logicalexpression.NegationAsFailure)
185      */
186     public void visitNegationAsFailure(NegationAsFailure expr) {
187         if (!body) {
188             addError(expr, ValidationError.AX_HEAD_ERR + ": Must not " +
189                     "contain a NegationAsFailure:\n" + 
190                     leSerializer.serialize(expr));
191         }
192         else {
193             expr.getOperand().accept(this);
194         } 
195     }
196 
197     /**
198      * Checks if a Negation is valid to wsml-rule.
199      * 
200      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitNegation(org.omwg.logicalexpression.Negation)
201      */
202     public void visitNegation(Negation expr) {
203         if (!body) {
204             addError(expr, ValidationError.AX_HEAD_ERR + ": Must not " +
205                     "contain a Negation:\n" + leSerializer.serialize(expr));
206         }
207         else {
208             addError(expr, ValidationError.AX_BODY_ERR + ": Must not " +
209                     "contain a Negation:\n" + leSerializer.serialize(expr));
210             body = false;
211         }
212     }
213 
214     /**
215      * Checks if a Constraint is valid to wsml-rule.
216      * 
217      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitConstraint(org.omwg.logicalexpression.Unary)
218      */
219     public void visitConstraint(Constraint expr) {
220         if (!body) {
221             body = true;
222             expr.getOperand().accept(this);
223         }
224         else {
225             addError(expr, ValidationError.AX_BODY_ERR + ": Must not " +
226                     "contain a Negation:\n" + leSerializer.serialize(expr));
227             body = false;
228         }
229     }
230 
231     /**
232      * Checks if a Conjunction is valid to wsml-rule.
233      * 
234      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitConjunction(org.omwg.logicalexpression.Conjunction)
235      */
236     public void visitConjunction(Conjunction expr) {
237         expr.getLeftOperand().accept(this);
238         expr.getRightOperand().accept(this);
239     }
240 
241     /**
242      * Checks if a Disjunction is valid to wsml-rule.
243      * 
244      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitDisjunction(org.omwg.logicalexpression.Disjunction)
245      */
246     public void visitDisjunction(Disjunction expr) {
247         if (!body) {
248             addError(expr, ValidationError.AX_HEAD_ERR + ": Must not " +
249                     "contain a Disjunction:\n" + leSerializer.serialize(expr));
250         }
251         else {
252             expr.getLeftOperand().accept(this);
253             expr.getRightOperand().accept(this);
254         }
255     }
256 
257     /**
258      * Checks if an Equivalence is valid to wsml-rule.
259      * 
260      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitEquivalence(org.omwg.logicalexpression.Equivalence)
261      */
262     public void visitEquivalence(Equivalence expr) {
263         if (!body) {
264             if (checkHeads(expr)) {
265                 addError(expr, ValidationError.AX_HEAD_ERR + ": a and b from " +
266                         "\"a equivalent b\" must not contain {implies, " +
267                         "impliedBy, equivalent):\n" + leSerializer.serialize(expr));
268             }
269             else {
270                 expr.getLeftOperand().accept(this);
271                 expr.getRightOperand().accept(this);
272             }
273         }
274         else {
275             expr.getLeftOperand().accept(this);
276             expr.getRightOperand().accept(this);
277         }
278     }
279 
280     /**
281      * Checks if an InverseImplication is valid to wsml-rule.
282      * 
283      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitInverseImplication(org.omwg.logicalexpression.InverseImplication)
284      */
285     public void visitInverseImplication(InverseImplication expr) {
286         if (!body) {
287             if (checkHeads(expr)) {
288                 addError(expr, ValidationError.AX_HEAD_ERR + ": a and b from " +
289                         "\"a impliedBy b\" must not contain {implies, " +
290                         "impliedBy, equivalent):\n" + leSerializer.serialize(expr));
291             }
292             else {
293                 expr.getLeftOperand().accept(this);
294                 expr.getRightOperand().accept(this);
295             }
296         }
297         else {
298             expr.getLeftOperand().accept(this);
299             expr.getRightOperand().accept(this);
300         }
301     }
302 
303     /**
304      * Checks if an Implication is valid to wsml-rule.
305      * 
306      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitImplication(org.omwg.logicalexpression.Implication)
307      */
308     public void visitImplication(Implication expr) {
309         if (!body) {
310             if (checkHeads(expr)) {
311                 addError(expr, ValidationError.AX_HEAD_ERR + ": a and b " +
312                         "from \"a implies b\" must not contain {implies, " +
313                         "impliedBy, equivalent):\n" + leSerializer.serialize(expr));
314             }
315             else {
316                 expr.getLeftOperand().accept(this);
317                 expr.getRightOperand().accept(this);
318             }
319         }
320         else {
321             expr.getLeftOperand().accept(this);
322             expr.getRightOperand().accept(this);
323         }
324     }
325 
326     /**
327      * Checks if a LogicProgrammingRule is valid to wsml-rule.
328      * 
329      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitLogicProgrammingRule(org.omwg.logicalexpression.LogicProgrammingRule)
330      */
331     public void visitLogicProgrammingRule(LogicProgrammingRule expr) {
332         body = false;
333         expr.getLeftOperand().accept(this);
334         body = true;
335         expr.getRightOperand().accept(this);
336     }
337 
338     /**
339      * Checks if a UniversalQuantification is valid to wsml-rule.
340      * 
341      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitUniversalQuantification(org.omwg.logicalexpression.UniversalQuantification)
342      */
343     public void visitUniversalQuantification(UniversalQuantification expr) {
344         if (!body) {
345             addError(expr, ValidationError.AX_HEAD_ERR + ": Must not " +
346                     "contain an UniversalQuantification:\n" + 
347                     leSerializer.serialize(expr));
348         }
349         else {
350             expr.getOperand().accept(this);
351         }
352         
353     }
354     
355     /**
356      * Checks if an ExistentialQuantification is valid to wsml-rule.
357      * 
358      * @see org.deri.wsmo4j.validator.WsmlFullExpressionValidator#visitExistentialQuantification(org.omwg.logicalexpression.ExistentialQuantification)
359      */
360     public void visitExistentialQuantification(ExistentialQuantification expr) {
361         if (!body) {
362             addError(expr, ValidationError.AX_HEAD_ERR + ": Must not " +
363                     "contain an ExistentialQuantification:\n" + 
364                     leSerializer.serialize(expr));
365         }
366         else {
367             expr.getOperand().accept(this);
368         }
369         
370     }
371 
372     /*
373      * check if Equivalences, Implications and InverseImplications don't contain
374      * themselves other Equivalences, Implications or InverseImplications
375      */
376     private boolean checkHeads(LogicalExpression expr) {
377         boolean flag = false;
378         if (expr instanceof Binary) {
379             LogicalExpression lLeft = ((Binary) expr).getLeftOperand();
380             LogicalExpression lRight = ((Binary) expr).getRightOperand();
381             if (lLeft instanceof Equivalence || lLeft instanceof Implication 
382                     || lLeft instanceof InverseImplication) {
383                 flag = true;
384             }
385             else {
386                 checkHeads(lLeft);
387             }
388             if (lRight instanceof Equivalence || lRight instanceof Implication 
389                     || lRight instanceof InverseImplication) {
390                 flag = true;
391             }
392             else {
393                 checkHeads(lRight);
394             }
395         }
396         else if (expr instanceof Unary) {
397             LogicalExpression l = ((Unary) expr).getOperand();
398             if (l instanceof Equivalence || l instanceof Implication 
399                     || l instanceof InverseImplication) {
400                 flag = true;
401             }
402             else {
403                 checkHeads(l);
404             }
405         }     
406         return flag;
407     }
408     
409     private void addError(LogicalExpression logexp, String msg) {
410         LogicalExpressionErrorImpl le = new LogicalExpressionErrorImpl(
411                 axiom, logexp, msg, WSML.WSML_RULE);
412         if (!errors.contains(le)) {
413             errors.add(le);
414         }
415     }
416 }