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  
17  package org.deri.wsmo4j.validator;
18  
19  
20  import java.util.*;
21  
22  import org.deri.wsmo4j.io.serializer.wsml.*;
23  import org.deri.wsmo4j.logicalexpression.*;
24  import org.omwg.logicalexpression.*;
25  import org.omwg.ontology.*;
26  import org.wsmo.common.*;
27  import org.wsmo.common.exception.*;
28  import org.wsmo.factory.LogicalExpressionFactory;
29  import org.wsmo.service.Capability;
30  import org.wsmo.service.Goal;
31  import org.wsmo.service.WebService;
32  import org.wsmo.validator.*;
33  
34  
35  /**
36   * Checks an ontology for wsml-full validity.
37   *
38   * <pre>
39   *    Created on Jul 28, 2005
40   *    Committed by $Author: morcen $
41   *    $Source$,
42   * </pre>
43   *
44   * @author Holger Lausen
45   * @author nathalie.steinmetz@deri.org
46   * @version $Revision: 1946 $ $Date: 2007-04-02 15:13:28 +0300 (Mon, 02 Apr 2007) $
47   */
48  public class WsmlFullValidator
49          implements Validator {
50      
51      private Ontology ontology = null;
52     
53      private AnonIdCollectHelper helper = null;
54      
55      protected ConstantTransformer constants = ConstantTransformer.getInstance();
56      
57      protected List <ValidationError> errors = null;
58      
59      protected List <ValidationWarning> warnings = null;
60      
61      protected LogExprSerializerWSML leSerializer = null;
62      
63      protected LogicalExpressionFactory leFactory = null;
64      
65      public WsmlFullValidator(LogicalExpressionFactory leFactory) {
66          this.leFactory = leFactory;
67      }
68      
69      /**
70       * Checks if an axiom is valid to wsml-full.
71       * 
72       * @param axiom
73       */
74      protected void visitAxiom(Axiom axiom) {
75          WsmlFullExpressionValidator exprVal = new WsmlFullExpressionValidator(axiom, errors);
76          Iterator axioms = axiom.listDefinitions().iterator();
77          while (axioms.hasNext()) {
78              ((LogicalExpression)axioms.next()).accept(exprVal);
79          }
80      }
81  
82      /**
83       * Checks if a concept is valid to wsml-full.
84       * 
85       * @param concept
86       */
87      protected void visitConcept(Concept concept) {
88          // concept ID should always be OK
89          // superConcept should also be OK
90          // attributes can be mal formed      
91          Iterator i = concept.listAttributes().iterator();
92          while (i.hasNext()) {
93              Attribute a = (Attribute)i.next();
94              if (a.listTypes().size() == 0) {
95                  if (a.getIdentifier() instanceof IRI) {
96                      if (concept.getIdentifier() instanceof IRI) {
97                          addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
98                                  "Attributes must have a range specified ("
99                                   + ((IRI) a.getIdentifier()).getLocalName() + " at Concept "
100                                  + ((IRI) concept.getIdentifier()).getLocalName() + ")"); 
101                     }
102                     else {
103                         addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
104                                 "Attributes must have a range specified ("
105                                  + ((IRI) a.getIdentifier()).getLocalName() + " at Concept "
106                                  + concept.getIdentifier().toString() + ")"); 
107                     }
108                 }
109                 else {
110                     if (concept.getIdentifier() instanceof IRI) {
111                         addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
112                                 "Attributes must have a range specified ("
113                                  + a.getIdentifier().toString() + " at Concept "
114                                  + ((IRI) concept.getIdentifier()).getLocalName() + ")"); 
115                     }
116                     else {
117                         addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
118                                 "Attributes must have a range specified ("
119                                  + a.getIdentifier().toString() + " at Concept "
120                                  + concept.getIdentifier().toString() + ")");   
121                     }
122                 }
123             }
124             if (a.isReflexive()) {
125             	Iterator it = a.listTypes().iterator();
126             	while (it.hasNext()) {
127             		if (it.next() instanceof WsmlDataType) {
128             			addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
129                                 "Attribute features are not allowed on attributes " +
130                                 "with a data type in its range ("
131                                  + a.getIdentifier().toString() + " at Concept "
132                                  + concept.getIdentifier().toString() + ")");  
133             		}
134             	}
135             }
136             if (a.isSymmetric()) {
137             	Iterator it = a.listTypes().iterator();
138             	while (it.hasNext()) {
139             		if (it.next() instanceof WsmlDataType) {
140             			addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
141                                 "Attribute features are not allowed on attributes " +
142                                 "with a data type in its range ("
143                                  + a.getIdentifier().toString() + " at Concept "
144                                  + concept.getIdentifier().toString() + ")");  
145             		}
146             	} 
147             }
148             if (a.isTransitive()) {
149             	Iterator it = a.listTypes().iterator();
150             	while (it.hasNext()) {
151             		if (it.next() instanceof WsmlDataType) {
152             			addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
153                                 "Attribute features are not allowed on attributes " +
154                                 "with a data type in its range ("
155                                  + a.getIdentifier().toString() + " at Concept "
156                                  + concept.getIdentifier().toString() + ")");  
157             		}
158             	} 
159             }
160             if (a.getInverseOf() != null) {
161             	Iterator it = a.listTypes().iterator();
162             	while (it.hasNext()) {
163             		if (it.next() instanceof WsmlDataType) {
164             			addError(concept, a, ValidationError.ATTR_ERR + ":\n" +
165                                 "Attribute features are not allowed on attributes " +
166                                 "with a data type in its range ("
167                                  + a.getIdentifier().toString() + " at Concept "
168                                  + concept.getIdentifier().toString() + ")");  
169             		}
170             	}
171             }
172         }
173     }
174 
175     /**
176      * Checks if an instance is valid to wsml-full.
177      * 
178      * @param instance
179      */
180     protected void visitInstance(Instance instance) {
181         // API does not allow for inconsistent instances
182     }
183 
184     /**
185      * Checks if a relation is valid to wsml-full.
186      * 
187      * @param relation
188      */
189     protected void visitRelation(Relation relation) {
190         int parameterCount = relation.listParameters().size(); 
191         if (parameterCount == 0) {
192             if (relation.getIdentifier() instanceof IRI) {
193                 addError(relation, ValidationError.REL_ARITY_ERR + ":\n" +
194                         "Relation must have arity specified ("
195                         + ((IRI) relation.getIdentifier()).getLocalName() + ")");
196             }
197             else {
198                 addError(relation, ValidationError.REL_ARITY_ERR + ":\n" +
199                         "Relation must have arity specified ("
200                          + relation.getIdentifier().toString() + ")");
201             }
202             return;
203         }
204         Iterator i = relation.listParameters().iterator();
205         int specifiedParameters=0;
206         while (i.hasNext()) {
207             Parameter p = (Parameter)i.next();
208             if (p.listTypes().size() == 0) {
209                 specifiedParameters++;
210             }
211         } 
212         if (parameterCount != specifiedParameters && specifiedParameters != 0) {
213             if (relation.getIdentifier() instanceof IRI) {
214                 addError(relation, ValidationError.REL_ERR + ":\n" +
215                         "Either all Parameter or none must be specified\n" +
216                         "(in relation " + ((IRI) relation.getIdentifier()).getLocalName() + ")");
217             }
218             else {
219                 addError(relation, ValidationError.REL_ERR + ":\n" +
220                         "Either all Parameter or none must be specified\n" +
221                         "(in relation " + relation.getIdentifier().toString() + ")");
222             }
223         }
224 
225     }
226 
227     /*
228      * These exceptions shouldn't be thrown at all
229      */
230     /**
231      * Checks if a relation instance is valid to wsml-full.
232      * 
233      * @param relationInstance
234      * @throws SynchronisationException
235      * @throws InvalidModelException
236      */
237     protected void visitRelationInstance(RelationInstance relationInstance)
238             throws SynchronisationException, InvalidModelException {
239         if (relationInstance.getRelation() == null) {
240             if (relationInstance.getIdentifier() instanceof IRI) {
241                 addError(relationInstance, ValidationError.REL_INST_ERR + ":\n" +
242                          "RelationInstances must be associated to an Relation "
243                          + "(" + ((IRI) relationInstance.getIdentifier()).getLocalName() + ")");
244             }
245             else {
246                 addError(relationInstance, ValidationError.REL_INST_ERR + ":\n" +
247                         "RelationInstances must be associated to an Relation "
248                         + "(" + relationInstance.getIdentifier().toString() + ")");
249             }
250         }
251     }
252 
253     /**
254      * 
255      * @return error list
256      */
257     public Collection getErrors() {
258         return errors;
259     }
260     
261     /**
262      * Given an ontology as TopEntity, the method checks if the different 
263      * ontology elements are valid and fills the error- and warningMessages lists 
264      * with errors and warnings if not.
265      * Given a WebService or a Goal as TopEntity, the method checks the capability 
266      * assumptions, effects, postcondition and precondition axioms for validity and 
267      * fills the error- and warningMessages if the axioms are not valid.
268      * 
269      * @param te TopEntity to be checked
270      * @param errorMessages list that will be filled with error messages of found variant violations
271      * @return true if valid (no errors), false if errors occured
272      * @see org.wsmo.validator.Validator#isValid(org.wsmo.common.TopEntity, java.util.List, 
273      *      java.util.List)
274      */
275     public boolean isValid(TopEntity te, List <ValidationError> errorMessages, List <ValidationWarning> warningMessages) {
276         leSerializer = new LogExprSerializerWSML(te);
277         errors = errorMessages;
278         warnings = warningMessages;
279         if (te instanceof Ontology) {
280             ontology = (Ontology)te;
281             // check for an erronous use of unnumbered anonymous identifiers
282             helper = new AnonIdCollectHelper(errors);
283             helper.checkAnonIds(ontology);
284             Iterator i = ontology.listConcepts().iterator();
285             while (i.hasNext()) {
286                 visitConcept((Concept)i.next());
287             }
288             i = ontology.listInstances().iterator();
289             while (i.hasNext()) {
290                 visitInstance((Instance)i.next());
291             }
292 
293             i = ontology.listRelations().iterator();
294             while (i.hasNext()) {
295                 visitRelation((Relation)i.next());
296             }
297 
298             i = ontology.listRelationInstances().iterator();
299             while (i.hasNext()) {
300                 try {
301                     visitRelationInstance((RelationInstance)i.next());
302                 }
303                 catch (InvalidModelException ime) {
304                     new RuntimeException(ime);
305                 }
306             }
307 
308             i = ontology.listAxioms().iterator();
309             while (i.hasNext()) {
310                 visitAxiom((Axiom)i.next());
311             }
312         }
313         else if (te instanceof WebService || te instanceof Goal) {
314         	Capability capa = null;
315         	if (te instanceof WebService) {
316         		WebService webServ = (WebService) te;
317         		capa = webServ.getCapability();
318         	}
319         	else if (te instanceof Goal) {
320         		Goal goal = (Goal) te;
321         		capa = goal.getCapability();
322         	}
323         	if (capa != null) {
324 	        	Iterator it = capa.listAssumptions().iterator();
325 	        	while (it.hasNext()) {
326 	        		visitAxiom((Axiom) it.next());
327 	        	}
328 	        	
329 	        	it = capa.listEffects().iterator();
330 	        	while (it.hasNext()) {
331 	        		visitAxiom((Axiom) it.next());
332 	        	}
333 	        	
334 	        	it = capa.listPreConditions().iterator();
335 	        	while (it.hasNext()) {
336 	        		visitAxiom((Axiom) it.next());
337 	        	}
338 	        	
339 	        	it = capa.listPostConditions().iterator();
340 	        	while (it.hasNext()) {
341 	        		visitAxiom((Axiom) it.next());
342 	        	}
343         	}
344         	addWarning(te, "The validation of Web Services and Goals is not " +
345         			"yet complete. Currently the logical expressions in " +
346         			"assumptions, effects, pre- and postconditions are " +
347         			"validated against the WSML variant specified in the " +
348         			"file.", null);
349         }
350         else {
351             throw new UnsupportedOperationException(
352                     "Only implemented for ontologies, web services and goals at present");
353         }
354         return (errors.isEmpty());
355     }
356     
357     public boolean isValid(LogicalExpression logExpr, List <ValidationError> errorMessages, List <ValidationWarning> warningMessages) {
358     	leSerializer = new LogExprSerializerWSML(null);
359     	errors = errorMessages;
360         warnings = warningMessages;
361     	WsmlFullExpressionValidator exprVal = new WsmlFullExpressionValidator(null, errors);
362         logExpr.accept(exprVal);
363     	return (errors.isEmpty());
364     }
365     
366     /*
367      * Adds a new ValidationWarning to the error list
368      */
369     protected void addWarning(Entity ent, String msg, String quickFix) {
370         ValidationWarningImpl vw = new ValidationWarningImpl(ent, msg, quickFix);
371         if (!warnings.contains(vw)) {
372             warnings.add(vw);
373         }
374     }
375     
376     /*
377      * Adds a new ValidationError to the error list
378      */
379     protected void addError(Entity ent, String msg) {
380         ValidationErrorImpl ve = new ValidationErrorImpl(ent, msg, WSML.WSML_FULL);
381         if (!errors.contains(ve)) {
382             errors.add(ve);
383         }
384     }
385     
386     /*
387      * Adds a new AttributeError to the error list
388      */
389     protected void addError(Entity ent, Attribute att, String msg) {
390         AttributeErrorImpl ae = new AttributeErrorImpl(ent, att, msg, WSML.WSML_FULL);
391         if (!errors.contains(ae)) {
392             errors.add(ae);
393         }
394     }
395     
396 }