Skip to content

Commit 08d7ef3

Browse files
Initial testing is complete.
1 parent fd7ee38 commit 08d7ef3

File tree

6 files changed

+98
-39
lines changed

6 files changed

+98
-39
lines changed

src/main/scala/org/uml2semantics/Input.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import java.io.File
77
case class InputParameters(classesTsv: Option[File] = None,
88
attributesTsv: Option[File] = None,
99
enumerationsTsv: Option[File] = None,
10-
enumerationsValuesTsv: Option[File] = None,
10+
enumerationValuesTsv: Option[File] = None,
1111
owlOntologyFile: Option[File] = None,
1212
ontologyIRI: String = "https://uml2semantics.com/ontology",
1313
ontologyPrefix: String = "uml2ont:https://uml2semantics.com/ontology/",

src/main/scala/org/uml2semantics/Main.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ val argParser =
4444
.text("A TSV file containing UML enumerations"),
4545
opt[Option[File]]('n', "enumeration values")
4646
.valueName("<csv-enumeration-values-file>")
47-
.action((a, c) => c.copy(enumerationsValuesTsv = a))
47+
.action((a, c) => c.copy(enumerationValuesTsv = a))
4848
.validate(o =>
4949
if (o.exists(f => f.exists()) || o.isEmpty) success
5050
else failure(s"The file \"${o.get}\" does not exist.")

src/main/scala/org/uml2semantics/model/UMLClassDiagram.scala

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.uml2semantics.model.UMLCardinality.{>=, logger}
66
import sourcecode.Text
77

88
import java.io.File
9+
import scala.:+
910
import scala.annotation.{tailrec, targetName}
1011
import scala.collection.mutable
1112

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

114-
private val attributeIdentityByName: mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity] =
115+
private var attributeIdentityByName: mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity] =
115116
mutable.HashMap[UMLClassAttributeName, UMLClassAttributeIdentity]()
116-
private val attributeIdentityByIRI: mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity] =
117+
private var attributeIdentityByIRI: mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity] =
117118
mutable.HashMap[UMLClassAttributeIRI, UMLClassAttributeIdentity]()
118-
private val attributeIdentityByCurie: mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity] =
119+
private var attributeIdentityByCurie: mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity] =
119120
mutable.HashMap[UMLClassAttributeCurie, UMLClassAttributeIdentity]()
120121

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

178-
private val valueIdentityByName: mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity] =
179+
private var valueIdentityByName: mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity] =
179180
mutable.HashMap[UMLEnumerationValueName, UMLEnumerationValueIdentity]()
180-
private val valueIdentityByIRI: mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity] =
181+
private var valueIdentityByIRI: mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity] =
181182
mutable.HashMap[UMLEnumerationValueIRI, UMLEnumerationValueIdentity]()
182-
private val valueIdentityByCurie: mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity] =
183+
private var valueIdentityByCurie: mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity] =
183184
mutable.HashMap[UMLEnumerationValueCurie, UMLEnumerationValueIdentity]()
184185

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

405-
private val classIdentityByName: mutable.HashMap[UMLClassName, UMLClassIdentity] = mutable.HashMap[UMLClassName, UMLClassIdentity]()
406-
private val classIdentityByIRI: mutable.HashMap[UMLClassIRI, UMLClassIdentity] = mutable.HashMap[UMLClassIRI, UMLClassIdentity]()
407-
private val classIdentityByCurie: mutable.HashMap[UMLClassCurie, UMLClassIdentity] = mutable.HashMap[UMLClassCurie, UMLClassIdentity]()
406+
private var classIdentityByName: mutable.HashMap[UMLClassName, UMLClassIdentity] = mutable.HashMap[UMLClassName, UMLClassIdentity]()
407+
private var classIdentityByIRI: mutable.HashMap[UMLClassIRI, UMLClassIdentity] = mutable.HashMap[UMLClassIRI, UMLClassIdentity]()
408+
private var classIdentityByCurie: mutable.HashMap[UMLClassCurie, UMLClassIdentity] = mutable.HashMap[UMLClassCurie, UMLClassIdentity]()
408409

