package org.semanticweb.HermiT.reasoner;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.semanticweb.HermiT.AbstractOntologyTest;
import org.semanticweb.HermiT.Configuration;
import org.semanticweb.HermiT.EntailmentChecker;
import org.semanticweb.HermiT.Prefixes;
import org.semanticweb.HermiT.Reasoner;
import org.semanticweb.HermiT.Reasoner.ReasonerFactory;
import org.semanticweb.HermiT.model.Constant;
import org.semanticweb.HermiT.model.DescriptionGraph;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLogicalAxiom;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;

public abstract class AbstractReasonerTest extends AbstractOntologyTest {
    protected Reasoner m_reasoner;

    public AbstractReasonerTest(String name) {
        super(name);
    }

    protected void tearDown() {
        super.tearDown();
        m_reasoner=null;
        m_dataFactory=null;
        m_ontology=null;
        m_ontologyManager=null;
    }

    protected void loadReasonerFromResource(String resourceName) throws Exception {
        IRI physicalIRI=IRI.create(getClass().getResource(resourceName).toURI());
        m_ontology=m_ontologyManager.loadOntologyFromOntologyDocument(physicalIRI);
        createReasoner();
    }

    protected void loadReasonerWithAxioms(String axioms) throws Exception {
        loadOntologyWithAxioms(axioms);
        createReasoner();
    }
    protected void createReasoner() {
        createReasoner(getConfiguration(),null);
    }
    protected void createReasoner(Configuration configuration,Set<DescriptionGraph> descriptionGraphs) {
        if (descriptionGraphs==null)
            descriptionGraphs=Collections.emptySet();
        m_reasoner=new Reasoner(configuration,m_ontology,descriptionGraphs);
    }
    protected void createOWLReasoner(Configuration c) {
        OWLReasonerFactory factory=new ReasonerFactory();
        m_reasoner=(Reasoner)factory.createReasoner(m_ontology,c);
    }
    protected void createOWLReasoner() {
        createOWLReasoner(getConfiguration());
    }

    /**
     * Returns the class and the property hierarchies as text.
     */
    protected String getHierarchiesAsText() {
        CharArrayWriter buffer=new CharArrayWriter();
        PrintWriter output=new PrintWriter(buffer);
        m_reasoner.printHierarchies(output,true,true,true);
        output.flush();
        return buffer.toString();
    }

    /**
     * Loads the ontology from ontologyResource and the string in controlResource and compares the computed taxonomy for the ontology with the one in the controlResource by comparing the sorted ancestor list.
     *
     * @param ontologyResource
     *            the ontology
     * @param controlResource
     *            the expected taxonomy (sorted ancestor list)
     */
    protected void assertHierarchies(String controlResource) throws Exception {
        String taxonomy=getHierarchiesAsText();
        String controlString=getResourceText(controlResource);
        assertEquals(controlString,taxonomy);
    }

    /**
     * Tests whether the loaded ontology is consistent or not and asserts that this coincides with the given parameter satisfiable.
     *
     * @param satisfiable
     *            if the currently loaded ontology is expected to be satisfiable
     */
    protected void assertABoxSatisfiable(boolean satisfiable) {
        assertEquals(satisfiable,m_reasoner.isConsistent());
    }

    /**
     * Tests whether the atomic concept subAtomicConcept is subsumed by the atomic concept superAtomicConcept and asserts that this coincides with the expected result.
     *
     * @param subAtomicConcept
     *            a string that represents an atomic concept. If no prefix is given, NS is used as prefix
     * @param superAtomicConcept
     *            a string that represents an atomic concept. If no prefix is given, NS is used as prefix
     * @param expectedResult
     */
    protected void assertSubsumedBy(String subAtomicConcept,String superAtomicConcept,boolean expectedResult) {
        if (!subAtomicConcept.contains("#"))
            subAtomicConcept=NS+subAtomicConcept;
        if (!superAtomicConcept.contains("#"))
            superAtomicConcept=NS+superAtomicConcept;
        OWLClass subClass=m_dataFactory.getOWLClass(IRI.create(subAtomicConcept));
        OWLClass superClass=m_dataFactory.getOWLClass(IRI.create(superAtomicConcept));
        boolean result=m_reasoner.isEntailed(m_dataFactory.getOWLSubClassOfAxiom(subClass, superClass));
        assertEquals(expectedResult,result);
    }

