package OWL2generator;

/**
 *  <b><code>SharedUtils</code></b> class offers a collection of utility methods 
 *  for OWL/XML ontology generation within the framework. It doesn't directly
 *  belong to any specific class but functions as a helper.
 *  <code>SharedUtils</code> acts as a utility class, providing reusable
 *  functionalities for building the OWL ontology structure. It
 *  helps in creating declarations for classes, individuals, properties,
 *  and their relationships within the ontology based on text file
 *  configurations.
 *  <p>
 *  <b>Key Functionalities</b>:
 *  <p>
 *  Generates OWL code snippets for various ontology elements:
 *  <p>
 *  <ul>
 *  <li>Classes (<code>declareClass</code>, <code>declareSubClass</code>)
 *  <li>Individuals (<code>genIndividual</code>) with their declarations, class
 *  assertions, and annotations
 *  <li>Object properties (<code>genObjPropDecl</code>) with potential
 *  super-properties and annotations
 *  <li>Sub-object property relationships (<code>genSubObjProp</code>)
 *  <li>Inverse object properties (<code>genInverseObjProps</code>)
 *  <li>OWL class individual triplets (<code>genTriplet</code>)
 *  </ul>
 *  <p>
 *  Formats class names with a project-wide IRI prefix (<code>formatClassName</code>)
 *  <p>
 *  Generates annotation assertions (<code>genAnnotationAssertion</code>)
 *  <p>
 *  Defines constants like <code>IRI</code> (Internationalized Resource Identifier)
 *  <p>
 *  <b>Additional Notes</b>:
 *  <p>
 *  The class utilizes a constant IRI (Internationalized Resource Identifier)
 *  to serve as a prefix for all identifiers within the generated ontology.
 *  <p>
 *  A boolean flag <code>GENERATE_HEADER</code> controls whether comments are included in
 *  the generated XML for better human readability during development
 *  (currently disabled).
 *  <p>
 *  Some methods (like <code>genObjPropDomainAndRange</code>) are currently not used,
 *  suggesting potential future extensibility for associating domain and
 *  range OWL classes with object properties.
 *  <p>
 *  <b>Environment:</b> 
 *  <ul>
 *  <li>    IDE:              Eclipse IDE for Java Developers
 *  <li>    Version:          2021-12 (4.22.0)
 *  <li>    Build id:         20211202-1639
 *  <li>    HW Model Name:    iMac, MacOS Monterey, 12.5.1
 *  <li>    Processor Name:   Quad-Core Intel Core i5
 *  <li>    Processor Speed:  3.2 GHz
 *  <li>    Memory:           32 GB 1867 MHz DDR3
 *  <li>    Disk:             APPLE SSD SM0256G    
 *  <li>    Serial:           DGKRC080GG7V
 *  </ul>
 *  @version 1-001
 *  @since   2024/05/24
 *  @author  Edit Hlaszny (https://www.edithlaszny.eu/ edithlaszny@gmail.com)
 */

public class SharedUtils 
{
	/**
	 *  Some methods generate OWL-fragments, and for testing purposes it can be useful 
	 *  to display their parameters as XML-comments
	 */
    private final static boolean GENERATE_HEADER = false  ;

	/**
	 *  Internationalized Resource Identifiers (IRIs) are a protocol element, 
	 *  a complement to URIs [RFC2396], and is used as prefix to each identifier.
	 *  The class members are project-wide constant. 
	 */
    private       String  IRI           = "https://www.edithlaszny.eu/ontology/OWLschemafy/data/" ;
    private final static String  XMLNS_XSD_IRI = "http://www.w3.org/2001/XMLSchema" ;

	/**
	 *  W3C/defined separator between IRI and unique variable name
	 */
    private final static String  SEPARATOR = "#" ;

    SharedUtils(String baseURI)
    {
        this.IRI = baseURI ;
        
    }   //  end of constructor()
    
    /**
     *  Assert a data property: it's a three fold task:
     *  1) assigns it to a named individual
     *  2) define its type
     *  3) also assigns a value
     * 
     *  @param dataPropertyName
     *  @param individualName
     *  @param dataPropertyType (each element of the xlmns:xsd schema can be used)
     *  @param dataPropertyValue
     *  
     *  @return XML code snippet
     */
    public String assertDataProperty(String dataPropertyName,
                                     String individualName,
                                     String dataPropertyType,
                                     String dataPropertyValue
                                    )
    {
        return new StringBuilder()
            .append("    <DataPropertyAssertion>\n") 
            .append("        <DataProperty IRI=\""    + IRI + SEPARATOR     
                                                      + dataPropertyName   + "\"/>\n")
            .append("        <NamedIndividual IRI=\"" + IRI + SEPARATOR 
                                                      + individualName + "\"/>\n")
            .append("        <Literal datatypeIRI=\"" + XMLNS_XSD_IRI  + SEPARATOR 
                                                      + dataPropertyType + "\">" 
                                                      + dataPropertyValue 
                                                      + "</Literal>\n")
            .append("    </DataPropertyAssertion>\n")
            .toString();

    }   //  end of method assertDataProperty()
    
