Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ManchesterParser passes quotes to ShortFormProvider #1111

Closed
tfrancart opened this issue Aug 25, 2023 · 3 comments
Closed

ManchesterParser passes quotes to ShortFormProvider #1111

tfrancart opened this issue Aug 25, 2023 · 3 comments
Labels

Comments

@tfrancart
Copy link

Below is a reproductible test case showing that it is not possible to parse class expressions with labels that contain quotes, e.g. A_Pizza and hasTopping some 'Meat topping'"

It shows that the AnnotationValueShortFormProvider does work and can successfully resolve IRIs from their labels, then shows that the parsing of class expressions with labels fails. If we debug the code we see that the ManchesterOWLSyntaxParser passes the labels with quotes included to the ShortFormProvider (e.g. "'Meat Topping'").

See also https://stackoverflow.com/questions/76951595/how-to-parse-manchester-syntax-with-rdfs-labels-like-in-prot%c3%a9g%c3%a9?noredirect=1#comment135661024_76951595

package fr.limics.intercations_classifier;

import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.expression.ShortFormEntityChecker;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.util.AnnotationValueShortFormProvider;
import org.semanticweb.owlapi.util.BidirectionalShortFormProvider;
import org.semanticweb.owlapi.util.BidirectionalShortFormProviderAdapter;
import org.semanticweb.owlapi.util.SimpleShortFormProvider;
import org.semanticweb.owlapi.util.mansyntax.ManchesterOWLSyntaxParser;

public class ManchesterParserLabelTest {