    /**
     * Tests whether the possibly complex concept subConcept is subsumed by the possibly complex concept superConcept and asserts that this coincides with the expected result.
     */
    protected void assertSubsumedBy(OWLClassExpression subClass,OWLClassExpression superClass,boolean expectedResult) {
        boolean result=m_reasoner.isEntailed(m_dataFactory.getOWLSubClassOfAxiom(subClass, superClass));
        assertEquals(expectedResult,result);
    }

    /**
     * Tests whether the atomic concept atomicConcept is satisfiable and asserts that this coincides with the expected result (satisfiable).
     */
    protected void assertSatisfiable(String atomicConcept,boolean expectedResult) {
        if (!atomicConcept.contains("#"))
            atomicConcept=NS+atomicConcept;
        OWLClass clazz=m_dataFactory.getOWLClass(IRI.create(atomicConcept));
        boolean result=m_reasoner.isSatisfiable(clazz);
        assertEquals(expectedResult,result);
    }

    /**
     * Tests whether the given possibly complex concept is satisfiable and asserts that this coincides with the expected result (satisfiable).
     */
    protected void assertSatisfiable(OWLClassExpression concept,boolean satisfiable) throws Exception {
        assertEquals(satisfiable,m_reasoner.isSatisfiable(concept));
    }

    /**
     * Tests whether the given individual is an instance of the given concept and asserts that this coincides with the expected result.
     */
    protected void assertInstanceOf(OWLClassExpression concept,OWLNamedIndividual individual,boolean expectedResult) {
        boolean result=m_reasoner.hasType(individual,concept,false);
        assertEquals(expectedResult,result);
    }

    /**
     * Tests whether the given concept has the specified individuals.
     */
    protected void assertInstancesOf(OWLClassExpression concept,boolean direct,String... expectedIndividuals) {
        NodeSet<OWLNamedIndividual> actual=m_reasoner.getInstances(concept,direct);
        Set<String> actualIndividualIRIs=new HashSet<String>();
        for (OWLIndividual individual : actual.getFlattened()) {
            if (!individual.isAnonymous())
                actualIndividualIRIs.add(individual.asOWLNamedIndividual().getIRI().toString());
        }
        String[] expectedModified=expectedIndividuals.clone();
        assertContainsAll(actualIndividualIRIs,expectedModified);
    }