	/**
	 *  Declares an OWL class according to OWL2 XML Syntax
	 *  
	 *  @param className Name of the OWL class
	 *  
	 *  @return XML code snippet
	 */
    public String declareClass(String className) 
    {
        return new StringBuilder()
        .append("    <Declaration>\n")
        .append("        <Class IRI=\"" + IRI + SEPARATOR + className + "\"/>\n")
        .append("    </Declaration>\n")
        .toString();
        
    }   //  end of method declareClass()

	/**
	 *  Declares OWL subclass according to OWL2 XML Syntax
	 *  
	 *  @param superClass Name of the OWL superclass
	 *  @param suvClass Name of the OWL subclass
	 *  
	 *  @return XML code snippet	 
	 */
    public String declareSubClass(String superClass, 
    		                      String subClass) 
    {
        return new StringBuilder()
        .append("    <SubClassOf>\n")
        .append("        <Class IRI=\"" + IRI + SEPARATOR + subClass   + "\"/>\n")
        .append("        <Class IRI=\"" + IRI + SEPARATOR + superClass + "\"/>\n")
        .append("    </SubClassOf>\n")
        .toString();
    	
    }   //  end of method declareSubClass()
    
    /**
     *  Declare a data property 
     *  (1) per name
     *  (2) as a sub data property
     *  (3) associate an annotation
     *  
     *  @param dataPropertyName
     *  @param superDataPropertyName
     *  @param annotation
     *  
     *  @return XML code snippet
     */
    public String declareDataProperty(String dataPropertyName,
                                      String superDataPropertyName,
                                      String annotation)
    {
        return new StringBuilder()
        .append("    <Declaration>\n")
        .append("        <DataProperty IRI=\"" + IRI + SEPARATOR + dataPropertyName + "\"/>\n")
        .append("    </Declaration>\n")
        
        .append("    <SubDataPropertyOf>\n")
        .append("        <DataProperty IRI=\"" + IRI + SEPARATOR + dataPropertyName + "\"/>\n")
        .append("        <DataProperty abbreviatedIRI=\""   + superDataPropertyName + "\"/>\n")
        .append("    </SubDataPropertyOf>\n")
        
        .append(genAnnotationAssertion(dataPropertyName, annotation))
        .toString();
        
    }   //  end of method declareDataProperty()
    
	/**
	 *  Adds project-wide IRI to an OWL class name
	 *  
	 *  @param className OWL class name to be formatted
	 *  
	 *  @return XML code snippet	 
	 */
    String formatClassName(String className) 
    {
        return new StringBuilder()
        .append("    <Class IRI=\"" + IRI + SEPARATOR + className + "\"/>\n")
        .toString();

    }   //  end of method formatClassName()

	/**
	 *  Declaring property annotation assertion
	 *  
	 *  @param propertyName  name of an OWL property
	 *  @param annotation    annotation as literal text 
	 *  
	 *  @return XML code snippet	 
	 */
    public String genAnnotationAssertion(String propertyName,
                                         String annotation
                                        )
    {
        return  "    <AnnotationAssertion>\n" +
                "        <AnnotationProperty abbreviatedIRI=\"rdfs:comment\"/>\n" +
                "        <IRI>"               + IRI + SEPARATOR   +
                         propertyName         + "</IRI>\n"        +
                "        <Literal>" + annotation + "</Literal>\n" +
                "    </AnnotationAssertion>\n" ;
    	
    }   //  end of method genAnnotationAssertion()
    
	/**
	 *  Generate OWL class individual: consists of three steps:
	 *  <br />
	 *  1) declaring the individual
	 *  <br />
	 *  2) associating it to its OWL class
	 *  <br />
	 *  3) adding annotation to the individual
	 *  
	 *  @param className         name of the OWL class
	 *  @param individualName    name of the individual as instance of the OWL class 
	 *  @param annotation        annotation as literal text associated to the individual
	 *  
	 *  @return XML code snippet	 
	 */
    String genIndividual(String className, 
                         String individualName,
                         String annotation
                        ) 
    {
        String  hdr = "" ;
        
        if (GENERATE_HEADER)
        {
            hdr = "    <!--  generated named individual : " + individualName + "\n" +
                  "                    associated class : " + className      + "\n" +
                  "                 asserted annotation : " + annotation     + "\n" +
                  "      -->\n" ;
        }
            
        return  hdr +           
                genIndividualDeclaration(                   individualName            ) +
                genIndividualClassAssertion(     className, individualName            ) +
                genIndividualAnnotationAssertion(className, individualName, annotation) ;

    }   //  end of method genIndividual()
    
