Skip to content

Commit

Permalink
Initial testing is complete.
Browse files Browse the repository at this point in the history
  • Loading branch information
henrietteharmse committed Nov 14, 2023
1 parent fd7ee38 commit 08d7ef3
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/org/uml2semantics/Input.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.File
case class InputParameters(classesTsv: Option[File] = None,
attributesTsv: Option[File] = None,
enumerationsTsv: Option[File] = None,
enumerationsValuesTsv: Option[File] = None,
enumerationValuesTsv: Option[File] = None,
owlOntologyFile: Option[File] = None,
ontologyIRI: String = "https://uml2semantics.com/ontology",
ontologyPrefix: String = "uml2ont:https://uml2semantics.com/ontology/",
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/org/uml2semantics/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ val argParser =
.text("A TSV file containing UML enumerations"),
opt[Option[File]]('n', "enumeration values")
.valueName("<csv-enumeration-values-file>")
.action((a, c) => c.copy(enumerationsValuesTsv = a))
.action((a, c) => c.copy(enumerationValuesTsv = a))
.validate(o =>
if (o.exists(f => f.exists()) || o.isEmpty) success
else failure(s"The file \"${o.get}\" does not exist.")
Expand Down
34 changes: 18 additions & 16 deletions src/main/scala/org/uml2semantics/model/UMLClassDiagram.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.uml2semantics.model.UMLCardinality.{>=, logger}
import sourcecode.Text

import java.io.File
import scala.:+
import scala.annotation.{tailrec, targetName}
import scala.collection.mutable

Expand Down Expand Up @@ -111,11 +112,11 @@ case class UMLClassAttributeIdentity(classNamedElement: UMLClassNamedElement,
object UMLClassAttributeIdentity:
private val logger = Logger[this.type]

private val attributeIdentityByName: mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity] =
private var attributeIdentityByName: mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity] =
mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity]()
private val attributeIdentityByIRI: mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity] =
private var attributeIdentityByIRI: mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity] =
mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity]()
private val attributeIdentityByCurie: mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity] =
private var attributeIdentityByCurie: mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity] =
mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity]()

def apply(classNamedElement: UMLClassNamedElement,
Expand Down Expand Up @@ -175,11 +176,11 @@ case class UMLEnumerationValueIdentity(enumerationNamedElement: UMLEnumerationNa
object UMLEnumerationValueIdentity:
private val logger = Logger[this.type]

private val valueIdentityByName: mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity] =
private var valueIdentityByName: mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity] =
mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity]()
private val valueIdentityByIRI: mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity] =
private var valueIdentityByIRI: mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity] =
mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity]()
private val valueIdentityByCurie: mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity] =
private var valueIdentityByCurie: mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity] =
mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity]()

