From 501333548561873a0027f235d47f876610dc9fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Euzenat?= <Jerome.Euzenat@inria.fr> Date: Sun, 7 Mar 2010 19:41:03 +0000 Subject: [PATCH] - added RDFParser for dealing with EDOAL --- .../exmo/align/parser/RDFParser.java | 816 ++++++++++++++++++ 1 file changed, 816 insertions(+) create mode 100644 src/fr/inrialpes/exmo/align/parser/RDFParser.java diff --git a/src/fr/inrialpes/exmo/align/parser/RDFParser.java b/src/fr/inrialpes/exmo/align/parser/RDFParser.java new file mode 100644 index 00000000..cb878b14 --- /dev/null +++ b/src/fr/inrialpes/exmo/align/parser/RDFParser.java @@ -0,0 +1,816 @@ +/* + * $Id$ + * + * Copyright (C) 2006 Digital Enterprise Research Insitute (DERI) Innsbruck + * Sourceforge version 1.7 - 2008 + * Copyright (C) INRIA, 2008-2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package fr.inrialpes.exmo.align.parser; + +import org.semanticweb.owl.align.AlignmentException; + +import fr.inrialpes.exmo.ontowrap.Ontology; +import fr.inrialpes.exmo.ontowrap.BasicOntology; + +import fr.inrialpes.exmo.align.impl.Annotations; +import fr.inrialpes.exmo.align.impl.Namespace; + +import fr.inrialpes.exmo.align.impl.edoal.EDOALAlignment; +import fr.inrialpes.exmo.align.impl.edoal.EDOALCell; +import fr.inrialpes.exmo.align.impl.edoal.EDOALRelation; +import fr.inrialpes.exmo.align.impl.edoal.Expression; +import fr.inrialpes.exmo.align.impl.edoal.Id; +import fr.inrialpes.exmo.align.impl.edoal.Expression; +import fr.inrialpes.exmo.align.impl.edoal.ClassExpression; +import fr.inrialpes.exmo.align.impl.edoal.ClassId; +import fr.inrialpes.exmo.align.impl.edoal.ClassConstruction; +import fr.inrialpes.exmo.align.impl.edoal.ClassRestriction; +import fr.inrialpes.exmo.align.impl.edoal.ClassTypeRestriction; +import fr.inrialpes.exmo.align.impl.edoal.ClassValueRestriction; +import fr.inrialpes.exmo.align.impl.edoal.ClassOccurenceRestriction; +import fr.inrialpes.exmo.align.impl.edoal.PathExpression; +import fr.inrialpes.exmo.align.impl.edoal.PropertyExpression; +import fr.inrialpes.exmo.align.impl.edoal.PropertyId; +import fr.inrialpes.exmo.align.impl.edoal.PropertyConstruction; +import fr.inrialpes.exmo.align.impl.edoal.PropertyRestriction; +import fr.inrialpes.exmo.align.impl.edoal.PropertyDomainRestriction; +import fr.inrialpes.exmo.align.impl.edoal.PropertyTypeRestriction; +import fr.inrialpes.exmo.align.impl.edoal.PropertyValueRestriction; +import fr.inrialpes.exmo.align.impl.edoal.RelationExpression; +import fr.inrialpes.exmo.align.impl.edoal.RelationId; +import fr.inrialpes.exmo.align.impl.edoal.RelationConstruction; +import fr.inrialpes.exmo.align.impl.edoal.RelationRestriction; +import fr.inrialpes.exmo.align.impl.edoal.RelationDomainRestriction; +import fr.inrialpes.exmo.align.impl.edoal.RelationCoDomainRestriction; +import fr.inrialpes.exmo.align.impl.edoal.InstanceExpression; +import fr.inrialpes.exmo.align.impl.edoal.InstanceId; + +import fr.inrialpes.exmo.align.impl.edoal.TransfService; +import fr.inrialpes.exmo.align.impl.edoal.Value; +import fr.inrialpes.exmo.align.impl.edoal.Datatype; +import fr.inrialpes.exmo.align.impl.edoal.Comparator; + +import fr.inrialpes.exmo.align.parser.SyntaxElement.Constructor; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Set; +import java.util.HashSet; +import java.util.List; +import java.util.LinkedList; + +// JE2010: to be suppressed +// How do I shut up the logger? + +import java.util.logging.Logger; +import java.util.logging.Handler; +import java.util.logging.Level; + +// Yes we are relying on Jena for parsing RDF +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Property; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.RDFList; +import com.hp.hpl.jena.rdf.model.Container; +import com.hp.hpl.jena.rdf.model.NodeIterator; +import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; +import com.hp.hpl.jena.vocabulary.RDF; + +/** + * <p> + * Parser for the omwg xml mapping syntax. The document reader is Jena, input can be any document + * which can be read by Jena. The input document format shall be consistent with format document -- + * Expressive alignment language and implementation. You can also see the example input document--example.rdf + * + * </p> + * <p> + * $Id: RDFParser.java,v 1.7 2008/01/26 16:24:58 jeuzenat Exp $ + * </p> + * + * @author Richard Pöttler + * @version $Revision: 1.7 $ + * @date $Date$ + */ +public class RDFParser { + + static Logger logger = Logger.getLogger(RDFParser.class.toString()); + + static Model rDFModel; + + static private boolean debug = false; + + /** + * Initialisation of the structures + * This creates an RDF Model which contains all the syntactic elements. + * This is to be called before parsing, i.e., before exploring RDF resources + */ + public static void initSyntax() { + if ( rDFModel == null ) { + rDFModel = ModelFactory.createDefaultModel(); + // The register is always initialised? + for ( SyntaxElement el : SyntaxElement.values() ) { + // JE2010 This is incorrect because there can be Resources (classes) + // and/or Property ... They may all be resources... + if ( el.isProperty == true ) { + el.resource = rDFModel.createProperty( el.id() ); + } else { + el.resource = rDFModel.createResource( el.id() ); + } + //register.put( el.getName(), el ); + } + } + } + + /** + * Parse the input model. The model shall include one statement that include (?,RDF.type,Alignment) + * @param align + * @return the result EDOALAlignment + * @throws AlignmentException if there is any exception, throw AlignmentException that include describe infomation + * and a caused exception. + */ + public static EDOALAlignment parse( final Model align ) throws AlignmentException { + // Initialize the syntax description + initSyntax(); + // Shut up logging handling (should put a + com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler.silent = true; + //get the statement including alignment resource as rdf:type + StmtIterator stmtIt = align.listStatements(null, RDF.type,(Resource)SyntaxElement.getResource("Alignment")); + // take the first one if it exists + Statement alignDoc; + if (stmtIt.hasNext()) { + alignDoc = stmtIt.nextStatement(); + } else { + throw new AlignmentException("There is no alignment in the RDF docuemnt"); + } + + // Step from this statement + final EDOALAlignment doc = parseAlignment( alignDoc.getSubject() ); + // JE 2010: Clean up the RDF stuff + return doc; +// +// getting and adding the xml namespaces +// final NamedNodeMap attrs = root.getAttributes(); +// for (int iCounter = 0; iCounter < attrs.getLength(); iCounter++) { +// final Node tempNode = attrs.item(iCounter); +// if (tempNode.getNodeName().equals("xmlns")) { +// doc.addNamespace(new Namespace(Namespace.DEFAULT_NS_PREFIX, +// new URI(tempNode.getNodeValue()))); +// } else if (tempNode.getNodeName().startsWith("xmlns")) { +// doc.addNamespace(new Namespace(tempNode.getNodeName() +// .substring(6), new URI(tempNode.getNodeValue()))); +// } +// } + } + + // Below is the plumbing: + // Load the RDF under an RDFModel + // Call the above parse: RDFModel -> EDOALAlignment + + public static EDOALAlignment parse( final File file ) + throws AlignmentException { + Model align = ModelFactory.createDefaultModel(); + try { + align.read(new FileInputStream(file), null); + } catch ( FileNotFoundException fnfe ) { + throw new AlignmentException("RDFParser: There isn't such file: " + + file.getName(), fnfe); + } + return parse(align); + } + + public static EDOALAlignment parse(final Reader is) + throws AlignmentException { + if (is == null) { + throw new AlignmentException("The inputstream must not be null"); + } + Model align = ModelFactory.createDefaultModel(); + align.read(is, null); + // debug align.write(System.out); + return parse(align); + } + + public static EDOALAlignment parse(final InputStream is) + throws AlignmentException { + if (is == null) { + throw new AlignmentException("The inputstream must not be null"); + } + Model align = ModelFactory.createDefaultModel(); + align.read(is, null); + //debug align.write(System.out); + return parse(align); + } + + public static EDOALAlignment parse(final String file) + throws AlignmentException { + Model align = ModelFactory.createDefaultModel(); + align.read(file); + return parse(align); + } + + // Below is the real work + /** + * Parses a mapping document. The resource passed to this method must be a + * <code><Alignment></code> tag. + * + * @param node the alignment resource + * @return the parsed mapping document + * @throws AlignmentException + */ + static EDOALAlignment parseAlignment( final Resource node ) throws AlignmentException { + if (node == null) { + throw new NullPointerException("Alignment must not be null"); + } + + try { + Ontology source = null; + Ontology target = null; + + // getting the id of the document + final URI id = getNodeId( node ); + + final EDOALAlignment doc = new EDOALAlignment(); + if ( id != null ) + doc.setExtension( Namespace.ALIGNMENT.uri, Annotations.ID, id.toString() ); + + StmtIterator stmtIt = node.listProperties((Property)SyntaxElement.MAPPING_SOURCE.resource ); + if ( stmtIt.hasNext() ) { + source = parseOntology( stmtIt.nextStatement().getResource() ); + } else { + throw new AlignmentException( "Missing ontology "+"onto1" ); + } + stmtIt = node.listProperties((Property)SyntaxElement.MAPPING_TARGET.resource ); + if ( stmtIt.hasNext() ) { + target = parseOntology( stmtIt.nextStatement().getResource() ); + } else { + throw new AlignmentException( "Missing ontology "+"onto2" ); + } + stmtIt = node.listProperties((Property)SyntaxElement.LEVEL.resource ); + if ( stmtIt.hasNext() ) { + final String level = stmtIt.nextStatement().getString(); + if ((level != null) && (!level.equals(""))) { + doc.setLevel( level ); + } + } else { + throw new AlignmentException( "Missing level " ); + } + stmtIt = node.listProperties((Property)SyntaxElement.TYPE.resource ); + if ( stmtIt.hasNext() ) { + final String arity = stmtIt.nextStatement().getString(); + if ((arity != null) && (!arity.equals(""))) { + // JE2009: Certainly some control checking should be useful + doc.setType( arity ); + } + } else { + throw new AlignmentException( "Missing type " ); + } + + stmtIt = node.listProperties((Property)SyntaxElement.MAP.resource ); + while (stmtIt.hasNext()) { + Statement stmt = stmtIt.nextStatement(); + if ( debug ) System.err.println( " ---------------> "+stmt ); + //doc.addRule(parseCell(stmt.getResource())); + try { doc.addAlignCell( parseCell( stmt.getResource() ) ); } + catch ( AlignmentException ae ) { + System.err.println( "Error "+ae ); + ae.printStackTrace(); + } + // rdf:type must be forgotten + } + + // Remaining resources... + //else if ( !pred.equals( SyntaxElement.getResource("rdftype") ) ) { // Unknown is annotation + // parseAnnotation( stmt, doc ); + //} + + if ( source != null && target != null ) { + doc.init( source, target ); + } else { + throw new IllegalArgumentException("Missing ontology description"); + } + return doc; + + } catch (AlignmentException e) { + throw e; + } catch (Exception e) { + throw new AlignmentException("There is some error in parsing alignment: " + node.getLocalName(), e); + } + } + + /** + * Parse an ontology node <code><onto1></code> or + * <code><onto2></code> Node to an Ontology object. The node must + * contain the <code><onto...></code> element. + * + * @param node + * the ontology node + * @return the Ontology object + * @throws NullPointerException + * if the node is null + */ + static Ontology parseOntology(final Resource node) throws AlignmentException { + if (node == null) { + throw new AlignmentException("The ontology node must not be null"); + } + + try { + Resource formu = node.getProperty((Property)SyntaxElement.FORMATT.resource).getResource(); + final String formalismName = formu.getProperty((Property)SyntaxElement.NAME.resource).getString(); + final String formalismUri = formu.getProperty((Property)SyntaxElement.URI.resource).getString(); + final Statement location = node.getProperty((Property)SyntaxElement.LOCATION.resource); + Ontology onto = new BasicOntology(); + onto.setURI( new URI( node.getURI() ) ); + onto.setFormURI( new URI( formalismUri ) ); + onto.setFormalism( formalismName ); + if ( location != null ) onto.setFile( new URI( location.getString() ) ); + return onto; + } catch ( Exception e ) { + throw new AlignmentException("The ontology node isn't correct: " + + node.getLocalName(), e); + } + } + + /** + * Parses a mapping rule. The parsed node must be a Cell resource including the mandatory Statement. + * <code><Cell></code> tag. + * + * @param node + * the <code><Cell></code> tag + * @return the parsed rule + * @exception AlignmentException + */ + public static EDOALCell parseCell( final Resource node ) throws AlignmentException { + if (node == null) { + throw new NullPointerException("The node must not be null"); + } + try { + // JE2009: Should be better to use AlignmentAPI relation recognition + // determine the relation, the relation shall be Literal + final String relation = node.getProperty((Property)SyntaxElement.RULE_RELATION.resource).getString(); + //Get the relation + final EDOALRelation type = new EDOALRelation( relation ); + if (type == null) { // I raise an error in this case anyway + throw new IllegalArgumentException("Couln't parse the string \"" + relation + +"\" to a valid rule type"); + } + + // parse the measure, the node shall be Literal and it's a number + final float m = node.getProperty((Property)SyntaxElement.MEASURE.resource).getFloat(); + + // get the id + final URI id = getNodeId( node ); + + //parsing the entity1 and entity2 + Resource entity1 = node.getProperty((Property)SyntaxElement.ENTITY1.resource).getResource(); + Resource entity2 = node.getProperty((Property)SyntaxElement.ENTITY2.resource).getResource(); + + // JE2010: + // Here it would be better to check if the entity has a type. + // If both have none, then we get a old-style correspondence for free + // If it has one, let's go parsing + // I also assume that the factory only do dispatch + + Expression s = parseExpression( entity1 ); + Expression t = parseExpression( entity2 ); + if ( debug ) { + System.err.println(" s : "+s); + System.err.println(" t : "+t); + } + + return new EDOALCell( id.toString(), s, t, type, m ); + } catch (Exception e) { //wrap other type exception + logger.log(java.util.logging.Level.SEVERE, "The cell isn't correct:" + node.getLocalName() + " "+e.getMessage()); + throw new AlignmentException("Cannot parse correspondence " + node.getLocalName(), e); + } + } + + // Here given the type of expression, this can be grand dispatch + public static Expression parseExpression( final Resource node ) throws AlignmentException { + Resource rdfType = node.getProperty( RDF.type ).getResource(); + if ( rdfType.equals( SyntaxElement.CLASS_EXPR.resource ) || + rdfType.equals( SyntaxElement.PROPERTY_OCCURENCE_COND.resource ) || + rdfType.equals( SyntaxElement.PROPERTY_TYPE_COND.resource ) || + rdfType.equals( SyntaxElement.PROPERTY_VALUE_COND.resource ) ) { + return parseClass( node ); + } else if ( rdfType.equals( SyntaxElement.PROPERTY_EXPR.resource ) || + rdfType.equals( SyntaxElement.DOMAIN_RESTRICTION.resource ) || + rdfType.equals( SyntaxElement.TYPE_COND.resource ) || + rdfType.equals( SyntaxElement.VALUE_COND.resource ) ) { + return parseProperty( node ); + } else if ( rdfType.equals( SyntaxElement.RELATION_EXPR.resource ) || + rdfType.equals( SyntaxElement.DOMAIN_RESTRICTION.resource ) || // JE 2010: no chance + rdfType.equals( SyntaxElement.CODOMAIN_RESTRICTION.resource ) ) { + return parseRelation( node ); + } else if ( rdfType.equals( SyntaxElement.INSTANCE_EXPR.resource ) ) { + return parseInstance( node ); + } else { + throw new AlignmentException("There is no parser for entity "+rdfType.getLocalName()); + } + } + + public static ClassExpression parseClass( final Resource node ) throws AlignmentException { + if ( debug ) { + StmtIterator it = node.listProperties(); + while ( it.hasNext() ) System.err.println( " > "+it.next() ); + } + Resource rdfType = node.getProperty(RDF.type).getResource(); + if ( rdfType.equals( SyntaxElement.CLASS_EXPR.resource ) ) { + URI id = getNodeId( node ); + if ( id != null ) { + return new ClassId( id ); + } else { + Statement stmt = null; + Constructor op = null; + // Using a List preserves the order... useful mostly for COMPOSE + // Given the Jena encoding of Collection, LinkedList seems the best + List<ClassExpression> clexpr = new LinkedList<ClassExpression>(); + if ( node.hasProperty( (Property)SyntaxElement.AND.resource ) ) { + op = SyntaxElement.AND.getOperator(); + // listProperties would give them all + stmt = node.getProperty( (Property)SyntaxElement.AND.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.OR.resource ) ) { + op = SyntaxElement.OR.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.OR.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.NOT.resource ) ) { + op = SyntaxElement.NOT.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.NOT.resource ); + } else { + throw new AlignmentException( "Class statement must containt one constructor or Id : "+node ); + } + //JE2010MUSTCHECK + Resource coll = stmt.getResource(); //JE2010MUSTCHECK + if ( op == SyntaxElement.NOT.getOperator() ) { + clexpr.add( parseClass( coll ) ); + } else { // Jena encode these collections as first/rest statements + // THIS IS HORRIBLE BUT I DID NOT FOUND BETTER! + while ( !RDF.nil.getURI().equals( coll.getURI() ) ) { + clexpr.add( parseClass( coll.getProperty( RDF.first ).getResource() ) ); + coll = coll.getProperty( RDF.rest ).getResource(); + } + } + return new ClassConstruction( op, clexpr ); + } + } else { + if ( !rdfType.equals( SyntaxElement.PROPERTY_OCCURENCE_COND.resource ) && + !rdfType.equals( SyntaxElement.PROPERTY_TYPE_COND.resource ) && + !rdfType.equals( SyntaxElement.PROPERTY_VALUE_COND.resource ) ) { + throw new AlignmentException( "Bad class restriction type : "+rdfType ); + } + PathExpression pe; + Comparator comp; + // Find onProperty + Statement stmt = node.getProperty( (Property)SyntaxElement.ONPROPERTY.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:onProperty property" ); + //JE2010MUSTCHECK + pe = parsePathExpression( stmt.getResource() ); + if ( rdfType.equals( SyntaxElement.PROPERTY_TYPE_COND.resource ) ) { + // Datatype could also be defined as objets...? (like rdf:resource="") + // Or classes? OF COURSE???? + stmt = node.getProperty( (Property)SyntaxElement.DATATYPE.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:datatype property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isLiteral() ) { + return new ClassTypeRestriction( pe, new Datatype( ((Literal)nn).getString() ) ); + } else { + throw new AlignmentException( "Bad edoal:datatype value" ); + } + } else { + // Find comparator + // JE2010: This is not good as comparator management... + stmt = node.getProperty( (Property)SyntaxElement.COMPARATOR.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:comparator property" ); + URI id = getNodeId( stmt.getResource() ); + if ( id != null ) comp = new Comparator( id ); + else throw new AlignmentException("Cannot parse anonymous individual"); + /* + try { + comp = new Comparator ( new URI( stmt.getResource().getURI() ) ); + } catch ( URISyntaxException usex ) { + throw new AlignmentException( "Bad URI for comparator: "+stmt.getResource().getURI(), usex ); + } + */ + if ( rdfType.equals( SyntaxElement.PROPERTY_OCCURENCE_COND.resource ) ) { + stmt = node.getProperty( (Property)SyntaxElement.VALUE.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:value property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isLiteral() ) { + return new ClassOccurenceRestriction( pe, comp, ((Literal)nn).getInt() ); + } else { + throw new AlignmentException( "Bad occurence specification : "+nn ); + } + } else if ( rdfType.equals( SyntaxElement.PROPERTY_VALUE_COND.resource ) ) { + stmt = node.getProperty( (Property)SyntaxElement.VALUE.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:value property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isLiteral() ) { + return new ClassValueRestriction( pe, comp, new Value( ((Literal)nn).getString() ) ); + } else if ( nn.isResource() ) { + // get the type + Resource nnType = ((Resource)nn).getProperty(RDF.type).getResource(); + if ( nnType.equals( SyntaxElement.INSTANCE_EXPR.resource ) ) { + return new ClassValueRestriction( pe, comp, parseInstance( (Resource)nn ) ); + } else { + return new ClassValueRestriction( pe, comp, parsePathExpression( (Resource)nn ) ); + } // This one will raise the error + } else { + throw new AlignmentException( "Bad edoal:value value" ); + } + } + } + } + return null; + } + + // JE2010: Here is the problem again with DOMAIN (for instance) + static PathExpression parsePathExpression( final Resource node ) throws AlignmentException { + Resource rdfType = node.getProperty(RDF.type).getResource(); + if ( rdfType.equals( SyntaxElement.PROPERTY_EXPR.resource ) || + rdfType.equals( SyntaxElement.DOMAIN_RESTRICTION.resource ) || + rdfType.equals( SyntaxElement.TYPE_COND.resource ) || + rdfType.equals( SyntaxElement.VALUE_COND.resource ) ) { + return parseProperty( node ); + } else if ( rdfType.equals( SyntaxElement.RELATION_EXPR.resource ) || + rdfType.equals( SyntaxElement.CODOMAIN_RESTRICTION.resource ) || + rdfType.equals( SyntaxElement.VALUE_COND.resource ) ) { + return parseRelation( node ); + } else throw new AlignmentException( "Cannot parse path expression ("+rdfType+"): "+node ); + + } + + // rdf:parseType="Collection" is supposed to preserve the order () + // Jena indeed always preserves the order so this can be used + static PropertyExpression parseProperty( final Resource node ) throws AlignmentException { + Resource rdfType = node.getProperty(RDF.type).getResource(); + Statement stmt = null; + if ( rdfType.equals( SyntaxElement.PROPERTY_EXPR.resource ) ) { + URI id = getNodeId( node ); + if ( id != null ) { + return new PropertyId( id ); + } else { + Constructor op = null; + List<PathExpression> clexpr = new LinkedList<PathExpression>(); + if ( node.hasProperty( (Property)SyntaxElement.AND.resource ) ) { + op = SyntaxElement.AND.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.AND.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.OR.resource ) ) { + op = SyntaxElement.OR.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.OR.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.COMPOSE.resource ) ) { + op = SyntaxElement.COMPOSE.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.COMPOSE.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.NOT.resource ) ) { + op = SyntaxElement.NOT.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.NOT.resource ); + } else { + throw new AlignmentException( "Property statement must containt one constructor or Id : "+node ); + } + Resource coll = stmt.getResource(); //JE2010MUSTCHECK + if ( op == SyntaxElement.NOT.getOperator() ) { + clexpr.add( parseProperty( coll ) ); + } else if ( op == SyntaxElement.COMPOSE.getOperator() ) { + // THIS IS HORRIBLE BUT I DID NOT FOUND BETTER! + while ( !RDF.nil.getURI().equals( coll.getURI() ) ) { + // In this present case, I have to parse a series of Relations + // followed by a Property + Resource newcoll = coll.getProperty( RDF.rest ).getResource(); //JE2010MUSTCHECK + if ( !RDF.nil.getURI().equals( newcoll.getURI() ) ) { + clexpr.add( parseRelation( coll.getProperty( RDF.first ).getResource() ) ); + } else { + clexpr.add( parseProperty( coll.getProperty( RDF.first ).getResource() ) ); + } + coll = newcoll; + } + } else { // This is a first/rest statements + // THIS IS HORRIBLE BUT I DID NOT FOUND BETTER! + while ( !RDF.nil.getURI().equals( coll.getURI() ) ) { + //JE2010MUSTCHECK + clexpr.add( parseProperty( coll.getProperty( RDF.first ).getResource() ) ); + coll = coll.getProperty( RDF.rest ).getResource(); + } + } + return new PropertyConstruction( op, clexpr ); + } + } else if ( rdfType.equals( SyntaxElement.DOMAIN_RESTRICTION.resource ) ) { + stmt = node.getProperty( (Property)SyntaxElement.TOCLASS.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:toClass property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isResource() ) { + return new PropertyDomainRestriction( parseClass( (Resource)nn ) ); + } else { + throw new AlignmentException( "Incorrect class expression "+nn ); + } + } else if ( rdfType.equals( SyntaxElement.TYPE_COND.resource ) ) { + // Datatype could also be defined as objets...? (like rdf:resource="") + // Or classes? OF COURSE???? + stmt = node.getProperty( (Property)SyntaxElement.DATATYPE.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:datatype property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isLiteral() ) { + return new PropertyTypeRestriction( new Datatype( ((Literal)nn).getString() ) ); + } else { + throw new AlignmentException( "Bad edoal:datatype value" ); + } + } else if ( rdfType.equals( SyntaxElement.VALUE_COND.resource ) ) { + // Find comparator + // JE2010: This is not good as comparator management... + stmt = node.getProperty( (Property)SyntaxElement.COMPARATOR.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:comparator property" ); + URI id = getNodeId( stmt.getResource() ); + if ( id == null ) throw new AlignmentException("Bad comparator"); + Comparator comp = new Comparator( id ); + /* + try { + comp = new Comparator ( new URI( stmt.getResource().getURI() ) ); + } catch ( URISyntaxException usex ) { + throw new AlignmentException( "Bad URI for comparator: "+stmt.getResource().getURI(), usex ); + } + */ + stmt = node.getProperty( (Property)SyntaxElement.VALUE.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:value property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isLiteral() ) { + return new PropertyValueRestriction( comp, new Value( ((Literal)nn).getString() ) ); + } else if ( nn.isResource() ) { + // get the type + Resource nnType = ((Resource)nn).getProperty(RDF.type).getResource(); + if ( nnType.equals( SyntaxElement.INSTANCE_EXPR.resource ) ) { + return new PropertyValueRestriction( comp, parseInstance( (Resource)nn ) ); + } else { + //return new ClassValueRestriction( pe, comp, parsePathExpression( (Resource)nn ) ); + throw new AlignmentException( "Connot restrict value to "+nnType ); + } + } else { + throw new AlignmentException( "Bad edoal:value value" ); + } + } else { + throw new AlignmentException("There is no pasrser for entity "+rdfType.getLocalName()); + } + } + + static RelationExpression parseRelation( final Resource node ) throws AlignmentException { + Resource rdfType = node.getProperty(RDF.type).getResource(); + Statement stmt = null; + if ( rdfType.equals( SyntaxElement.RELATION_EXPR.resource ) ) { + URI id = getNodeId( node ); + if ( id != null ) { + return new RelationId( id ); + } else { + Constructor op = null; + // JE2010: does not compile with RelationExpression !! + List<PathExpression> clexpr = new LinkedList<PathExpression>(); + if ( node.hasProperty( (Property)SyntaxElement.AND.resource ) ) { + op = SyntaxElement.AND.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.AND.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.OR.resource ) ) { + op = SyntaxElement.OR.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.OR.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.COMPOSE.resource ) ) { + op = SyntaxElement.COMPOSE.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.COMPOSE.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.NOT.resource ) ) { + op = SyntaxElement.NOT.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.NOT.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.INVERSE.resource ) ) { + op = SyntaxElement.INVERSE.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.INVERSE.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.REFLEXIVE.resource ) ) { + op = SyntaxElement.REFLEXIVE.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.REFLEXIVE.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.SYMMETRIC.resource ) ) { + op = SyntaxElement.SYMMETRIC.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.SYMMETRIC.resource ); + } else if ( node.hasProperty( (Property)SyntaxElement.TRANSITIVE.resource ) ) { + op = SyntaxElement.TRANSITIVE.getOperator(); + stmt = node.getProperty( (Property)SyntaxElement.TRANSITIVE.resource ); + } else { + throw new AlignmentException( "Relation statement must containt one constructor or Id : "+node ); + } + Resource coll = stmt.getResource(); //JE2010MUSTCHECK + if ( op == SyntaxElement.NOT.getOperator() || + op == SyntaxElement.INVERSE.getOperator() || + op == SyntaxElement.REFLEXIVE.getOperator() || + op == SyntaxElement.SYMMETRIC.getOperator() || + op == SyntaxElement.TRANSITIVE.getOperator() ) { + clexpr.add( parseRelation( coll ) ); + } else { // This is a first/rest statements + // THIS IS HORRIBLE BUT I DID NOT FOUND BETTER! + while ( !RDF.nil.getURI().equals( coll.getURI() ) ) { + //JE2010MUSTCHECK + clexpr.add( parseRelation( coll.getProperty( RDF.first ).getResource() ) ); + coll = coll.getProperty( RDF.rest ).getResource(); + } + } + return new RelationConstruction( op, clexpr ); + } + } else if ( rdfType.equals( SyntaxElement.DOMAIN_RESTRICTION.resource ) ) { + stmt = node.getProperty( (Property)SyntaxElement.TOCLASS.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:toClass property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isResource() ) { + return new RelationDomainRestriction( parseClass( (Resource)nn ) ); + } else { + throw new AlignmentException( "Incorrect class expression "+nn ); + } + } else if ( rdfType.equals( SyntaxElement.CODOMAIN_RESTRICTION.resource ) ) { + stmt = node.getProperty( (Property)SyntaxElement.TOCLASS.resource ); + if ( stmt == null ) throw new AlignmentException( "Required edoal:toClass property" ); + RDFNode nn = stmt.getObject(); + if ( nn.isResource() ) { + return new RelationCoDomainRestriction( parseClass( (Resource)nn ) ); + } else { + throw new AlignmentException( "Incorrect class expression "+nn ); + } + } else { + throw new AlignmentException("There is no pasrser for entity "+rdfType.getLocalName()); + } + } + + static InstanceExpression parseInstance( final Resource node ) throws AlignmentException { + Resource rdfType = node.getProperty(RDF.type).getResource(); + if ( rdfType.equals( SyntaxElement.INSTANCE_EXPR.resource ) ) { + URI id = getNodeId( node ); + if ( id != null ) return new InstanceId( id ); + else throw new AlignmentException("Cannot parse anonymous individual"); + } else { + throw new AlignmentException("There is no pasrser for entity "+rdfType.getLocalName()); + } + } + + static Value parseValue( final Resource node ) throws AlignmentException { + return null; + } + + static URI getNodeId( final Resource node ) throws AlignmentException { + final String idS = node.getURI(); + if ((idS != null) && (idS.length() > 0)) { + try { + return new URI(idS); + } catch ( URISyntaxException usex ) { + throw new AlignmentException( "Incorrect URI: "+idS ); + } + } else { + return null; + } + } + + /** + * Parses a given annotaion in the the given node. + * + * @param node + * which is the parent of the annotation node + * @param e + * the tag which contains the annotation. + * @return the parsed annotation, with the id set to the element and the + * value set to the text of the parsed node, or null, if nothing + * could be found + * @throws NullPointerException + * if the node or the element is null + */ + static void parseAnnotation(final Statement stmt, EDOALAlignment al ) throws AlignmentException { + try { + final String anno = stmt.getString(); + if ((anno != null) && (anno.length() > 0)) { + URI uri = new URI ( stmt.getPredicate().getURI() ); + String name = uri.getFragment(); + String prefix = uri.getScheme()+":"+uri.getSchemeSpecificPart(); + if ( name == null ) { + int pos = prefix.lastIndexOf('/'); + name = prefix.substring( pos+1 ); + prefix = prefix.substring( 0, pos+1 ); + } else { prefix += "#"; } + // JE: this will not work for stuff like dc:creator which has no fragment! + al.setExtension( prefix, name, anno ); + } + } catch (Exception e1) { + // JE2009: Would be better to silently ignore annotations + // Or report them in a bunch + throw new AlignmentException("The annotation is not correct", e1); + } + } + + +} -- GitLab