    /**
     * Checks the direct superproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSuperObjectProperties(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSuperObjectProperties(ope,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the direct superproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSuperObjectPropertiesOfInverse(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectProperty op=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectInverseOf(op);
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSuperObjectProperties(ope,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the superproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertSuperObjectProperties(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSuperObjectProperties(ope,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the superproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertSuperObjectPropertiesOfInverse(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectProperty op=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectInverseOf(op);
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSuperObjectProperties(ope,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the direct subproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSubObjectProperties(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSubObjectProperties(ope,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the direct subproperties of the inverse of the given object property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSubObjectPropertiesOfInverse(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectProperty op=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectInverseOf(op);
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSubObjectProperties(ope,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the subproperties of some object property.
     */
    @SuppressWarnings("all")
    protected void assertSubObjectProperties(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSubObjectProperties(ope,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the subproperties of the inverse of the given object property.
     */
    @SuppressWarnings("all")
    protected void assertSubObjectPropertiesOfInverse(String objectProperty,Set<String>... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectProperty op=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectInverseOf(op);
        Set<Set<String>> actual=nodeSetOfOPEsToStrings(m_reasoner.getSubObjectProperties(ope,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the equivalents of some object property.
     */
    protected void assertEquivalentObjectProperties(String objectProperty,String... control) {
        if (!objectProperty.contains("#"))
            objectProperty=NS+objectProperty;
        OWLObjectPropertyExpression ope=m_dataFactory.getOWLObjectProperty(IRI.create(objectProperty));
        Set<String> actual=nodeOfOPEs(m_reasoner.getEquivalentObjectProperties(ope));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the superproperties of some data property.
     */
    @SuppressWarnings("all")
    protected void assertSuperDataProperties(String dataProperty,Set<String>... control) {
        if (!dataProperty.contains("#"))
            dataProperty=NS+dataProperty;
        OWLDataProperty dp=m_dataFactory.getOWLDataProperty(IRI.create(dataProperty));
        Set<Set<String>> actual=nodeSetOfDPsToStrings(m_reasoner.getSuperDataProperties(dp,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the direct superproperties of some data property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSuperDataProperties(String dataProperty,Set<String>... control) {
        if (!dataProperty.contains("#"))
            dataProperty=NS+dataProperty;
        OWLDataProperty dp=m_dataFactory.getOWLDataProperty(IRI.create(dataProperty));
        Set<Set<String>> actual=nodeSetOfDPsToStrings(m_reasoner.getSuperDataProperties(dp,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the subproperties of some data property.
     */
    @SuppressWarnings("all")
    protected void assertSubDataProperties(String dataProperty,Set<String>... control) {
        if (!dataProperty.contains("#"))
            dataProperty=NS+dataProperty;
        OWLDataProperty dp=m_dataFactory.getOWLDataProperty(IRI.create(dataProperty));
        Set<Set<String>> actual=nodeSetOfDPsToStrings(m_reasoner.getSubDataProperties(dp,false));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the direct subproperties of some data property.
     */
    @SuppressWarnings("all")
    protected void assertDirectSubDataProperties(String dataProperty,Set<String>... control) {
        if (!dataProperty.contains("#"))
            dataProperty=NS+dataProperty;
        OWLDataProperty dp=m_dataFactory.getOWLDataProperty(IRI.create(dataProperty));
        Set<Set<String>> actual=nodeSetOfDPsToStrings(m_reasoner.getSubDataProperties(dp,true));
        assertContainsAll(actual,control);
    }

    /**
     * Checks the equivalents of some data property.
     */
    protected void assertEquivalentDataProperties(String dataProperty,String... control) {
        if (!dataProperty.contains("#"))
            dataProperty=NS+dataProperty;
        OWLDataProperty dp=m_dataFactory.getOWLDataProperty(IRI.create(dataProperty));
        Set<String> actual=nodeOfDPEs(m_reasoner.getEquivalentDataProperties(dp));
        assertContainsAll(actual,control);
    }

    protected void assertEntails(OWLAxiom axiom,boolean expectedResult) {
        assertTrue(new EntailmentChecker(m_reasoner,m_dataFactory).entails(axiom)==expectedResult);
    }

    protected void assertEntails(Set<OWLLogicalAxiom> axioms,boolean expectedResult) {
        assertTrue(new EntailmentChecker(m_reasoner,m_dataFactory).entails(axioms)==expectedResult);
    }

    protected static Set<Set<String>> nodeSetOfOPEsToStrings(NodeSet<OWLObjectPropertyExpression> nodeSet) {
        Set<Set<String>> result=new HashSet<Set<String>>();
        for (Node<OWLObjectPropertyExpression> node : nodeSet.getNodes()) {
            result.add(nodeOfOPEs(node));
        }
        return result;
    }

    protected static Set<String> nodeOfOPEs(Node<OWLObjectPropertyExpression> node) {
        Set<String> translatedSet=new HashSet<String>();
        for (OWLObjectPropertyExpression ope : node.getEntities()) {
            if (ope.getSimplified().isAnonymous()) {
                // inverse
                translatedSet.add("InverseOf("+ope.getNamedProperty().getIRI().toString()+")");
            }
            else
                translatedSet.add(ope.asOWLObjectProperty().getIRI().toString());
        }
        return translatedSet;
    }

    protected static Set<Set<String>> nodeSetOfDPsToStrings(NodeSet<OWLDataProperty> nodeSet) {
        Set<Set<String>> result=new HashSet<Set<String>>();
        for (Node<OWLDataProperty> set : nodeSet) {
            Set<String> translatedSet=nodeOfDPEs(set);
            result.add(translatedSet);
        }
        return result;
    }

    protected static Set<String> nodeOfDPEs(Node<OWLDataProperty> node) {
        Set<String> translatedSet=new HashSet<String>();
        for (OWLDataProperty dp : node)
            translatedSet.add(dp.getIRI().toString());
        return translatedSet;
    }

    /**
     * Can be overridden by the subclass to provide a different configuration for the tests.
     */
    protected Configuration getConfiguration() {
        Configuration c=new Configuration();
        c.throwInconsistentOntologyException=false;
        return c;
    }

    protected void assertDRSatisfiable(boolean value,String... parts) throws Exception {
        assertDRSatisfiableNEQ(value,1,null,parts);
    }

    protected void assertDRSatisfiable(boolean value,int cardinality,String... parts) throws Exception {
        // The dummy forbidden value is used to turn off the "symmetric clique" optimization in the DatatypeManager.
        // This is useful only when value>=1 (otherwise, there is just one individual and the D-conjunction is a clique).
        // This is so that we test the basic algorithm.
        assertDRSatisfiableNEQ(value,cardinality,new String[] { STR("$internal$") },parts);
    }

    protected void assertDRSatisfiableUseCliqueOptimization(boolean value,int cardinality,String... parts) throws Exception {
        // This version of the method does not introduce any forbidden values, which allows the DatatypeManager
        // to use the "symmetric clique" optimization if possible.
        assertDRSatisfiableNEQ(value,cardinality,null,parts);
    }

    protected void assertDRSatisfiableNEQ(boolean value,String[] forbiddenValues,String... parts) throws Exception {
        assertDRSatisfiableNEQ(value,1,forbiddenValues,parts);
    }

    protected void assertDRSatisfiableNEQ(boolean value,int cardinality,String[] forbiddenValues,String... parts) throws Exception {
        StringBuffer buffer=new StringBuffer();
        buffer.append("Declaration(NamedIndividual(test:a)) Declaration(Class(test:A)) Declaration(DataProperty(test:dp)) SubClassOf( test:A DataMinCardinality( ");
        buffer.append(cardinality);
        buffer.append(" test:dp rdfs:Literal ) ) ");
        for (String part : parts) {
            buffer.append("SubClassOf( test:A DataAllValuesFrom( test:dp ");
            buffer.append(part);
            buffer.append(" ) ) ");
        }
        buffer.append("ClassAssertion( test:A test:a ) ");
        if (forbiddenValues!=null) {
            int index=0;
            for (String forbiddenValue : forbiddenValues) {
                String fvName="test:fv"+index;
                buffer.append("DisjointDataProperties( test:dp ");
                buffer.append(fvName);
                buffer.append(" ) ");
                buffer.append("DataPropertyAssertion( ");
                buffer.append(fvName);
                buffer.append(" test:a ");
                buffer.append(forbiddenValue);
                buffer.append(" ) ");
                index++;
            }
        }
        loadReasonerWithAxioms(buffer.toString());
        assertABoxSatisfiable(value);
    }

    protected void assertRegular(String axioms,boolean b) throws Exception {
        boolean regular=true;
        try {
            loadReasonerWithAxioms(axioms);
        }
        catch (IllegalArgumentException e) {
            if (e.getMessage().contains("The given property hierarchy is not regular"))
                regular=false;
            else
                throw new Exception(e.getMessage());
        }
        assertEquals(regular,b);
    }
    protected void assertSimple(String axioms,boolean b) throws Exception {
        boolean simple=true;
        try {
            loadReasonerWithAxioms(axioms);
        }
        catch (IllegalArgumentException e) {
            if (e.getMessage().contains("Non-simple property '"))
                simple=false;
            else
                throw new Exception(e.getMessage());
        }
        assertEquals(simple,b);
    }

    protected static Set<String> EQ(String... args) {
        Set<String> result=new HashSet<String>();
        for (String arg : args) {
            if (!arg.contains("#"))
                arg=NS+arg;
            result.add(arg);
        }
        return result;
    }

    protected static Set<String> EQInv(String... args) {
        Set<String> result=new HashSet<String>();
        for (String arg : args) {
            if (!arg.contains("#"))
                arg=NS+arg;
            result.add("InverseOf("+arg+")");
        }
        return result;
    }

    protected static String[] IRIs(String... args) {
        for (int index=0;index<args.length;index++)
            args[index]=IRI(args[index]);
        return args;
    }

    protected static String IRI(String arg) {
        if (!arg.contains("#"))
            arg=NS+arg;
        return arg;
    }

    protected static String NOT(String argument) {
        return "DataComplementOf( "+argument+" )";
    }

    protected static String DR(String datatype,String... restrictions) {
        StringBuffer buffer=new StringBuffer();
        if (restrictions.length==0)
            buffer.append(datatype);
        else {
            buffer.append("DatatypeRestriction( ");
            buffer.append(datatype);
            for (String restriction : restrictions) {
                buffer.append(' ');
                buffer.append(restriction);
            }
            buffer.append(" )");
        }
        return buffer.toString();
    }

    protected static String OO(String... elements) {
        StringBuffer buffer=new StringBuffer();
        buffer.append("DataOneOf(");
        for (String element : elements) {
            buffer.append(' ');
            buffer.append(element);
        }
        buffer.append(" )");
        return buffer.toString();
    }

    protected static String INT(String value) {
        return '\"'+value+"\"^^xsd:integer";
    }

    protected static Constant INT_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"integer");
    }

    protected static String DEC(String value) {
        return '\"'+value+"\"^^xsd:decimal";
    }

    protected static Constant DEC_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"decimal");
    }

    protected static String RAT(String num,String denom) {
        return '\"'+num+"/"+denom+"\"^^owl:rational";
    }

    protected static Constant RAT_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"rational");
    }

    protected static String FLT(String value) {
        return '\"'+value+"\"^^xsd:float";
    }

    protected static Constant FLT_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"float");
    }

    protected static String DBL(String value) {
        return '\"'+value+"\"^^xsd:double";
    }

    protected static Constant DBL_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"double");
    }

    protected static String DATE(String value) {
        return '\"'+value+"\"^^xsd:dateTime";
    }

    protected static Constant DATE_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"dateTime");
    }

    protected static String DATES(String value) {
        return '\"'+value+"\"^^xsd:dateTimeStamp";
    }

    protected static Constant DATES_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"dateTimeStamp");
    }

    protected static String XMLL(String value) {
        return '\"'+value+"\"^^rdf:XMLLiteral";
    }

    protected static Constant XMLL_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("rdf:")+"XMLLiteral");
    }

    protected static String HEXB(String value) {
        return '\"'+value+"\"^^xsd:hexBinary";
    }

    protected static Constant HEXB_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"hexBinary");
    }

    protected static String B64B(String value) {
        return '\"'+value+"\"^^xsd:base64Binary";
    }

    protected static Constant B64B_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"has64Binary");
    }

    protected static String STR(String value) {
        return '\"'+value+"\"^^xsd:string";
    }

    protected static Constant STR_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"string");
    }

    protected static String STR(String value,String languageTag) {
        return '\"'+value+"\"@"+languageTag;
    }

    protected static Constant STR_C(String value,String languageTag) {
        return Constant.create(value+"\"@"+languageTag,Prefixes.s_semanticWebPrefixes.get("xsd:")+"string");
    }

    protected static String AURI(String value) {
        return '\"'+value+"\"^^xsd:anyURI";
    }

    protected static Constant AURI_C(String value) {
        return Constant.create(value,Prefixes.s_semanticWebPrefixes.get("xsd:")+"anyURI");
    }

    protected static String[] S(String... args) {
        return args;
    }
}