	public static void main(String...args) throws Exception {
		OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
		
		final String TEST_ONTO = "Prefix: : <http://www.co-ode.org/ontologies/pizza/pizza.owl#>\n"
				+ "Prefix: owl: <http://www.w3.org/2002/07/owl#>\n"
				+ "Prefix: rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
				+ "Prefix: rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
				+ "Prefix: xml: <http://www.w3.org/XML/1998/namespace>\n"
				+ "Prefix: xsd: <http://www.w3.org/2001/XMLSchema#>\n"
				+ "\n"
				+ "\n"
				+ "\n"
				+ "Ontology: <http://www.co-ode.org/ontologies/pizza>\n"
				+ "<http://www.co-ode.org/ontologies/pizza/2.0.0>\n"
				+ "    \n"
				+ "    \n"
				+ "ObjectProperty: hasTopping\n"
				+ "    \n"
				+ "\n"
				+ "Class: Pizza\n"
				+ "\n"
				+ "    Annotations: \n"
				+ "        rdfs:label \"A_Pizza\"@en\n"
				+ "\n"
				+ "Class: FishTopping\n"
				+ "\n"
				+ "    Annotations: \n"
				+ "        rdfs:label \"Fish_Topping\"@en\n"
				+ "    \n"
				+ "Class: MeatTopping\n"
				+ "\n"
				+ "    Annotations: \n"
				+ "        rdfs:label \"Meat topping\"@en\n"
				+ "    \n"
				+ "Class: XXX\n"
				+ "\n"
				+ "    EquivalentTo: \n"
				+ "        Pizza\n"
				+ "         and (not (hasTopping some MeatTopping))";
		
		OWLOntology ontology = manager.loadOntologyFromOntologyDocument(new ByteArrayInputStream(TEST_ONTO.getBytes()));
		OWLDataFactory df = manager.getOWLDataFactory();

		
		ManchesterOWLSyntaxParser manchesterParser = OWLManager.createManchesterParser();
		manchesterParser.setDefaultOntology(ontology); // my ontology
		ShortFormEntityChecker checker = new ShortFormEntityChecker(getShortFormProvider(manager, ontology));
		// prints : <http://www.co-ode.org/ontologies/pizza/pizza.owl#MeatTopping>
		System.out.println("Meat topping : ");
		System.out.println(checker.getOWLClass("Meat topping"));
        // prints : null
        System.out.println("'Meat topping' : ");
        System.out.println(checker.getOWLClass("'Meat topping'"));
        
        manchesterParser.setOWLEntityChecker(checker);
        
        try {
			// This works
			// prints : 
			// ObjectIntersectionOf(<http://www.co-ode.org/ontologies/pizza/pizza.owl#Pizza> ObjectSomeValuesFrom(<http://www.co-ode.org/ontologies/pizza/pizza.owl#hasTopping> <http://www.co-ode.org/ontologies/pizza/pizza.owl#FishTopping>))
			System.out.println("Class expression containing labels without spaces:");
			final String CLASS_EXPRESSION_WITH_LABEL_NO_SPACE = "A_Pizza and hasTopping some Fish_Topping";
			OWLClassExpression exprWithLabelNoSpace = manchesterParser.parseClassExpression(CLASS_EXPRESSION_WITH_LABEL_NO_SPACE);
			System.out.println(exprWithLabelNoSpace);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
       
        
        try {
			System.out.println("Class expression containing IRIs local parts:");
			final String CLASS_EXPRESSION_WITHOUT_LABEL = "Pizza and hasTopping some MeatTopping";
			// Throws ParserException : Encountered Pizza at line 1 column 1
			// this shows the ShortFormProvider works only with labels, not with IRIs
			OWLClassExpression exprWithout = manchesterParser.parseClassExpression(CLASS_EXPRESSION_WITHOUT_LABEL);
			System.out.println(exprWithout);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        
        try {
			System.out.println("Class expression containing labels with space:");
			// throws ParserException : Encountered 'Meat topping' at line 1 column 27.
			// If debugging, we can see that the ShortFormEntityChecker receives the string "'Meat topping'"
			// with quotes included
			final String CLASS_EXPRESSION_WITH_LABEL = "A_Pizza and hasTopping some 'Meat topping'";
			OWLClassExpression exprWith = manchesterParser.parseClassExpression(CLASS_EXPRESSION_WITH_LABEL);
			System.out.println(exprWith);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
    private static BidirectionalShortFormProvider getShortFormProvider(OWLOntologyManager manager, OWLOntology ont) {
        Set<OWLOntology> ontologies = manager.getOntologies(); // my OWLOntologyManager        
        
        // OWLAnnotationProperty rdfsLabelProp = manager.getOWLDataFactory().getOWLAnnotationProperty("http://www.w3.org/2000/01/rdf-schema#label");
        AnnotationValueShortFormProvider sfp = new AnnotationValueShortFormProvider(
        		Collections.singletonList(manager.getOWLDataFactory().getRDFSLabel()),
        		new HashMap<OWLAnnotationProperty, List<String>>() {{
        			put(manager.getOWLDataFactory().getRDFSLabel(), Arrays.asList(new String[] {"en"}));
        		}},
        		manager,
        		new SimpleShortFormProvider()
        );
        
        BidirectionalShortFormProvider shortFormProvider = new BidirectionalShortFormProviderAdapter(
                ontologies, sfp);
        return shortFormProvider;
    }
}
@ignazio1977
Copy link
Contributor

ignazio1977 commented Sep 17, 2023

Protege deals with this with its own classes:

(from OWLClassAxiomChecker)

    parser.setOWLEntityChecker(new ProtegeOWLEntityChecker(mngr.getOWLEntityFinder())); 

The use of '' to escape annotation values with spaces is managed in OWLEntityFinderImpl, it's not part of the manchester syntax implementation in OWL API.

These classes are all part of the protege UI project, so it might be difficult for you to reuse them directly; they also rely on Protege specific ontology manager classes, so not easy to extract as is.

Licence is BSD, which, as far as I understand it, means you could copy and tweak those classes in your own project, provided you include the same licence notice for the new files. I'm not sure if this is compatible with your project licence.

@jamesaoverton
Copy link

ROBOT also has some short form providers (also open source), in case those are easier to borrow and modify than the Protege ones:

https://github.com/ontodev/robot/tree/master/robot-core/src/main/java/org/obolibrary/robot/providers

@tfrancart
Copy link
Author

Thanks ! I am actually doing an integration one level above, by an implementing my own ShortFormEntityChecker instead of my own ShortFormProvider. Much easier. I need to know in theory if an identifier is an identifier of a Class, ObjectProp or DatatypeProp, but I can deal with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants