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.rdf;
17  
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.Map;
21  import java.util.Set;
22  import java.util.Map.Entry;
23  
24  import org.omwg.logicalexpression.LogicalExpression;
25  import org.omwg.ontology.Attribute;
26  import org.omwg.ontology.Axiom;
27  import org.omwg.ontology.Concept;
28  import org.omwg.ontology.DataValue;
29  import org.omwg.ontology.Instance;
30  import org.omwg.ontology.Ontology;
31  import org.omwg.ontology.Parameter;
32  import org.omwg.ontology.Relation;
33  import org.omwg.ontology.RelationInstance;
34  import org.omwg.ontology.Type;
35  import org.omwg.ontology.WsmlDataType;
36  import org.openrdf.model.BNode;
37  import org.openrdf.model.Graph;
38  import org.openrdf.model.GraphException;
39  import org.openrdf.model.Resource;
40  import org.openrdf.model.Statement;
41  import org.openrdf.model.URI;
42  import org.openrdf.model.Value;
43  import org.openrdf.model.impl.GraphImpl;
44  import org.openrdf.model.impl.URIImpl;
45  import org.openrdf.sesame.sail.StatementIterator;
46  import org.openrdf.vocabulary.RDF;
47  import org.openrdf.vocabulary.RDFS;
48  import org.openrdf.vocabulary.XmlSchema;
49  import org.wsmo.common.Entity;
50  import org.wsmo.common.IRI;
51  import org.wsmo.common.Namespace;
52  import org.wsmo.common.WSML;
53  import org.wsmo.common.exception.InvalidModelException;
54  import org.wsmo.common.exception.SynchronisationException;
55  import org.wsmo.factory.DataFactory;
56  import org.wsmo.factory.LogicalExpressionFactory;
57  import org.wsmo.factory.WsmoFactory;
58  import org.wsmo.wsml.ParserException;
59  
60  /**
61  * Transformation from native rdf to wsml.
62  *
63  * <pre>
64  *  Created on May 02, 2006
65  *  Committed by $Author: nathaliest $
66  *  $Source$
67  * </pre>
68  * 
69  * @see RDFParserImpl
70  * @author nathalie.steinmetz@deri.org
71  * @version $Revision: 2644 $ $Date: 2008-08-08 02:20:48 +0300 (Fri, 08 Aug 2008) $
72  */
73  public class RDFExprParser {
74      
75      private String DC = "http://purl.org/dc/elements/1.1#";
76      private String OWL = "http://www.w3.org/2002/07/owl#";
77      private String LABEL = "title";
78      private String COMMENT = "description";
79      private String RELATION = "relation";
80      
81      public final static String WSML_AXIOM = "http://www.wsmo.org/wsml/wsml-syntax#axiom";
82      public final static String CONSTRAINING_ATTR = "constraining attribute";
83      public final static String TRANSITIVE_ATTR = "transitive attribute";
84      public final static String REFLEXIVE_ATTR = "reflexive attribute";
85      public final static String SYMMETRIC_ATTR = "symmetric attribute";
86      public final static String CONSTRAINING_REL_1 = "constraining relation parameter 1";
87      public final static String CONSTRAINING_REL_2 = "constraining relation parameter 2";
88      public final static String WSML_INVERSE_ATTR = "http://www.wsmo.org/wsml/wsml-syntax#inverseAttribute";
89      public final static String WSML_ONTOLOGY_ID = "http://www.wsmo.org/wsml/wsml-syntax#ontologyID";
90      
91      private Set <String> idConcepts	= null;
92      private Set <String> idInstances = null;
93      private Set <String> idRelations = null;
94      
95      private WsmoFactory factory                 = null;
96      private LogicalExpressionFactory leFactory  = null;
97      private DataFactory dataFactory             = null; 
98      private RDFParseErrorListener errorListener = null;
99      
100     private String properties   = null;
101     private String labels = null;
102     private Ontology ontology   = null;
103     private Graph graph2        = null;
104     private Namespace defaultNS = null;
105     private boolean noDCNFP = false;
106     
107     public RDFExprParser(WsmoFactory factory, LogicalExpressionFactory leFactory, 
108             DataFactory dataFactory, String properties, String labels, RDFParseErrorListener errorListener) {
109         this.factory = factory;
110         this.leFactory = leFactory;
111         this.dataFactory = dataFactory;
112         this.properties = properties;
113         this.labels = labels;
114         this.errorListener = errorListener;
115         this.graph2 = new GraphImpl();
116         this.defaultNS = null;
117         this.idConcepts = new HashSet <String> ();
118         this.idInstances = new HashSet <String> ();
119         this.idRelations = new HashSet <String> ();
120     }
121     
122     /**
123      * This method takes an rdf graph as input and checks through all 
124      * the statements, to transform the rdf input into wsmo objects.
125      * 
126      * @param graph RDF Graph, containing all the parsed statements.
127      * @param namespaces HashMap containing all the namespaces of the RDF file.
128      * @throws GraphException
129      * @throws SynchronisationException
130      * @throws InvalidModelException
131      * @throws ParserException 
132      */
133     public void rdf2Wsml(Graph graph, Map namespaces) 
134             throws GraphException, SynchronisationException, InvalidModelException, ParserException {
135         
136         // create wsmo ontology and set namespaces
137         createOntology(graph, namespaces);
138         setNamespaces(namespaces);
139         
140         // check through all statements
141         StatementIterator iterator = graph.getStatements();
142         while(iterator.hasNext()) {
143             Statement statement = iterator.next();
144             // if the statement describes a class, a new wsml concept is created
145             if ((statement.getPredicate().getURI().equals(RDF.TYPE)) &&
146                     (statement.getObject().toString().equals(RDFS.CLASS))){
147                 visitClass(statement);
148                 graph2.add(statement);
149             }
150             // if the statement describes a property, either an attribute is added 
151             // to a concept, or a relation is created
152             else if ((statement.getPredicate().getURI().equals(RDF.TYPE)) &&
153                     (statement.getObject().toString().equals(RDF.PROPERTY))){
154                 if (properties.equals(RDFParserImpl.RDF_PROP_AS_ATTR)) {
155                     visitPropertyAsAttribute(statement); 
156                     graph2.add(statement);
157                 }    
158                 else if (properties.equals(RDFParserImpl.RDF_PROP_AS_REL)) {
159                     visitPropertyAsRelation(statement);
160                     graph2.add(statement);
161                 }
162             }
163             // if the statement describes an instance, an instance is created
164             else if (statement.getPredicate().getURI().equals(RDF.TYPE)) {
165                 visitInstance(statement);
166                 graph2.add(statement);
167             }
168             // if the statement describes a <wsml:axiom>, we build an axiom using 
169             // the value of the statement
170             else if (statement.getPredicate().getURI().equals(
171             		WSML_AXIOM)) {
172             	visitAxiom(statement);
173             	graph2.add(statement);
174             }
175         }
176         // a warning is put into the list of warnings for all statements that 
177         // have not been transformed to WSML 
178         graph.remove(graph2);
179         iterator = graph.getStatements();
180         while(iterator.hasNext()) {
181             Statement stat = iterator.next();
182             addWarning("Statement/-s containing the predicate \"" + 
183                     stat.getPredicate().getLocalName() +
184                     "\" has/have not been transformed to WSML!", stat);
185         }
186         setWsmlVariant();
187     }
188     
189     /*
190      * This method creates a wsml concept from the rdf class.
191      * If a class is a subClass of another, the corresponding concept adds 
192      * the super class as superConcept.
193      * If a class has associated comments or labels, those are added as non 
194      * functional properties to the corresponding concept.
195      */
196     private void visitClass(Statement statement) 
197             throws GraphException, SynchronisationException, InvalidModelException {
198         // create concept
199         Concept concept = createConcept(statement.getSubject().toString(), statement);
200         if (concept != null) {
201             // check for nfps and superConcepts
202             StatementIterator it = statement.getSubject().getSubjectStatements();
203             while (it != null && it.hasNext()) {             
204                 Statement stat = it.next();            
205                 checkForNFP(concept,stat);
206                 // add any superConcept to the list of superConcepts of this concept
207                 if (stat.getPredicate().getURI().equals(RDFS.SUBCLASSOF)) {
208                     // create superConcept and add superConcept as superConcept to concept
209                     Concept superConcept = createConcept(stat.getObject().toString(), stat);
210                     if (superConcept != null) {
211                         addSuperConcept(concept, superConcept, stat);
212                     }
213                     graph2.add(stat);
214                 }
215             }
216         }
217     }
218     
219     private void checkForNFP(Entity entity, Statement stat) throws InvalidModelException {
220         // add any label, a human readable name of the resource, to the nfps
221         if (stat.getPredicate().getURI().equals(RDFS.LABEL)) {
222         	// if the entity is an axiom and we have an rdfs#label, we add the label 
223             // as rdfs#label to the wsml ontology, instead of dc#label. This is done 
224             // for roundtripping reasons with the RDF Serializer. That one looks for 
225             // rdfs#labels related to the <wsml:axiom> statements.
226         	if (entity instanceof Axiom && noDCNFP) {
227         		addNFP(entity, RDFS.LABEL, stat.getObject().toString());
228                 graph2.add(stat);
229         	}
230         	else if (labels.equals(RDFParserImpl.DC_TITLE)){
231         		addNFP(entity, DC + LABEL, stat.getObject().toString());
232         		graph2.add(stat);
233         	}
234         	else {
235         		addNFP(entity, RDFS.LABEL, stat.getObject().toString());
236         		graph2.add(stat);
237         	}
238         }
239         // add any comment, a human readable description of a resource, to the nfps
240         else if (stat.getPredicate().getURI().equals(RDFS.COMMENT)) {
241             if (entity instanceof Attribute) {
242             	if (stat.getObject().toString().equals(CONSTRAINING_ATTR)) {
243             		((Attribute) entity).setConstraining(true);
244             		graph2.add(stat);
245             	}
246             	if (stat.getObject().toString().equals(TRANSITIVE_ATTR)) {
247             		((Attribute) entity).setTransitive(true);
248             		graph2.add(stat);
249             	}
250             	if (stat.getObject().toString().equals(REFLEXIVE_ATTR)) {
251             		((Attribute) entity).setReflexive(true);
252             		graph2.add(stat);
253             	}
254             	if (stat.getObject().toString().equals(SYMMETRIC_ATTR)) {
255             		((Attribute) entity).setSymmetric(true);
256             		graph2.add(stat);
257             	}
258             }
259             else {  	
260             	addNFP(entity, DC + COMMENT, stat.getObject().toString());
261             	graph2.add(stat);
262             }
263         }
264         // map any rdfs:seeAlso to dc#relation
265         else if (stat.getPredicate().getURI().equals(RDFS.SEEALSO)) {
266             addNFP(entity, DC + RELATION, stat.getObject().toString());
267             graph2.add(stat);
268         }
269         // map any rdfs:isDefinedBy to dc#relation
270         else if (stat.getPredicate().getURI().equals(RDFS.ISDEFINEDBY)) {
271             addNFP(entity, DC + RELATION, stat.getObject().toString());
272             graph2.add(stat);
273 		}
274     }
275     
276     /*
277      * This method creates concept attributes. If the property has 
278      * a domain, this domain is used as concept, whom the attribute 
279      * belongs to. Otherwise rdfs:Class is used as domain.
280      * The property's range specifies the type of the attribute. If 
281      * no range is specified, rdfs:Class is used as range.
282      * If a property has a subProperty, an axiom, containing an 
283      * implication, is created.
284      * If a property has associated comments and labels, those are 
285      * added to the non functional properties of the corresponding 
286      * concept.
287      */
288     private void visitPropertyAsAttribute(Statement statement) 
289             throws GraphException, SynchronisationException, InvalidModelException, ParserException {
290         Concept concept = null;
291         Attribute attribute = null;
292         
293         // check for property domain
294         StatementIterator it = statement.getSubject().getSubjectStatements();
295         while (it != null && it.hasNext()) {
296             Statement stat = it.next();
297             // the domain specifies the concept, whom the attribute belongs to.
298             if (stat.getPredicate().getURI().equals(RDFS.DOMAIN)) {
299                 concept = createConcept(stat.getObject().toString(), stat);
300                 graph2.add(stat);
301             }         
302         }
303         // if no domain was specified, rdfs:Class is used instead.
304         if (concept == null) {
305             concept = createConcept(RDFS.CLASS, null);
306         }
307         
308         // create an attribute
309         attribute = createAttribute(concept, statement.getSubject().toString(), statement);
310         
311         // check for labels, comments (and whit that: attribute features) and inverse attributes
312         it = statement.getSubject().getSubjectStatements();
313         while (it != null && it.hasNext()) {
314             Statement stat = it.next();
315             checkForNFP(attribute,stat);
316             if (stat.getPredicate().getURI().equals(WSML_INVERSE_ATTR)) {
317             	attribute.setInverseOf(factory.createIRI(
318             			stat.getObject().toString()));
319             	graph2.add(stat);
320             }
321         }  
322         
323         // check for property range
324         it = statement.getSubject().getSubjectStatements();
325         while (it != null && it.hasNext()) {
326             Statement stat = it.next();
327             if (stat.getPredicate().getURI().equals(RDFS.RANGE)) {
328             	boolean range = false;
329                 IRI iri = null;
330                 // check for anonymous ids
331                 try {
332                     iri = factory.createIRI(stat.getObject().toString());
333                 } catch (IllegalArgumentException e) {
334                     addWarning("Anonymous identifiers problem - One or more " +
335                             "anonymous concepts have not been added to " +
336                             "the WSMO object model!", statement);
337                     return;
338                 }
339                 iri = factory.createIRI(stat.getObject().toString());
340                 if (attribute != null) {
341                 	if (ontology.listConcepts().size() > 0) {
342 	                    Iterator iter = ontology.listConcepts().iterator();
343 	                    while (iter.hasNext()) {
344 	                        Concept conc = (Concept) iter.next();
345 	                        if (conc.getIdentifier().equals(iri)) {
346 	                        	range = true;
347 	                            addAttributeType(attribute, conc);
348 	                            graph2.add(stat);
349 	                        }
350 	                        else if (iri.toString().equals(RDFS.CLASS)) {
351 	                            conc = createConcept(iri.toString(), null);
352 	                            range = true;
353 	                            addAttributeType(attribute, conc);
354 	                            graph2.add(stat);
355 	                        }
356 	                    }
357                 	}
358                 	if (!range) {
359                 		if (iri.toString().equals(RDFS.LITERAL)) {
360                             Type t = dataFactory.createWsmlDataType(WsmlDataType.WSML_STRING);
361                             addWarning("A property range of type rdfs:Literal is transformed " +
362                                     "to WSML_STRING", stat);
363                             addAttributeType(attribute, t);   
364                             graph2.add(stat);
365                         }
366                         else if (iri.getNamespace().equals(XmlSchema.NAMESPACE)) {
367                             Type t = createWsmlDataType(iri);
368                             if (t != null) {
369                                 addAttributeType(attribute, t);        
370                                 graph2.add(stat);
371                             }
372                         }
373                         else {
374                         	Concept conc = createConcept(iri.toString(), null);
375                             addAttributeType(attribute, conc);
376                             graph2.add(stat);
377                         }
378                     }
379                 }         
380             }
381         }
382         if (attribute.listTypes().size() == 0 && attribute != null) {
383             Concept tmp = createConcept(RDFS.CLASS, null);
384             addAttributeType(attribute, tmp);
385         }
386         
387         // check for subProperties
388         it = statement.getSubject().getSubjectStatements(); 
389         while(it != null && it.hasNext()) {
390             Statement stat = it.next();
391             if (stat.getPredicate().getURI().equals(RDFS.SUBPROPERTYOF)) {
392                 Attribute b = null;
393                 String superProperty = stat.getObject().toString();
394                 if (ontology.listConcepts().size() > 0) {
395                     Iterator iter = ontology.listConcepts().iterator();
396                     while (iter.hasNext()) {
397                         Concept conc = (Concept) iter.next();
398                         if (conc.listAttributes().size() > 0) {
399                             Iterator iter2 = conc.listAttributes().iterator();
400                             while (iter2.hasNext()) {
401                                 Attribute attr = (Attribute) iter2.next();
402                                 if (attr.getIdentifier().toString().equals(superProperty)) {
403                                     b = attr;
404                                 }
405                             }
406                         }
407                     }
408                 }
409                 if (b == null) {
410                     Concept conc = createConcept(RDFS.CLASS, null);
411                     b = createAttribute(conc, superProperty, null);
412                 }
413                 // create axiom, defined by an implication and add nfps to axiom and concept
414                 Axiom axiom = createAxiom(attribute, b);
415                 addNFP(axiom, DC + RELATION, ((IRI) concept.getIdentifier()).getLocalName());
416                 addNFP(concept, DC + RELATION, ((IRI) axiom.getIdentifier()).getLocalName());
417             
418                 graph2.add(stat);
419             }
420         }
421     }
422     
423     /*
424      * This method creates relations. The property's domain and range 
425      * specify the types of the relation. If no domain or range is 
426      * specified, rdfs:Class is used instead.
427      * If a property is a subProperty of another, a subRelation is 
428      * created.
429      * If a property has associated comments and labels, those are 
430      * added as non functional properties to the corresponding relation.
431      */
432     private void visitPropertyAsRelation(Statement statement) 
433             throws GraphException, SynchronisationException, InvalidModelException {
434         Concept concept = null;
435         Relation relation = null;
436         
437         // create a relation
438         relation = createRelation(statement.getSubject().toString(), statement);
439         
440         if (relation != null) {
441             // check for labels or comments
442             StatementIterator it = statement.getSubject().getSubjectStatements();
443             while (it != null && it.hasNext()) {
444                 Statement stat = it.next();
445                 checkForNFP(relation,stat);
446             }
447             
448             // check for property domain
449             it = statement.getSubject().getSubjectStatements();
450             while (it != null && it.hasNext()) {
451                 Statement stat = it.next();
452                 // the domain specifies one type of the relation.
453                 if (stat.getPredicate().getURI().equals(RDFS.DOMAIN)) {
454                     concept = createConcept(stat.getObject().toString(), stat);
455                     graph2.add(stat);
456                 }         
457             }
458             // if no domain was specified, rdfs:Class is used instead.
459             if (concept == null) {
460                 concept = createConcept(RDFS.CLASS, null);
461             }
462             
463             // check for property range
464             it = statement.getSubject().getSubjectStatements();
465             while (it != null && it.hasNext()) {
466                 Statement stat = it.next();
467                 if (stat.getPredicate().getURI().equals(RDFS.RANGE)) {
468                 	boolean range = false;
469                     IRI iri = factory.createIRI(stat.getObject().toString());
470                     String localName = iri.getLocalName();
471                     if (ontology.listConcepts().size() > 0) {
472                         Iterator iter = ontology.listConcepts().iterator();
473                         while (iter.hasNext()) {
474                             Concept conc = (Concept) iter.next();
475                             if (conc.getIdentifier().equals(iri)) {
476                             	range = true;
477                                 addRelationType(relation, concept, conc);
478                                 graph2.add(stat);
479                             }
480                             else if (iri.toString().equals(RDFS.CLASS)) {
481                             	range = true;
482                                 conc = createConcept(iri.toString(), stat);
483                                 addRelationType(relation, concept, conc);
484                                 graph2.add(stat);
485                             }
486                         }
487                     }
488                     if (!range) {
489                     	if (localName.endsWith("Literal")) {
490                     		Type t = dataFactory.createWsmlDataType(WsmlDataType.WSML_STRING);
491                     		addWarning("A property range of type rdfs:Literal is transformed " +
492                     				"to WSML_STRING", stat);
493                     		addRelationType(relation, concept, t);
494                     		graph2.add(stat);
495                     	}
496                     	else if (iri.getNamespace().equals(XmlSchema.NAMESPACE)) {
497                     		Type t = createWsmlDataType(iri);
498                     		if (t != null) {
499                     			addRelationType(relation, concept, t);   
500                     			graph2.add(stat);
501                     		}
502                     	}
503                     	else {
504                     		Concept conc = createConcept(iri.toString(), stat);
505                             addRelationType(relation, concept, conc);
506                             graph2.add(stat);
507                     	}
508                     }         
509                 }
510             }
511             if (relation.listParameters().get(0).listTypes().size() == 0) {
512                 Concept tmp = createConcept(RDFS.CLASS, null);
513                 addRelationType(relation, concept, tmp);  
514             }
515             // check if a property is subProperty of another property and
516             // if a parameter is constraining or not
517             it = statement.getSubject().getSubjectStatements(); 
518             while(it != null && it.hasNext()) {
519                 Statement stat = it.next();
520                 if (stat.getPredicate().getURI().equals(RDFS.SUBPROPERTYOF)) {        
521                     Relation superRelation = createRelation(stat.getObject().toString(), stat);
522                     if (superRelation != null) {
523                         addSuperRelation(relation, superRelation);
524                     }
525                     graph2.add(stat);
526                 }
527                 else if (stat.getPredicate().getURI().equals(RDFS.COMMENT)) {
528                 	if (stat.getObject().toString().equals(CONSTRAINING_REL_1)) {
529                 		relation.listParameters().get(0).setConstraining(true);
530                 		graph2.add(stat);
531                 	}
532                 	if (stat.getObject().toString().equals(CONSTRAINING_REL_2)) {
533                 		relation.listParameters().get(1).setConstraining(true);
534                 		graph2.add(stat);
535                 	}
536                 }
537             }
538         }
539     }
540     
541     /*
542      * This method creates instances. 
543      */
544     private void visitInstance(Statement statement) 
545             throws SynchronisationException, InvalidModelException, GraphException {
546         Concept concept = null;
547         
548         // create an instance
549         Instance instance = createInstance(statement.getSubject().toString(), statement);
550         
551         if (instance != null) {
552             // add an instance to a concept
553             Iterator iter = ontology.listConcepts().iterator();
554             while (iter.hasNext()) {
555                 Concept tmp = (Concept) iter.next();
556                 if (tmp.getIdentifier().toString().equals(statement.getObject().toString())) {
557                     concept = tmp;
558                 }
559             }
560             if (concept == null) {
561                 concept = createConcept(statement.getObject().toString(), statement);
562             }
563             concept.addInstance(instance);
564             
565             // check for labels or comments
566             StatementIterator it = statement.getSubject().getSubjectStatements();
567             while (it != null && it.hasNext()) {
568                 Statement stat = it.next();
569                 checkForNFP(instance,stat);
570                 if (properties.equals(RDFParserImpl.RDF_PROP_AS_ATTR)) {
571                     if (!addAttributeValue(concept, instance, stat) 
572                             && nonRDFSProperty(stat.getPredicate().getURI())) {
573                         Attribute attribute = createAttribute(concept, stat.getPredicate().toString(), stat);
574                         Concept tmp = createConcept(RDFS.CLASS, stat);
575                         addAttributeType(attribute, tmp);
576                         if (stat.getObject() instanceof URI) {
577                             Instance temp = createInstance(stat.getObject().toString(), stat);
578                             instance.addAttributeValue(attribute.getIdentifier(), temp);
579                         } else if (stat.getObject() instanceof BNode) {
580                             String name = "blank:" + stat.getObject().toString();
581                             Instance temp = createInstance(name, stat);
582                             instance.addAttributeValue(attribute.getIdentifier(), temp);
583                         } else {
584                             DataValue dataValue = dataFactory.createWsmlString(stat.getObject().toString());
585                             instance.addAttributeValue(attribute.getIdentifier(), dataValue);
586                         }
587                     }
588                     graph2.add(stat);
589                 } else if (properties.equals(RDFParserImpl.RDF_PROP_AS_REL)) {
590                     if (nonRDFSProperty(stat.getPredicate().getURI())) {
591                         addRelationInstances(concept, instance, stat);
592                         graph2.add(stat);
593                     }
594                 }
595                 
596             }
597         }
598     }
599     
600     /*
601      * This method creates a wsml axiom from the <wsml:axiom> statement.
602      * If the axiom has associated comments or labels, those are added as non 
603      * functional properties to the corresponding concept.
604      */
605     private void visitAxiom(Statement statement) 
606             throws GraphException, SynchronisationException, InvalidModelException, ParserException {
607     	// create axiom
608         Axiom axiom = createAxiom(statement.getSubject().toString(), statement);
609         if (axiom != null) {
610             // check for nfps and add the logical expressions
611             StatementIterator it = statement.getSubject().getSubjectStatements();
612             while (it != null && it.hasNext()) {             
613                 Statement stat = it.next();            
614                 noDCNFP = true;
615                 checkForNFP(axiom,stat);
616                 noDCNFP = false;
617                 // add any logical expression to the list of logical expressions of this axiom
618                 if (stat.getPredicate().getURI().equals(WSML_AXIOM)) {
619                     // logical expression and add it to the axiom
620                     LogicalExpression logExpr = leFactory.createLogicalExpression(statement.getObject().toString(), 
621                     		axiom.getOntology());
622                     axiom.addDefinition(logExpr);
623                     graph2.add(stat);
624                 }
625             }
626         }
627     }
628     
629     /*
630      * This method adds attribute values to instances
631      */
632     private boolean addAttributeValue(Concept concept, Instance instance, Statement statement) 
633             throws SynchronisationException, InvalidModelException {
634         Iterator iter = concept.listAttributes().iterator();
635         while (iter.hasNext()) {
636             Attribute attribute = (Attribute) iter.next();
637             if (statement.getPredicate().toString().equals(attribute.getIdentifier().toString())) {
638                 Instance tmp = getInstance(statement.getObject());
639                 if (tmp == null) {
640                     if (statement.getObject() instanceof URI) {
641                         tmp = createInstance(statement.getObject().toString(), statement);
642                         instance.addAttributeValue(attribute.getIdentifier(), tmp);
643                     } else if (statement.getObject() instanceof BNode) {
644                         String name = "blank:" + statement.getObject().toString();
645                         Instance temp = createInstance(name, statement);
646                         instance.addAttributeValue(attribute.getIdentifier(), temp);
647                     } else {
648                         DataValue dataValue = dataFactory.createWsmlString(statement.getObject().toString());
649                         instance.addAttributeValue(attribute.getIdentifier(), dataValue);
650                     }
651                 }
652                 else {
653                     instance.addAttributeValue(attribute.getIdentifier(), tmp);
654                 }
655                 return true;
656             }
657         }
658         if (concept.listSuperConcepts().size() > 0) {
659             Iterator iter2 = concept.listSuperConcepts().iterator();
660             while (iter2.hasNext()) {
661                 Concept tmp = (Concept) iter2.next();
662                 return addAttributeValue(tmp, instance, statement);
663             }
664         }
665         return false;
666     }
667     
668     /*
669      * This method adds a relation instance to a relation
670      */
671     private void addRelationInstances(Concept concept, Instance instance, Statement statement) 
672             throws SynchronisationException, InvalidModelException {
673         Relation relation = null;
674         RelationInstance relationInstance = null;
675         Iterator it = ontology.listRelations().iterator();
676         while (it.hasNext()) {
677             relation = (Relation) it.next();
678             if (relation.getIdentifier().toString().equals(statement.getPredicate().toString())) {
679                 relationInstance = createRelationInstance(instance, relation, statement);
680             }
681         }
682         if (relationInstance == null) {
683             relation = createRelation(statement.getPredicate().toString(), statement);
684             if (relation != null) {
685                 relationInstance = createRelationInstance(instance, relation, statement);
686             }
687         }
688     }
689     
690     /*
691      * Create an wsmo ontology and set the wsml variant.
692      */
693     private void createOntology(Graph g, Map ns) throws GraphException {
694         String ontID = null;
695         //if it is OWL/RDF there might be an id:
696         Resource r = new URIImpl(OWL+"Ontology");
697         StatementIterator i = g.getStatements(null, null, r);
698         while (i.hasNext()){
699             Statement s = i.next();
700             URI pred = s.getPredicate();
701             if (pred!=null && pred.getURI().equals(RDF.TYPE)){
702                 ontID = s.getSubject().toString();
703                 g.remove(s);
704             }
705         }
706         if (ontID == null){
707         	// we might have saved the id in an rdfs#comment statement, if 
708         	// it was already parsed from wsml before
709         	StatementIterator it = g.getStatements(
710         			null, new URIImpl(WSML_ONTOLOGY_ID), null);
711         	while (it.hasNext()) {
712         		Statement s = it.next();
713                 ontID= s.getObject().toString();
714                 g.remove(s);
715         	}
716         }
717         if (ontID == null) {
718             //an rdf file in general does not have an ID so just creat some
719             ontID = getDefaultNamespace(ns).getIRI() + "GENID" + System.currentTimeMillis();
720         }
721         ontology = factory.createOntology(factory.createIRI(ontID));
722     }
723     
724     /*
725      * This method checks whether metamodelling is used in this ontology. If so, 
726      * the resulting WSML Variant is set to WSML-FLIGHT, and if not, the resulting 
727      * WSML Variant is set to WSML-CORE.
728      */
729     private void setWsmlVariant() {
730     	Iterator it = idConcepts.iterator();
731     	while (it.hasNext()) {
732     		String id = (String) it.next();
733     		if (idInstances.contains(id) || idRelations.contains(id)) {
734     			ontology.setWsmlVariant(org.wsmo.common.WSML.WSML_FLIGHT);
735             }
736     	}
737     	it = idInstances.iterator();
738     	while (it.hasNext()) {
739     		String id = (String) it.next();
740     		if (idConcepts.contains(id) || idRelations.contains(id)) {
741     			ontology.setWsmlVariant(org.wsmo.common.WSML.WSML_FLIGHT);
742     		}
743     	}
744     	it = idRelations.iterator();
745     	while (it.hasNext()) {
746     		String id = (String) it.next();
747     		if (idConcepts.contains(id) || idInstances.contains(id)) {
748     			ontology.setWsmlVariant(org.wsmo.common.WSML.WSML_FLIGHT);
749     		}
750     	}
751     	if (ontology.getWsmlVariant() == null) {
752     		ontology.setWsmlVariant(org.wsmo.common.WSML.WSML_CORE);	
753     	}
754     }
755     
756     /*
757      * This method adds all the namespaces that are used in the rdf file to 
758      * the wsml ontology.
759      * Also added are the dublin core and the wsml namespaces. If no rdf and 
760      * rdfs namespaces are provided from the rdf file, they are added too.
761      * One namespace is set as default namespace to the ontology.
762      */
763     private void setNamespaces(Map namespaces) {       
764         boolean rdf = false;
765         boolean rdfs = false;
766         
767         ontology.addNamespace(
768                 factory.createNamespace("dc", factory.createIRI(DC)));
769         ontology.addNamespace(
770                 factory.createNamespace("wsml", factory.createIRI(WSML.WSML_NAMESPACE)));
771         
772         Iterator it = namespaces.entrySet().iterator();
773         while (it.hasNext()) {
774             Entry entry = (Entry) it.next();
775             String key = (String) entry.getKey();
776             String value = (String) entry.getValue();
777             
778             //attention some tools use the old rdf namespace
779             if (key.equals("rdf")) {
780                 if (value.equals(RDF.NAMESPACE)){
781                     rdf = true;
782                 }else{//we have someone using prefix rdf with somehting else :/
783                     key = "rdf-old";
784                 }
785             }
786             else if (key.equals("rdfs")) {
787                 if (value.equals(RDFS.NAMESPACE)){
788                     rdfs=true;
789                 }else{
790                     key = "rdfs-old";
791                 }
792             }
793             
794             ontology.addNamespace(
795                     factory.createNamespace(key , factory.createIRI(value)));
796         }
797 
798         ontology.setDefaultNamespace(getDefaultNamespace(namespaces));
799 
800         if (!rdf) {
801             ontology.addNamespace(
802                     factory.createNamespace("rdf", factory.createIRI(RDF.NAMESPACE)));
803         }
804         if (!rdfs) {
805             ontology.addNamespace(
806                     factory.createNamespace("rdfs", factory.createIRI(RDFS.NAMESPACE)));
807         }
808     }
809     
810     
811     private Namespace getDefaultNamespace(Map namespaces){    
812         if(this.defaultNS!=null) {
813             return defaultNS;
814         } else{
815             String defaultNsCandidate="http://www.example.org/ontologies/example#";
816             String defaultNsPrefix=null;
817             Iterator it = namespaces.entrySet().iterator();
818             while (it.hasNext()) {
819                 Entry entry = (Entry) it.next();
820                 String key = (String) entry.getKey();
821                 String value = (String) entry.getValue();
822                 if (key.equals("")){
823                     defaultNS = factory.createNamespace("",factory.createIRI(value));
824                 }
825                 //could be improved to guess better a suitable namespace if
826                 //no default was in input
827                 if (!key.equals("dc") && !key.equals("owl")
828                     && !key.equals("xsd") && !key.equals("part-whole")
829                     && !key.equals("rdf") && !key.equals("rdfs")
830                     && !key.equals("wsmo") && !key.equals("foaf")) {
831                     defaultNsCandidate = value;
832                     defaultNsPrefix = key;
833                 }
834             }
835             if (defaultNS == null){
836                 if(defaultNsPrefix!=null) {
837                     namespaces.remove(defaultNsPrefix);
838                 }
839                 defaultNS = factory.createNamespace("",factory.createIRI(defaultNsCandidate)); 
840             }
841             return defaultNS;
842         }
843     }
844     /**
845      * This method returns the ontology that results from transforming the 
846      * rdf statements to a wsmo object model.
847      * 
848      * @return Ontology, the ontology that results from the parsed rdf file
849      */
850     public Ontology getOntology() {
851         return ontology;
852     }
853     
854     /*
855      * Create a wsmo concept and add it to the ontology, if it is not in yet.
856      */
857     private Concept createConcept(String name, Statement statement) 
858             throws SynchronisationException, InvalidModelException {
859         Concept concept = null;
860         IRI iri = null;
861         
862         // check for spaces in names
863         if (name.indexOf(" ") != -1) {
864             name = name.replaceAll(" ", "%20");
865             addWarning("No spaces allowed in identifiers! - Spaces in " +
866                     "one or more concept identifiers " +
867                     "have been replaced by '%20'!", statement);
868         } 
869         
870         // check for anonymous ids
871         try {
872             iri = factory.createIRI(name);
873         } catch (IllegalArgumentException e) {
874             addWarning("Anonymous identifiers problem - One or more " +
875                     "anonymous concepts have not been added to " +
876                     "the WSMO object model!", statement);
877             return null;
878         }
879         if (ontology.findConcept(iri) == null) {
880             concept = factory.createConcept(iri);
881             ontology.addConcept(concept);
882             idConcepts.add(concept.getIdentifier().toString());
883             return concept;
884         }
885         else {
886             return ontology.findConcept(iri);
887         }
888     }
889     
890     /*
891      * Add a SuperConcept to a specified concept.
892      */
893     private void addSuperConcept(Concept concept, Concept superConcept, Statement statement) 
894     throws SynchronisationException, InvalidModelException {
895         String localName = ((IRI) superConcept.getIdentifier()).getLocalName();
896         if (localName.equals("Resource") && !concept.getIdentifier().toString().equals(RDFS.CLASS)) {
897             //superConcept = createConcept(RDFS.CLASS, statement);
898         }
899         if (!concept.getIdentifier().equals(superConcept.getIdentifier())) {
900             concept.addSuperConcept(superConcept);
901         }
902     }
903     
904     /*
905      * Add non functional properties to a specified entity.
906      */
907     private void addNFP(Entity entity, String identifier, String value) 
908             throws SynchronisationException, InvalidModelException {
909         IRI key = factory.createIRI(identifier);
910         DataValue dataValue = dataFactory.createWsmlString(value);
911         entity.addNFPValue(key, dataValue);
912     }
913     
914     /*
915      * Add an attribute to a specified concept.
916      */
917     private Attribute createAttribute(Concept concept, String name, Statement statement) 
918             throws InvalidModelException {
919         IRI iri = null;
920         
921         // check for spaces in names
922         if (name.indexOf(" ") != -1) {
923             name = name.replaceAll(" ", "%20");
924             addWarning("No spaces allowed in identifiers! - Spaces in " +
925                     "one or more attribute identifiers " +
926                     "have been replaced by '%20'!", statement);
927         }  
928         
929         // check for anonymous ids
930         try {
931             iri = factory.createIRI(name);
932         } catch (IllegalArgumentException e) {
933             addWarning("Anonymous identifiers problem - One or more " +
934                     "anonymous attributes have not been added to " +
935                     "the WSMO object model!", statement);
936             return null;
937         }
938         return concept.createAttribute(iri);
939     }
940     
941     /*
942      * Add a type to a specified attribute.
943      */
944     private void addAttributeType(Attribute attribute, Type type) 
945             throws InvalidModelException {
946         attribute.addType(type);
947     }
948     
949     /*
950      * Create an axiom, containing an implication as logicalexpression, 
951      * and add it to the ontology.
952      */
953     private Axiom createAxiom(Attribute a, Attribute b) 
954             throws ParserException, SynchronisationException, InvalidModelException{
955         
956         Axiom axiom = factory.createAxiom(factory.createIRI(
957                 defaultNS.getIRI().toString() + 
958                 ((IRI) a.getIdentifier()).getLocalName() + "_is_" + 
959                 ((IRI) b.getIdentifier()).getLocalName()));
960         
961         ontology.addAxiom(axiom);
962         String le = "?x[" + ((IRI) a.getIdentifier()).getLocalName() + " hasValue ?y] implies ?x[" + 
963                 ((IRI) b.getIdentifier()).getLocalName() + " hasValue ?y].";
964         LogicalExpression logExpr = leFactory.createLogicalExpression(le, ontology);
965         axiom.addDefinition(logExpr);      
966         return axiom;
967     }
968     
969     /*
970      * Create an axiom, containing the string as logicalexpression, 
971      * and add it to the ontology.
972      */
973     private Axiom createAxiom(String name, Statement statement) 
974             throws ParserException, SynchronisationException, InvalidModelException{  
975     	IRI iri = null;
976         
977         // check for spaces in names
978         if (name.indexOf(" ") != -1) {
979             name = name.replaceAll(" ", "%20");
980             addWarning("No spaces allowed in identifiers! - Spaces in " +
981                     "one or more instances identifiers " +
982                     "have been replaced by '%20'!", statement);
983         }  
984         
985         // check for anonymous ids
986         try {
987             iri = factory.createIRI(name);
988         } catch (IllegalArgumentException e) {
989             if(name.startsWith("node")) {
990                 iri = factory.createIRI("blank:" + name);
991             } else {
992                 addWarning("Anonymous identifiers problem - One or more " +
993                         "anonymous instances have not been added to " +
994                         "the WSMO object model!", statement);
995                 return null;
996             }
997         }
998         if (ontology.findAxiom(iri) == null) {
999         	Axiom axiom = factory.createAxiom(iri);
1000             ontology.addAxiom(axiom);
1001             return axiom;
1002         }
1003         else {           
1004             return ontology.findAxiom(iri);
1005         }             
1006     }
1007     
1008     /*
1009      * Create a releation and add it to the ontology.
1010      */
1011     private Relation createRelation(String name, Statement statement) 
1012             throws SynchronisationException, InvalidModelException {
1013         IRI iri = null;
1014         
1015         // check for spaces in names
1016         if (name.indexOf(" ") != -1) {
1017             name = name.replaceAll(" ", "%20");
1018             addWarning("No spaces allowed in identifiers! - Spaces in " +
1019                     "one or more relation identifiers " +
1020                     "have been replaced by '%20'!", statement);
1021         }  
1022         
1023         // check for anonymous ids
1024         try {
1025             iri = factory.createIRI(name);
1026         } catch (IllegalArgumentException e) {
1027             addWarning("Anonymous identifiers problem - One or more " +
1028                     "anonymous relations have not been added to " +
1029                     "the WSMO object model!", statement);
1030             return null;
1031         }
1032         if (ontology.findRelation(iri) == null) {
1033             Relation relation = factory.createRelation(iri);
1034             relation.createParameter((byte) 0);
1035             relation.createParameter((byte) 1);
1036             ontology.addRelation(relation);
1037             idRelations.add(relation.getIdentifier().toString());
1038             return relation;
1039         }
1040         else {           
1041             return ontology.findRelation(iri);
1042         }       
1043     }
1044     
1045     /*
1046      * Add a SuperRelation to a specified relation.
1047      */
1048     private void addSuperRelation(Relation relation, Relation superRelation) 
1049             throws SynchronisationException, InvalidModelException {
1050         relation.addSuperRelation(superRelation);
1051     }
1052     
1053     /*
1054      * Add a type to a specified relation.
1055      */
1056     private void addRelationType(Relation relation, Type type1, Type type2) 
1057             throws SynchronisationException, InvalidModelException {
1058         Parameter p1 = relation.listParameters().get(0);
1059         Parameter p2 = relation.listParameters().get(1);
1060         p1.addType(type1);
1061         p2.addType(type2); 
1062     }
1063     
1064     /*
1065      * Create an instance and add it to the ontology.
1066      */
1067     private Instance createInstance(String name, Statement statement) 
1068             throws SynchronisationException, InvalidModelException {
1069         IRI iri = null;
1070         
1071         // check for spaces in names
1072         if (name.indexOf(" ") != -1) {
1073             name = name.replaceAll(" ", "%20");
1074             addWarning("No spaces allowed in identifiers! - Spaces in " +
1075                     "one or more instances identifiers " +
1076                     "have been replaced by '%20'!", statement);
1077         }  
1078         
1079         // check for anonymous ids
1080         try {
1081             iri = factory.createIRI(name);
1082         } catch (IllegalArgumentException e) {
1083             if(name.startsWith("node")) {
1084                 iri = factory.createIRI("blank:" + name);
1085             } else {
1086                 addWarning("Anonymous identifiers problem - One or more " +
1087                         "anonymous instances have not been added to " +
1088                         "the WSMO object model!", statement);
1089                 return null;
1090             }
1091         }
1092         if (ontology.findInstance(iri) == null) {
1093             Instance instance = factory.createInstance(iri);
1094             ontology.addInstance(instance);
1095             idInstances.add(instance.getIdentifier().toString());
1096             return instance;
1097         }
1098         else {           
1099             return ontology.findInstance(iri);
1100         }       
1101     }
1102     
1103     /*
1104      * Check if the ontology contains a specified instance and return 
1105      * it. If the instance is not contained, null is returned.
1106      */
1107     private Instance getInstance(Value object) {
1108         IRI iri = null;
1109         try {
1110             iri = factory.createIRI(object.toString());
1111         } catch (IllegalArgumentException e) {
1112             if(object instanceof URI) {
1113                 iri = factory.createIRI(ontology.getDefaultNamespace().getIRI() + object.toString());
1114             } else if (object instanceof BNode) {
1115                 iri = factory.createIRI("blank:" + object.toString());
1116             } else {
1117                 return null;
1118             }
1119         }     
1120         if (ontology.findInstance(iri) != null) {
1121             return ontology.findInstance(iri);
1122         }
1123         else {
1124             return null;
1125         }
1126     }
1127     
1128     /*
1129      * Create a RelationInstance and add it to the ontology. As first 
1130      * parameter value the instance is added, and as second parameter 
1131      * value a DataValue from the statement's object value is created 
1132      * and added.
1133      */
1134     private RelationInstance createRelationInstance(Instance instance, Relation relation, Statement statement) 
1135             throws SynchronisationException, InvalidModelException {  
1136         RelationInstance relationInstance = factory.createRelationInstance(relation);
1137         ontology.addRelationInstance(relationInstance);
1138         Instance tmp = getInstance(statement.getObject());
1139         if (tmp == null) {
1140             if (statement.getObject() instanceof URI) {
1141                 tmp = createInstance(statement.getObject().toString(), statement);
1142                 relationInstance.setParameterValue((byte) 1, tmp);
1143             }
1144             else {
1145                 DataValue dataValue = dataFactory.createWsmlString(statement.getObject().toString());
1146                 relationInstance.setParameterValue((byte) 1, dataValue);
1147             }
1148         }
1149         else {
1150             relationInstance.setParameterValue((byte) 1, tmp);
1151         }
1152         relationInstance.setParameterValue((byte) 0, instance);
1153         
1154         return relationInstance; 
1155     }
1156     
1157     private Type createWsmlDataType(IRI iri) {
1158         Type t = null;
1159         if (iri.toString().equals(XmlSchema.STRING)) {
1160             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_STRING);
1161         }
1162         else if (iri.toString().equals(XmlSchema.DECIMAL)) {
1163             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_DECIMAL);
1164         }
1165         else if (iri.toString().equals(XmlSchema.INTEGER)) {
1166             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_INTEGER);
1167         }
1168         else if (iri.toString().equals(XmlSchema.BOOLEAN)) {
1169             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_BOOLEAN);
1170         }
1171         else if (iri.toString().equals(XmlSchema.DATE)) {
1172             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_DATE);
1173         }
1174         else if (iri.toString().equals(XmlSchema.DATETIME)) {
1175             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_DATETIME);
1176         }
1177         else if (iri.toString().equals(XmlSchema.TIME)) {
1178             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_TIME);
1179         }
1180         else if (iri.toString().equals(XmlSchema.ANYURI)) {
1181             t = dataFactory.createWsmlDataType(WsmlDataType.WSML_IRI);
1182         }
1183         return t;
1184     }
1185     
1186     private boolean nonRDFSProperty(String uri) {
1187         return !uri.equals(RDF.TYPE) 
1188             && !uri.equals(RDFS.LABEL)
1189             && !uri.equals(RDFS.COMMENT)
1190             && !uri.equals(RDFS.SEEALSO);
1191     }
1192     
1193     /*
1194      * This methods sends a warning to the RDFParseErrorListener.
1195      */
1196     private void addWarning(String message, Statement statement) {
1197         errorListener.warning(message, -1, -1, statement);
1198     }
1199     
1200 }
1201 /*
1202  * $Log$
1203  * Revision 1.15  2007/04/02 12:13:23  morcen
1204  * Generics support added to wsmo-api, wsmo4j and wsmo-test
1205  *
1206  * Revision 1.14  2007/01/11 12:33:48  nathaliest
1207  * added metamodelling check for detecting correct wsml variant
1208  *
1209  * Revision 1.13  2006/11/30 13:49:46  nathaliest
1210  * *** empty log message ***
1211  *
1212  * Revision 1.12  2006/11/30 13:45:17  nathaliest
1213  * fixed a bug concerning the call of the parse method with a stringbuffer as parameter
1214  *
1215  * Revision 1.11  2006/11/17 16:43:04  nathaliest
1216  * fixed rdf parser to replace spaces by %20
1217  *
1218  * Revision 1.10  2006/11/16 13:24:22  ohamano
1219  * *** empty log message ***
1220  *
1221  * Revision 1.9  2006/11/16 09:52:21  ohamano
1222  * no more internal constant strings
1223  *
1224  * Revision 1.8  2006/11/15 17:01:51  ohamano
1225  * first attempts to more modularization
1226  *
1227  * Revision 1.7  2006/11/15 16:25:20  ohamano
1228  * find a means to "model" blank nodes (bnodes were ignored)
1229  * disambiguate rdf:type from xxx:type (e.g. xsi:type)
1230  *
1231  * Revision 1.6  2006/11/15 14:05:40  ohamano
1232  * remove explict statement for subconcept of rdfs:class resp rdfs:resource
1233  * include wsml.datetime
1234  *
1235  * Revision 1.5  2006/06/06 11:36:12  nathaliest
1236  * fixed problem with xml schema ranges
1237  *
1238  * Revision 1.4  2006/05/15 07:58:12  holgerlausen
1239  * corrected issues with namespaces and ontology ids
1240  *
1241  * Revision 1.2  2006/05/03 15:30:36  nathaliest
1242  * *** empty log message ***
1243  *
1244  * Revision 1.1  2006/05/03 13:32:49  nathaliest
1245  * adding RDF parser
1246  *
1247  * 
1248  */