def apply(enumerationNamedElement: UMLEnumerationNamedElement,
Expand Down Expand Up @@ -402,9 +403,9 @@ case class UMLClassIdentity(className: UMLClassName,
object UMLClassIdentity:
private val logger = Logger[this.type]

private val classIdentityByName: mutable.HashMap[UMLClassName, UMLClassIdentity] = mutable.HashMap[UMLClassName, UMLClassIdentity]()
private val classIdentityByIRI: mutable.HashMap[UMLClassIRI, UMLClassIdentity] = mutable.HashMap[UMLClassIRI, UMLClassIdentity]()
private val classIdentityByCurie: mutable.HashMap[UMLClassCurie, UMLClassIdentity] = mutable.HashMap[UMLClassCurie, UMLClassIdentity]()
private var classIdentityByName: mutable.HashMap[UMLClassName, UMLClassIdentity] = mutable.HashMap[UMLClassName, UMLClassIdentity]()
private var classIdentityByIRI: mutable.HashMap[UMLClassIRI, UMLClassIdentity] = mutable.HashMap[UMLClassIRI, UMLClassIdentity]()
private var classIdentityByCurie: mutable.HashMap[UMLClassCurie, UMLClassIdentity] = mutable.HashMap[UMLClassCurie, UMLClassIdentity]()

/**
*
Expand Down Expand Up @@ -481,9 +482,9 @@ case class UMLEnumerationIdentity(enumerationName: UMLEnumerationName,
object UMLEnumerationIdentity:
private val logger = Logger[this.type]

private val enumerationIdentityByName: mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity]()
private val enumerationIdentityByIRI: mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity]()
private val enumerationIdentityByCurie: mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity]()
private var enumerationIdentityByName: mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity]()
private var enumerationIdentityByIRI: mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity]()
private var enumerationIdentityByCurie: mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity]()

def apply(enumerationName: UMLEnumerationName = UMLEnumerationName(),
enumerationCurie: UMLEnumerationCurie = UMLEnumerationCurie(),
Expand Down Expand Up @@ -609,14 +610,15 @@ case class UMLEnumeration(enumerationIdentity: UMLEnumerationIdentity,
object UMLEnumeration:
private val logger = Logger[this.type]

private val enumerationsWithEnumerationValues: mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]] =
private var enumerationsWithEnumerationValues: mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]] =
mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]]()

def cache(enumerationIdentity: UMLEnumerationIdentity, enumerationValueIdentity: UMLEnumerationValueIdentity): UMLEnumerationIRI =
logger.debug(s"enumerationIdentity=$enumerationIdentity, enumerationValueIdentity=$enumerationValueIdentity ${Code.source}")
val enumerationValues: mutable.Set[UMLEnumerationValueIdentity] =
var enumerationValues: mutable.Set[UMLEnumerationValueIdentity] =
enumerationsWithEnumerationValues.getOrElse(enumerationIdentity, mutable.HashSet[UMLEnumerationValueIdentity]())
enumerationValues += enumerationValueIdentity
enumerationsWithEnumerationValues.put(enumerationIdentity, enumerationValues)
logger.trace(s"enumerationsWithEnumerationValues.size = ${enumerationsWithEnumerationValues.size}")
enumerationIdentity.enumerationIRI

def find(enumerationIdentity: UMLEnumerationIdentity): Option[mutable.Set[UMLEnumerationValueIdentity]] =
Expand All @@ -630,7 +632,7 @@ case class UMLEnumerationValue(valueIdentity: UMLEnumerationValueIdentity,
extends UMLClassDiagramElement

object UMLEnumerationValue:
private val enumerationValuesByIdentity: mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue] =
private var enumerationValuesByIdentity: mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue] =
mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue]()

def apply(valueIdentity: UMLEnumerationValueIdentity,
Expand Down
33 changes: 19 additions & 14 deletions src/main/scala/org/uml2semantics/owl/UML2OWLWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):


private def createAndAnnotateOWLClass(umlClass: UMLClass,
errorMessages: mutable.Seq[String]): OWLClass =
errorMessages: mutable.Seq[String],
hasParent: Boolean = false): OWLClass =
logger.debug(s"createAndAnnotateOWLClass: umlClass=$umlClass, errorMessages=$errorMessages ${Code.source}")
val owlClass = dataFactory.getOWLClass(umlClass.classIdentity.classIRI.iri)
if manager.addAxiom(ontology, dataFactory.getOWLSubClassOfAxiom(owlClass, dataFactory.getOWLThing)) != SUCCESSFULLY then
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} subClassOf owl:Thing"
if !hasParent then
if manager.addAxiom(ontology, dataFactory.getOWLSubClassOfAxiom(owlClass, dataFactory.getOWLThing)) != SUCCESSFULLY then
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} subClassOf owl:Thing"
createDefinitionAnnotation(owlClass, umlClass.classDefinition.definition, errorMessages)
createLabelAnnotation(owlClass, umlClass.classIdentity.classLabel, errorMessages)
owlClass
Expand Down Expand Up @@ -315,11 +317,12 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):
dataProperty


private def createAndAnnotateNamedIndividual(umlEnumerationValue: UMLEnumerationValue,
private def createAndAnnotateNamedIndividual(enumerationIdentity: UMLEnumerationIdentity,
umlEnumerationValue: UMLEnumerationValue,
errorMessages: mutable.Seq[String]): OWLNamedIndividual =
logger.debug(s"createAndAnnotateNamedIndividual: umlEnumerationValue=$umlEnumerationValue, " +
s"errorMessages=$errorMessages ${Code.source}")
val owlClass = dataFactory.getOWLClass(umlEnumerationValue.valueIdentity.valueIRI.iri)
val owlClass = dataFactory.getOWLClass(enumerationIdentity.enumerationIRI.iri)
val owlNamedIndividual = dataFactory.getOWLNamedIndividual(umlEnumerationValue.valueIdentity.valueIRI.iri)
val axiom = dataFactory.getOWLClassAssertionAxiom(owlClass, owlNamedIndividual)
if manager.addAxiom(ontology, axiom) != SUCCESSFULLY then
Expand All @@ -331,12 +334,12 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):

private def processUMLClasses: mutable.Seq[String] =
logger.info("processUMLClasses: Start")
val errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
var errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
umlClassDiagram.umlClasses.umlClasses.keySet.foreach(id => {
val umlClassOption = umlClassDiagram.umlClasses.umlClasses.get(id)
if umlClassOption.isDefined then
val umlClass = umlClassOption.get
val owlClass = createAndAnnotateOWLClass(umlClass, errorMessages)
val owlClass = createAndAnnotateOWLClass(umlClass, errorMessages, !umlClass.classParentIds.setOfParentNamedElements.isEmpty)
if umlClass.classParentIds.setOfParentNamedElements.isEmpty then
logger.trace("ParentIds is EMPTY")
else
Expand All @@ -355,7 +358,7 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):

private def processUMLClassAttributes: mutable.Seq[String] =
logger.info("processUMLClassAttributes: Start")
val errorMessages: ArrayBuffer[String] = new ArrayBuffer[String]()
var errorMessages: ArrayBuffer[String] = new ArrayBuffer[String]()
umlClassDiagram.umlClassAttributes.umlClassAttributes.keySet.foreach(id => {
val umlClassAttributeOption = umlClassDiagram.umlClassAttributes.umlClassAttributes.get(id)
if umlClassAttributeOption.isDefined then
Expand All @@ -369,34 +372,36 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):

private def processUMLEnumerations: mutable.Seq[String] =
logger.info("processUMLEnumerations: Start")
val errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
var errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
umlClassDiagram.umlEnumerations.umlEnumerations.keySet.foreach(id => {
val umlEnumerationOption = umlClassDiagram.umlEnumerations.umlEnumerations.get(id)
if umlEnumerationOption.isDefined then
if umlEnumerationOption.isDefined then {
val umlEnumeration = umlEnumerationOption.get
val owlClass = createAndAnnotateOWLClass(umlEnumeration, errorMessages)
if manager.addAxiom(ontology, dataFactory.getOWLSubClassOfAxiom(owlClass, dataFactory.getOWLThing)) != SUCCESSFULLY then
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} subClassOf owl:Thing"
val umlEnumerationValueIdentitiesOption = UMLEnumeration.find(umlEnumeration.enumerationIdentity)
if umlEnumerationValueIdentitiesOption.isDefined then
val individuals: mutable.Set[OWLIndividual] = new mutable.HashSet[OWLIndividual]()
umlEnumerationValueIdentitiesOption.get.foreach(v => {
val individual = createAndAnnotateNamedIndividual(UMLEnumerationValue.find(v).get, errorMessages)
val individual = createAndAnnotateNamedIndividual(
umlEnumeration.enumerationIdentity,
UMLEnumerationValue.find(v).get,
errorMessages)
individuals += individual
})
val owlClassExpression = dataFactory.getOWLObjectOneOf(individuals.asJava)
val owlEquivalentClassesAxiom: OWLEquivalentClassesAxiom =
dataFactory.getOWLEquivalentClassesAxiom(owlClass, owlClassExpression)
if (manager.addAxiom(ontology, owlEquivalentClassesAxiom) != SUCCESSFULLY) then
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} equivalent to ${owlClassExpression}"
}
})
logger.info("processUMLEnumerations: Done")
errorMessages
end processUMLEnumerations

def generateOWL: Either[String, ListBuffer[String]] =
logger.info("generateOWL: Start")
val errorMessages = new ListBuffer[String]()
var errorMessages = new ListBuffer[String]()
errorMessages.appendAll(processUMLClasses)
errorMessages.appendAll(processUMLClassAttributes)
errorMessages.appendAll(processUMLEnumerations)
Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/org/uml2semantics/reader/TSVReader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def parseClasses(maybeTsvFile: Option[File], ontologyPrefix: PrefixNamespace): U
implicit object TsvFormat extends TSVFormat {}

val reader = CSVReader.open(maybeTsvFile.get)
val umlClasses = mutable.Set[UMLClass]()
var umlClasses = mutable.Set[UMLClass]()

reader.allWithHeaders().foreach(m => {
logger.trace(s"m = $m")
Expand Down Expand Up @@ -70,7 +70,7 @@ def parseAttributes(maybeTsvFile: Option[File], ontologyPrefix: PrefixNamespace)
import ClassAttributesHeader.*
val logger = Logger("TsvReader: parseAttributes")
implicit object TsvFormat extends TSVFormat {}
val umlClassAttributes = mutable.Set[UMLClassAttribute]()
var umlClassAttributes = mutable.Set[UMLClassAttribute]()

if maybeTsvFile.isDefined then
val reader = CSVReader.open(maybeTsvFile.get)
Expand Down Expand Up @@ -112,7 +112,7 @@ def parseEnumerations(maybeTsvFile: Option[File], ontologyPrefix: PrefixNamespac
logger.info("Start")
implicit object TsvFormat extends TSVFormat {}

val umlEnumerations = mutable.Set[UMLEnumeration]()
var umlEnumerations = mutable.Set[UMLEnumeration]()
if maybeTsvFile.isDefined then
val reader = CSVReader.open(maybeTsvFile.get)

Expand Down Expand Up @@ -152,7 +152,7 @@ def parseEnumerationValues(maybeTsvFile: Option[File], ontologyPrefix: PrefixNam

if maybeTsvFile.isDefined then {
val reader = CSVReader.open(maybeTsvFile.get)
val umlEnumerationValues = mutable.Set[UMLEnumerationValue]()
var umlEnumerationValues = mutable.Set[UMLEnumerationValue]()

logger.info("Start")
reader.allWithHeaders().foreach(m => {
Expand Down Expand Up @@ -198,7 +198,7 @@ def parseUMLClassDiagram(input: InputParameters): UMLClassDiagram =
parseClasses(input.classesTsv, PrefixNamespace(input.ontologyPrefix)),
parseAttributes(input.attributesTsv, PrefixNamespace(input.ontologyPrefix)),
parseEnumerations(input.enumerationsTsv, PrefixNamespace(input.ontologyPrefix)),
parseEnumerationValues(input.enumerationsValuesTsv, PrefixNamespace(input.ontologyPrefix)))
parseEnumerationValues(input.enumerationValuesTsv, PrefixNamespace(input.ontologyPrefix)))



56 changes: 54 additions & 2 deletions src/test/resources/employer.rdf
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@

<owl:Class rdf:about="http://uml2semantics.org/examples/employer#Employee">
<rdfs:subClassOf rdf:resource="http://uml2semantics.org/examples/employer#Person"/>
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://uml2semantics.org/examples/employer#Employee/employedBy"/>
Expand All @@ -124,7 +123,6 @@

<owl:Class rdf:about="http://uml2semantics.org/examples/employer#Employer">
<rdfs:subClassOf rdf:resource="http://uml2semantics.org/examples/employer#Person"/>
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://uml2semantics.org/examples/employer#Employer/employes"/>
Expand Down Expand Up @@ -172,10 +170,64 @@


<owl:Class rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule">
<owl:equivalentClass>
<owl:Class>
<owl:oneOf rdf:parseType="Collection">
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#Daily"/>
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#Monthly"/>
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule/Weekly"/>
</owl:oneOf>
</owl:Class>
</owl:equivalentClass>
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:comment>Defines the frequency of payments</rdfs:comment>
<rdfs:label>PaymentSchedule</rdfs:label>
</owl:Class>



<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Individuals
//
///////////////////////////////////////////////////////////////////////////////////////
-->





<!-- http://uml2semantics.org/examples/employer#Daily -->


<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#Daily">
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
<rdfs:comment>Employee gets paid at the end of each day</rdfs:comment>
<rdfs:label>Daily</rdfs:label>
</owl:NamedIndividual>



<!-- http://uml2semantics.org/examples/employer#Monthly -->


<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#Monthly">
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
<rdfs:comment>Employee gets paid at the last day of the month</rdfs:comment>
<rdfs:label>Monthly</rdfs:label>
</owl:NamedIndividual>



<!-- http://uml2semantics.org/examples/employer#SalarySchedule/Weekly -->


<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule/Weekly">
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
<rdfs:comment>Employee gets paid at the end of each week on a Friday</rdfs:comment>
<rdfs:label>Weekly</rdfs:label>
</owl:NamedIndividual>
</rdf:RDF>


Expand Down

0 comments on commit 08d7ef3

Please sign in to comment.