	/**
	 *  Associate assertion to an OWL class individual
	 *  
	 *  @param className         name of the OWL class
	 *  @param individualName    name of the individual as instance of the OWL class 
	 *  @param annotation        annotation as literal text associated to the individual
	 *  
	 *  @return XML code snippet	 
	 */
    String genIndividualAnnotationAssertion(String className, 
                                            String individualName,
                                            String annotation
                                           ) 
    {
        return  "    <AnnotationAssertion>\n" +
                "        <AnnotationProperty abbreviatedIRI=\"rdfs:comment\"/>\n" +
                "        <IRI>"               + IRI + SEPARATOR      +
                         individualName             + "</IRI>\n"     +
                "        <Literal>" + annotation    + "</Literal>\n" +
                "    </AnnotationAssertion>\n" ;

    }   //  end of method genIndividualAnnotationAssertion()

	/**
	 *  Associate an individual to its OWL class 
	 *  
	 *  @param className         name of the OWL class
	 *  @param individualName    name of the individual as instance of the OWL class 
	 *  
	 *  @return XML code snippet	 
	 */
    String genIndividualClassAssertion(String className, 
                                       String individualName
                                      ) 
    {
        return  "    <ClassAssertion>\n"          +
                "        <Class IRI=\""           + IRI + SEPARATOR  +
                                className         + "\"/>\n"         +
                "        <NamedIndividual IRI=\"" + IRI + SEPARATOR  +
                                 individualName           + "\"/>\n" +
                "    </ClassAssertion>\n" ;

    }   //  end of method genIndividualClassAssertion()


	/**
	 *  Declares an individual  
	 *  
	 *  @param individualName    name of the individual 
	 *  
	 *  @return XML code snippet	 
	 */
    String genIndividualDeclaration(String individualName
                                   ) 
    {
        return  "    <Declaration>\n" +
                "        <NamedIndividual IRI=\"" + IRI       + SEPARATOR +
                         individualName           + "\"/>\n"  +
                "    </Declaration>\n" ;

    }   //  end of method genIndividualDeclaration()
    
	/**
	 *  Declares two object properties as inverses  
	 *  
	 *  @param objPropName_1    the first object property name 
	 *  @param objPropName_2    the second one 
	 *  
	 *  @return XML code snippet	 
	 */
    String genInverseObjProps(String objPropName_1,
                              String objPropName_2
                             )
    {
        String  hdr = "" ;
        
        if (GENERATE_HEADER)
        {
            hdr = "    <!--  defining inverse object properties: " + objPropName_1 + 
            		                                         " - " + objPropName_2 + "\n" +
                  "      -->\n" ;
        }
            
        return  hdr +           
                "    <InverseObjectProperties>\n" +
                "        <ObjectProperty IRI=\""  + IRI       + SEPARATOR +
                         objPropName_1            + "\"/>\n"  +
                "        <ObjectProperty IRI=\""  + IRI       + SEPARATOR +
                         objPropName_2            + "\"/>\n"  +
                "    </InverseObjectProperties>\n" ;

    }   //  end of method genInverseObjProps()


    /**
     *  Declaring object properties 
     */
    
	/**
	 *  Declares object property, consists of three steps:
	 *  <br />
	 *  1) declaring the object property
	 *  <br />
	 *  2) associating it to its super object property
	 *  <br />
	 *  3) adding annotation to the object property
	 *  
	 *  @param objPropName         name of the object property
	 *  @param superObjPropName    name of the super object property 
	 *  @param annotation          annotation as literal text associated to the object property
	 *  
	 *  @return XML code snippet	 
	 */
     String genObjPropDecl(String objPropName,
    		               String superObjPropName,
    		               String annotation
                          )
    {
        String  hdr = "" ;
        
        if (GENERATE_HEADER)
        {
            hdr = "    <!--  declaring object property: " + objPropName     + "\n" +
                  "                         annotation: " + annotation      + "\n" +
                  "      -->\n" ;
        }
        
        String declare = "    <Declaration>\n"   +
                         "        <ObjectProperty IRI=\"" + IRI       + SEPARATOR +
                                  objPropName             + "\"/>\n"  +
                         "    </Declaration>\n" ;
        
        
        String setSupObjProp =  genSubObjProp(objPropName, superObjPropName) ;
               
        String setAnnotation = genAnnotationAssertion(objPropName,
                                                      annotation
                                                     ) ;
        
        return hdr + declare + setSupObjProp + setAnnotation  ;

    }   //  end of method genObjPropDecl()