409410
/**
410411
*
@@ -481,9 +482,9 @@ case class UMLEnumerationIdentity(enumerationName: UMLEnumerationName,
481482
object UMLEnumerationIdentity:
482483
private val logger = Logger[this.type]
483484

484-
private val enumerationIdentityByName: mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity]()
485-
private val enumerationIdentityByIRI: mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity]()
486-
private val enumerationIdentityByCurie: mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity]()
485+
private var enumerationIdentityByName: mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationName, UMLEnumerationIdentity]()
486+
private var enumerationIdentityByIRI: mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationIRI, UMLEnumerationIdentity]()
487+
private var enumerationIdentityByCurie: mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity] = mutable.HashMap[UMLEnumerationCurie, UMLEnumerationIdentity]()
487488

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

612-
private val enumerationsWithEnumerationValues: mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]] =
613+
private var enumerationsWithEnumerationValues: mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]] =
613614
mutable.HashMap[UMLEnumerationIdentity, mutable.Set[UMLEnumerationValueIdentity]]()
614-
615615
def cache(enumerationIdentity: UMLEnumerationIdentity, enumerationValueIdentity: UMLEnumerationValueIdentity): UMLEnumerationIRI =
616616
logger.debug(s"enumerationIdentity=$enumerationIdentity, enumerationValueIdentity=$enumerationValueIdentity ${Code.source}")
617-
val enumerationValues: mutable.Set[UMLEnumerationValueIdentity] =
617+
var enumerationValues: mutable.Set[UMLEnumerationValueIdentity] =
618618
enumerationsWithEnumerationValues.getOrElse(enumerationIdentity, mutable.HashSet[UMLEnumerationValueIdentity]())
619619
enumerationValues += enumerationValueIdentity
620+
enumerationsWithEnumerationValues.put(enumerationIdentity, enumerationValues)
621+
logger.trace(s"enumerationsWithEnumerationValues.size = ${enumerationsWithEnumerationValues.size}")
620622
enumerationIdentity.enumerationIRI
621623

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

632634
object UMLEnumerationValue:
633-
private val enumerationValuesByIdentity: mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue] =
635+
private var enumerationValuesByIdentity: mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue] =
634636
mutable.HashMap[UMLEnumerationValueIdentity, UMLEnumerationValue]()
635637

636638
def apply(valueIdentity: UMLEnumerationValueIdentity,

src/main/scala/org/uml2semantics/owl/UML2OWLWriter.scala

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):
4747

4848

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

317319

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

332335
private def processUMLClasses: mutable.Seq[String] =
333336
logger.info("processUMLClasses: Start")
334-
val errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
337+
var errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
335338
umlClassDiagram.umlClasses.umlClasses.keySet.foreach(id => {
336339
val umlClassOption = umlClassDiagram.umlClasses.umlClasses.get(id)
337340
if umlClassOption.isDefined then
338341
val umlClass = umlClassOption.get
339-
val owlClass = createAndAnnotateOWLClass(umlClass, errorMessages)
342+
val owlClass = createAndAnnotateOWLClass(umlClass, errorMessages, !umlClass.classParentIds.setOfParentNamedElements.isEmpty)
340343
if umlClass.classParentIds.setOfParentNamedElements.isEmpty then
341344
logger.trace("ParentIds is EMPTY")
342345
else
@@ -355,7 +358,7 @@ class UML2OWLWriter(val umlClassDiagram: UMLClassDiagram):
355358

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

370373
private def processUMLEnumerations: mutable.Seq[String] =
371374
logger.info("processUMLEnumerations: Start")
372-
val errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
375+
var errorMessages: mutable.Seq[String] = new ArrayBuffer[String]()
373376
umlClassDiagram.umlEnumerations.umlEnumerations.keySet.foreach(id => {
374377
val umlEnumerationOption = umlClassDiagram.umlEnumerations.umlEnumerations.get(id)
375-
if umlEnumerationOption.isDefined then
378+
if umlEnumerationOption.isDefined then {
376379
val umlEnumeration = umlEnumerationOption.get
377380
val owlClass = createAndAnnotateOWLClass(umlEnumeration, errorMessages)
378-
if manager.addAxiom(ontology, dataFactory.getOWLSubClassOfAxiom(owlClass, dataFactory.getOWLThing)) != SUCCESSFULLY then
379-
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} subClassOf owl:Thing"
380381
val umlEnumerationValueIdentitiesOption = UMLEnumeration.find(umlEnumeration.enumerationIdentity)
381382
if umlEnumerationValueIdentitiesOption.isDefined then
382383
val individuals: mutable.Set[OWLIndividual] = new mutable.HashSet[OWLIndividual]()
383384
umlEnumerationValueIdentitiesOption.get.foreach(v => {
384-
val individual = createAndAnnotateNamedIndividual(UMLEnumerationValue.find(v).get, errorMessages)
385+
val individual = createAndAnnotateNamedIndividual(
386+
umlEnumeration.enumerationIdentity,
387+
UMLEnumerationValue.find(v).get,
388+
errorMessages)
385389
individuals += individual
386390
})
387391
val owlClassExpression = dataFactory.getOWLObjectOneOf(individuals.asJava)
388392
val owlEquivalentClassesAxiom: OWLEquivalentClassesAxiom =
389393
dataFactory.getOWLEquivalentClassesAxiom(owlClass, owlClassExpression)
390394
if (manager.addAxiom(ontology, owlEquivalentClassesAxiom) != SUCCESSFULLY) then
391395
errorMessages :+ s"Could not add axiom ${owlClass.getIRI} equivalent to ${owlClassExpression}"
396+
}
392397
})
393398
logger.info("processUMLEnumerations: Done")
394399
errorMessages
395400
end processUMLEnumerations
396401

397402
def generateOWL: Either[String, ListBuffer[String]] =
398403
logger.info("generateOWL: Start")
399-
val errorMessages = new ListBuffer[String]()
404+
var errorMessages = new ListBuffer[String]()
400405
errorMessages.appendAll(processUMLClasses)
401406
errorMessages.appendAll(processUMLClassAttributes)
402407
errorMessages.appendAll(processUMLEnumerations)

src/main/scala/org/uml2semantics/reader/TSVReader.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def parseClasses(maybeTsvFile: Option[File], ontologyPrefix: PrefixNamespace): U
2828
implicit object TsvFormat extends TSVFormat {}
2929

3030
val reader = CSVReader.open(maybeTsvFile.get)
31-
val umlClasses = mutable.Set[UMLClass]()
31+
var umlClasses = mutable.Set[UMLClass]()
3232

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

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

115-
val umlEnumerations = mutable.Set[UMLEnumeration]()
115+
var umlEnumerations = mutable.Set[UMLEnumeration]()
116116
if maybeTsvFile.isDefined then
117117
val reader = CSVReader.open(maybeTsvFile.get)
118118

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

153153
if maybeTsvFile.isDefined then {
154154
val reader = CSVReader.open(maybeTsvFile.get)
155-
val umlEnumerationValues = mutable.Set[UMLEnumerationValue]()
155+
var umlEnumerationValues = mutable.Set[UMLEnumerationValue]()
156156

157157
logger.info("Start")
158158
reader.allWithHeaders().foreach(m => {
@@ -198,7 +198,7 @@ def parseUMLClassDiagram(input: InputParameters): UMLClassDiagram =
198198
parseClasses(input.classesTsv, PrefixNamespace(input.ontologyPrefix)),
199199
parseAttributes(input.attributesTsv, PrefixNamespace(input.ontologyPrefix)),
200200
parseEnumerations(input.enumerationsTsv, PrefixNamespace(input.ontologyPrefix)),
201-
parseEnumerationValues(input.enumerationsValuesTsv, PrefixNamespace(input.ontologyPrefix)))
201+
parseEnumerationValues(input.enumerationValuesTsv, PrefixNamespace(input.ontologyPrefix)))
202202

203203

204204

src/test/resources/employer.rdf

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@
106106

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

125124
<owl:Class rdf:about="http://uml2semantics.org/examples/employer#Employer">
126125
<rdfs:subClassOf rdf:resource="http://uml2semantics.org/examples/employer#Person"/>
127-
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
128126
<rdfs:subClassOf>
129127
<owl:Restriction>
130128
<owl:onProperty rdf:resource="http://uml2semantics.org/examples/employer#Employer/employes"/>
@@ -172,10 +170,64 @@
172170

173171

174172
<owl:Class rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule">
173+
<owl:equivalentClass>
174+
<owl:Class>
175+
<owl:oneOf rdf:parseType="Collection">
176+
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#Daily"/>
177+
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#Monthly"/>
178+
<rdf:Description rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule/Weekly"/>
179+
</owl:oneOf>
180+
</owl:Class>
181+
</owl:equivalentClass>
175182
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
176183
<rdfs:comment>Defines the frequency of payments</rdfs:comment>
177184
<rdfs:label>PaymentSchedule</rdfs:label>
178185
</owl:Class>
186+
187+
188+
189+
<!--
190+
///////////////////////////////////////////////////////////////////////////////////////
191+
//
192+
// Individuals
193+
//
194+
///////////////////////////////////////////////////////////////////////////////////////
195+
-->
196+
197+
198+
199+
200+
201+
<!-- http://uml2semantics.org/examples/employer#Daily -->
202+
203+
204+
<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#Daily">
205+
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
206+
<rdfs:comment>Employee gets paid at the end of each day</rdfs:comment>
207+
<rdfs:label>Daily</rdfs:label>
208+
</owl:NamedIndividual>
209+
210+
211+
212+
<!-- http://uml2semantics.org/examples/employer#Monthly -->
213+
214+
215+
<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#Monthly">
216+
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
217+
<rdfs:comment>Employee gets paid at the last day of the month</rdfs:comment>
218+
<rdfs:label>Monthly</rdfs:label>
219+
</owl:NamedIndividual>
220+
221+
222+
223+
<!-- http://uml2semantics.org/examples/employer#SalarySchedule/Weekly -->
224+
225+
226+
<owl:NamedIndividual rdf:about="http://uml2semantics.org/examples/employer#SalarySchedule/Weekly">
227+
<rdf:type rdf:resource="http://uml2semantics.org/examples/employer#SalarySchedule"/>
228+
<rdfs:comment>Employee gets paid at the end of each week on a Friday</rdfs:comment>
229+
<rdfs:label>Weekly</rdfs:label>
230+
</owl:NamedIndividual>
179231
</rdf:RDF>
180232

181233

0 commit comments

Comments
 (0)