    /**
     *  Associating domain- and range classes to an object property
     *  (used only if OWL classes are the domains and ranges,- currently not used)
     *  
	 *  @param objPropName         name of the object property
	 *  @param domainClassName     name of the domain OWL class class 
	 *  @param rangeClassName      name of the range  OWL class class 
	 *  
	 *  @return XML code snippet	 
     */
    String genObjPropDomainAndRange(String objPropName,
                                    String domainClassName,
                                    String rangeClassName
                                   )
    {
        return  "    <ObjectPropertyDomain>\n"   +
                "        <ObjectProperty IRI=\"" + IRI       + SEPARATOR +
                         objPropName             + "\"/>\n"  +
                "        <Class IRI=\""          + IRI       + SEPARATOR +
                         domainClassName         + "\"/>\n"  +
                "    </ObjectPropertyDomain>\n"  +
                "    <ObjectPropertyRange>\n"    +
                "        <ObjectProperty IRI=\"" + IRI       + SEPARATOR +
                         objPropName             + "\"/>\n"  +
                "        <Class IRI=\""          + IRI       + SEPARATOR +
                         rangeClassName          + "\"/>\n"  +
                "    </ObjectPropertyRange>\n" ;

    }   //  end of method genObjPropDomainAndRange()

    /**
     *  Associating a sub object property to its super object property
     *  
	 *  @param subObjPropName      name of the sub object property
	 *  @param superObjPropName    name of the super object property 
	 *  
	 *  @return XML code snippet	 
     */
    String genSubObjProp(String subObjPropName,
                         String superObjPropName
                        )
    {
        String  hdr = "" ;
        
        if (GENERATE_HEADER)
        {
            hdr = "    <!--  declaring   sub object properties " + subObjPropName   + "\n" +
                  "                 to super object properties " + superObjPropName + "\n" +
                  "      -->\n" ;
        }
            
        String currentIRI = "IRI=\"" + IRI + SEPARATOR + superObjPropName + "\"/>\n" ;
        
        if (superObjPropName.equals("owl:topObjectProperty"))
        {
            currentIRI = "abbreviatedIRI=\"owl:topObjectProperty\"/>" ;
        }
        
        return  hdr +           
                "    <SubObjectPropertyOf>\n" +
                "        <ObjectProperty IRI=\"" + IRI        + SEPARATOR +
                         subObjPropName          + "\"/>\n"   +
                "        <ObjectProperty "       + currentIRI + "\n" +
                "    </SubObjectPropertyOf>\n" ;
        
    }   //  end of method genSubObjProp()


    /**
     *  Defining semantical triplet. A triple consists of three components: 
     *  a subject, a predicate, and an object. The predicate describes the 
     *  relationship between two nodes, one the subject and the other the object. 
     *  Each node can be both a subject and object simultaneously if it’s used in
     *  more than one triple.
     *
	 *  @param namedIndividual_1      the subject as OWL class individual
	 *  @param objPropName            the predicate as OWL object property
	 *  @param namedIndividual_2      the object as OWL class individual 
	 *  
	 *  @return XML code snippet
	 */
    String genTriplet(String namedIndividual_1,  //  subject
                      String objPropName,        //  predicate
                      String namedIndividual_2   //  object
                     )
    {
        String  hdr = "" ;
        
        if (GENERATE_HEADER)
        {
            hdr = "    <!--  defininig triplet:  subject " + namedIndividual_1 + "\n" + 
                  "                            predicate " + objPropName       + "\n" +
                  "                               object " + namedIndividual_2 + "\n" +
                  "      -->\n" ;
        }
            
        return  hdr +           
                "    <ObjectPropertyAssertion>\n"  +
                "        <ObjectProperty  IRI=\""  + IRI       + SEPARATOR +
                         objPropName               + "\"/>\n"  +
                "        <NamedIndividual IRI=\""  + IRI       + SEPARATOR +
                         namedIndividual_1         + "\"/>\n"  +
                "        <NamedIndividual IRI=\""  + IRI       + SEPARATOR +
                         namedIndividual_2         + "\"/>\n"  +
                "    </ObjectPropertyAssertion>\n" ;
        
    }   //  end of method genTriplet()
    
}   //  end of class SharedUtils
