diff --git a/test_data/all_data/freetest-data.ttl b/test_data/all_data/freetest-data.ttl index 8ded38859f..e87e370463 100644 --- a/test_data/all_data/freetest-data.ttl +++ b/test_data/all_data/freetest-data.ttl @@ -80,3 +80,23 @@ knora-base:valueHasString "1.5"; knora-base:hasPermissions "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser"; knora-base:attachedToUser . + + a freetest:FreeTestResourceClass ; + knora-base:attachedToUser ; + knora-base:attachedToProject ; + knora-base:hasPermissions "V knora-admin:UnknownUser|M knora-admin:ProjectMember"; + knora-base:creationDate "2019-11-29T10:00:00.673298Z"^^xsd:dateTime; + + freetest:hasIntegerProperty ; + rdfs:label "a free test resource class instance"; + knora-base:isDeleted false . + + a knora-base:IntValue; + knora-base:valueHasUUID "bXMwnrHvQH2DMjOFrGmNzg"^^xsd:string; + knora-base:isDeleted false; + knora-base:valueCreationDate "2018-05-28T15:52:03.897Z"^^xsd:dateTime; + knora-base:valueHasInteger "1"^^xsd:integer; + knora-base:valueHasOrder 0; + knora-base:valueHasString "1"; + knora-base:hasPermissions "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser"; + knora-base:attachedToUser . diff --git a/test_data/ontologies/freetest-onto.ttl b/test_data/ontologies/freetest-onto.ttl index c694bf87c1..c270700310 100644 --- a/test_data/ontologies/freetest-onto.ttl +++ b/test_data/ontologies/freetest-onto.ttl @@ -58,6 +58,22 @@ "max=-1" . +:hasIntegerProperty rdf:type owl:ObjectProperty ; + + rdfs:subPropertyOf knora-base:hasValue ; + + rdfs:label "Ganzzahl"@de , + "Nombre entier"@fr , + "Intero"@it , + "Integer"@en ; + + knora-base:objectClassConstraint knora-base:IntValue ; + + salsah-gui:guiElement salsah-gui:Spinbox ; + + salsah-gui:guiAttribute "min=0" , + "max=-1" . + :hasDecimal rdf:type owl:ObjectProperty ; @@ -121,6 +137,12 @@ owl:onProperty :hasInteger ; owl:minCardinality "0"^^xsd:nonNegativeInteger ; salsah-gui:guiOrder "4"^^xsd:nonNegativeInteger + ] , + [ + rdf:type owl:Restriction ; + owl:onProperty :hasIntegerProperty ; + owl:minCardinality "0"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "5"^^xsd:nonNegativeInteger ] ; knora-base:resourceIcon "thing.png" ; @@ -141,3 +163,19 @@ "SFT en"@en ; rdfs:comment """A comment for SFT."""@de . + + +:FreeTestResourceClass rdf:type owl:Class ; + rdfs:subClassOf knora-base:Resource , + [ + rdf:type owl:Restriction ; + owl:onProperty :hasIntegerProperty ; + owl:minCardinality "0"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger + ] ; + rdfs:label "FTRC de"@de , + "FTRC fr"@fr , + "FTRC it"@it , + "FTRC en"@en ; + + rdfs:comment """A comment for FTRC."""@de . diff --git a/webapi/scripts/expected-client-test-data.txt b/webapi/scripts/expected-client-test-data.txt index 8a03e14513..97a366db1c 100644 --- a/webapi/scripts/expected-client-test-data.txt +++ b/webapi/scripts/expected-client-test-data.txt @@ -171,6 +171,8 @@ test-data/v2/ontologies/anything-ontology.json test-data/v2/ontologies/can-do-response.json test-data/v2/ontologies/candeletecardinalities-false-request.json test-data/v2/ontologies/candeletecardinalities-false-response.json +test-data/v2/ontologies/candeletecardinalities-true-if-not-used-in-this-class-request.json +test-data/v2/ontologies/candeletecardinalities-true-if-not-used-in-this-class-response.json test-data/v2/ontologies/candeletecardinalities-true-request.json test-data/v2/ontologies/candeletecardinalities-true-response.json test-data/v2/ontologies/change-class-comment-request.json diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala index 0f093584c3..58aede63a4 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala @@ -1786,7 +1786,7 @@ class OntologyResponderV2(responderData: ResponderData) extends Responder(respon * Checks if cardinalities can be removed from a class. * * @param canDeleteCardinalitiesFromClassRequest the request to remove cardinalities. - * @return a [[ReadOntologyV2]] in the internal schema, containing the new class definition. + * @return a [[CanDoResponseV2]] indicating whether a class's cardinalities can be deleted. */ private def canDeleteCardinalitiesFromClass( canDeleteCardinalitiesFromClassRequest: CanDeleteCardinalitiesFromClassRequestV2 diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala index 519514d493..d66803ed85 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala @@ -110,10 +110,15 @@ object Cardinalities { isCardinalityDefinedOnClass(cacheData, p._1, p._2, internalClassIri, internalOntologyIri) ) - // Check if property is used in resources + // Check if property is used in resources of this class submittedPropertyToDelete: SmartIri = cardinalitiesToDelete.head._1 - propertyIsUsed: Boolean <- isPropertyUsedInResources(settings, storeManager, submittedPropertyToDelete) + propertyIsUsed: Boolean <- isPropertyUsedInResources( + settings, + storeManager, + internalClassIri, + submittedPropertyToDelete + ) // Make an update class definition in which the cardinality to delete is removed @@ -249,10 +254,15 @@ object Cardinalities { isCardinalityDefinedOnClass(cacheData, p._1, p._2, internalClassIri, internalOntologyIri) ) - // Check if property is used in resources + // Check if property is used in resources of this class submittedPropertyToDelete: SmartIri = cardinalitiesToDelete.head._1 - propertyIsUsed: Boolean <- isPropertyUsedInResources(settings, storeManager, submittedPropertyToDelete) + propertyIsUsed: Boolean <- isPropertyUsedInResources( + settings, + storeManager, + internalClassIri, + submittedPropertyToDelete + ) _ = if (propertyIsUsed) { throw BadRequestException("Property is used in data. The cardinality cannot be deleted.") } @@ -429,6 +439,7 @@ object Cardinalities { def isPropertyUsedInResources( settings: KnoraSettingsImpl, storeManager: ActorRef, + internalClassIri: SmartIri, internalPropertyIri: SmartIri )(implicit ec: ExecutionContext, timeout: Timeout): Future[Boolean] = for { @@ -437,6 +448,7 @@ object Cardinalities { .isPropertyUsed( triplestore = settings.triplestoreType, internalPropertyIri = internalPropertyIri.toString, + internalClassIri = internalClassIri.toString, ignoreKnoraConstraints = true, ignoreRdfSubjectAndObject = true ) diff --git a/webapi/src/main/twirl/org/knora/webapi/queries/sparql/v2/isPropertyUsed.scala.txt b/webapi/src/main/twirl/org/knora/webapi/queries/sparql/v2/isPropertyUsed.scala.txt index 0d7e326fb9..fc6a3ce8d9 100644 --- a/webapi/src/main/twirl/org/knora/webapi/queries/sparql/v2/isPropertyUsed.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/queries/sparql/v2/isPropertyUsed.scala.txt @@ -17,6 +17,7 @@ *@ @(triplestore: String, internalPropertyIri: IRI, + internalClassIri: IRI, ignoreKnoraConstraints: Boolean = false, ignoreRdfSubjectAndObject: Boolean = false) @@ -33,6 +34,18 @@ ASK } WHERE { BIND(IRI("@internalPropertyIri") AS ?property) + BIND(IRI("@internalClassIri") AS ?classIri) - ?s ?property ?o . + { + # select all items of type classIri with property ?property. + ?s ?property ?o . + ?s rdf:type ?classIri . + } + + UNION { + # select all items belonging to a subclass of classIri and with property ?property. + ?s ?property ?o . + ?s rdf:type ?class . + ?class rdfs:subClassOf* ?classIri . + } } diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyModels.scala b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyModels.scala index 02abe04f39..74a85d0eba 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyModels.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyModels.scala @@ -80,13 +80,23 @@ object CreatePropertyRequest { ontologyName: String, lastModificationDate: Instant, propertyName: String, - subjectClassName: String, + subjectClassName: Option[String], propertyType: PropertyValueType, label: LangString, comment: LangString ): CreatePropertyRequest = { val LocalHost_Ontology = "http://0.0.0.0:3333/ontology" val ontologyId = LocalHost_Ontology + s"/0001/$ontologyName/v2" + + val optionalSubjectClass = subjectClassName match { + case Some(subjectName) => s""" + |"knora-api:subjectType" : { + | "@id" : "$ontologyName:$subjectName" + | }, + |""".stripMargin + case None => "" + } + val value = s"""{ | "@id" : "$ontologyId", | "@type" : "owl:Ontology", @@ -97,9 +107,7 @@ object CreatePropertyRequest { | "@graph" : [ { | "@id" : "$ontologyName:$propertyName", | "@type" : "owl:ObjectProperty", - | "knora-api:subjectType" : { - | "@id" : "$ontologyName:$subjectClassName" - | }, + | $optionalSubjectClass | "knora-api:objectType" : { | "@id" : "${propertyType.value}" | }, diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala index bce2c215ee..d1c60d645f 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala @@ -2523,7 +2523,7 @@ class OntologyV2R2RSpec extends R2RSpec { ontologyName = "freetest", lastModificationDate = freetestLastModDate, propertyName = "hasBlueTestTextProp", - subjectClassName = "BlueFreeTestClass", + subjectClassName = Some("BlueFreeTestClass"), propertyType = PropertyValueType.TextValue, label = LangString("en", "blue test text property"), comment = LangString("en", "A blue test text property") @@ -2551,7 +2551,7 @@ class OntologyV2R2RSpec extends R2RSpec { ontologyName = "freetest", lastModificationDate = freetestLastModDate, propertyName = "hasBlueTestIntProp", - subjectClassName = "BlueFreeTestClass", + subjectClassName = Some("BlueFreeTestClass"), propertyType = PropertyValueType.IntValue, label = LangString("en", "blue test integer property"), comment = LangString("en", "A blue test integer property") @@ -2737,6 +2737,213 @@ class OntologyV2R2RSpec extends R2RSpec { } } + "create two classes with the same property, use one in data, and allow removal of the cardinality for the property not used in data" in { + // Create TestClassOne with no cardinalities. + val createClassRequestJsonOne = CreateClassRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + className = "TestClassOne", + label = LangString("en", "Test class number one"), + comment = LangString("en", "A test class used for testing cardinalities") + ) + .value + + Post( + "/v2/ontologies/classes", + HttpEntity(RdfMediaTypes.`application/ld+json`, createClassRequestJsonOne) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + assert(status == StatusCodes.OK, response.toString) + val responseJsonDoc = responseToJsonLDDocument(response) + + val responseAsInput: InputOntologyV2 = + InputOntologyV2.fromJsonLD(responseJsonDoc, parsingMode = TestResponseParsingModeV2).unescape + + freetestLastModDate = responseAsInput.ontologyMetadata.lastModificationDate.get + } + + // Create TestClassTwo with no cardinalities + val createClassRequestJsonTwo = CreateClassRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + className = "TestClassTwo", + label = LangString("en", "Test class number two"), + comment = LangString("en", "A test class used for testing cardinalities") + ) + .value + + Post( + "/v2/ontologies/classes", + HttpEntity(RdfMediaTypes.`application/ld+json`, createClassRequestJsonTwo) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + assert(status == StatusCodes.OK, response.toString) + val responseJsonDoc = responseToJsonLDDocument(response) + + val responseAsInput: InputOntologyV2 = + InputOntologyV2.fromJsonLD(responseJsonDoc, parsingMode = TestResponseParsingModeV2).unescape + + freetestLastModDate = responseAsInput.ontologyMetadata.lastModificationDate.get + } + + // Create a text property hasTestTextProp. + val createPropRequestJson = CreatePropertyRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + propertyName = "hasIntProp", + subjectClassName = None, + propertyType = PropertyValueType.IntValue, + label = LangString("en", "Test int property"), + comment = LangString("en", "A test int property") + ) + .value + + Post( + "/v2/ontologies/properties", + HttpEntity(RdfMediaTypes.`application/ld+json`, createPropRequestJson) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + val responseStr = responseAs[String] + assert(status == StatusCodes.OK, responseStr) + val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) + + val responseAsInput: InputOntologyV2 = + InputOntologyV2.fromJsonLD(responseJsonDoc, parsingMode = TestResponseParsingModeV2).unescape + freetestLastModDate = responseAsInput.ontologyMetadata.lastModificationDate.get + + } + + // Add cardinality hasIntProp to TestClassOne. + val addCardinalitiesRequestJsonOne = AddCardinalitiesRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + className = "TestClassOne", + restrictions = List( + Restriction( + CardinalityRestriction.MaxCardinalityOne, + onProperty = Property(ontology = "freetest", property = "hasIntProp") + ) + ) + ) + .value + + Post( + "/v2/ontologies/cardinalities", + HttpEntity(RdfMediaTypes.`application/ld+json`, addCardinalitiesRequestJsonOne) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + val responseStr = responseAs[String] + assert(status == StatusCodes.OK, responseStr) + val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) + + val responseAsInput: InputOntologyV2 = + InputOntologyV2.fromJsonLD(responseJsonDoc, parsingMode = TestResponseParsingModeV2).unescape + freetestLastModDate = responseAsInput.ontologyMetadata.lastModificationDate.get + } + + // Add cardinality hasIntProp to TestClassTwo. + val addCardinalitiesRequestJsonTwo = AddCardinalitiesRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + className = "TestClassTwo", + restrictions = List( + Restriction( + CardinalityRestriction.MaxCardinalityOne, + onProperty = Property(ontology = "freetest", property = "hasIntProp") + ) + ) + ) + .value + + Post( + "/v2/ontologies/cardinalities", + HttpEntity(RdfMediaTypes.`application/ld+json`, addCardinalitiesRequestJsonTwo) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + val responseStr = responseAs[String] + assert(status == StatusCodes.OK, responseStr) + val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) + + val responseAsInput: InputOntologyV2 = + InputOntologyV2.fromJsonLD(responseJsonDoc, parsingMode = TestResponseParsingModeV2).unescape + freetestLastModDate = responseAsInput.ontologyMetadata.lastModificationDate.get + } + + // Create a resource of #TestClassOne using #hasIntProp + val createResourceWithValues: String = + s"""{ + | "@type" : "freetest:TestClassOne", + | "freetest:hasIntProp" : { + | "@type" : "knora-api:IntValue", + | "knora-api:hasPermissions" : "CR knora-admin:Creator|V http://rdfh.ch/groups/0001/thing-searcher", + | "knora-api:intValueAsInt" : 5, + | "knora-api:valueHasComment" : "this is the number five" + | }, + | "knora-api:attachedToProject" : { + | "@id" : "http://rdfh.ch/projects/0001" + | }, + | "rdfs:label" : "test class instance", + | "@context" : { + | "rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + | "knora-api" : "http://api.knora.org/ontology/knora-api/v2#", + | "rdfs" : "http://www.w3.org/2000/01/rdf-schema#", + | "xsd" : "http://www.w3.org/2001/XMLSchema#", + | "freetest" : "${SharedOntologyTestDataADM.FREETEST_ONTOLOGY_IRI_LocalHost}#" + | } + |}""".stripMargin + + Post( + "/v2/resources", + HttpEntity(RdfMediaTypes.`application/ld+json`, createResourceWithValues) + ) ~> addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> resourcesPath ~> check { + val responseStr = responseAs[String] + assert(status == StatusCodes.OK, responseStr) + val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) + val resourceIri: IRI = + responseJsonDoc.body.requireStringWithValidation(JsonLDKeywords.ID, stringFormatter.validateAndEscapeIri) + assert(resourceIri.toSmartIri.isKnoraDataIri) + } + + // payload to ask if cardinality can be removed from TestClassTwo + val cardinalityCanBeDeletedPayload = AddCardinalitiesRequest + .make( + ontologyName = "freetest", + lastModificationDate = freetestLastModDate, + className = "TestClassTwo", + restrictions = List( + Restriction( + CardinalityRestriction.MaxCardinalityOne, + onProperty = Property(ontology = "freetest", property = "hasIntProp") + ) + ) + ) + .value + + CollectClientTestData( + "candeletecardinalities-true-if-not-used-in-this-class-request", + cardinalityCanBeDeletedPayload + ) + + // Expect cardinality can be deleted from TestClassTwo - CanDo response should return true + Post( + "/v2/ontologies/candeletecardinalities", + HttpEntity(RdfMediaTypes.`application/ld+json`, cardinalityCanBeDeletedPayload) + ) ~> + addCredentials(BasicHttpCredentials(anythingUsername, password)) ~> ontologiesPath ~> check { + val responseStr = responseAs[String] + assert(status == StatusCodes.OK, response.toString) + val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) + assert( + responseJsonDoc.body + .value(OntologyConstants.KnoraApiV2Complex.CanDo) + .asInstanceOf[JsonLDBoolean] + .value + ) + + CollectClientTestData("candeletecardinalities-true-if-not-used-in-this-class-response", responseStr) + } + } + "verify that link-property can not be deleted" in { // payload representing a link-property to test that cardinality can't be deleted @@ -2751,7 +2958,6 @@ class OntologyV2R2RSpec extends R2RSpec { ) ) ) - println(cardinalityOnLinkPropertyWhichCantBeDeletedPayload) val params = s""" @@ -2776,7 +2982,6 @@ class OntologyV2R2RSpec extends R2RSpec { | }] |} |""".stripMargin - println(params) Post( "/v2/ontologies/candeletecardinalities", @@ -2785,7 +2990,6 @@ class OntologyV2R2RSpec extends R2RSpec { BasicHttpCredentials(anythingUsername, password) ) ~> ontologiesPath ~> check { val responseStr = responseAs[String] - println(responseStr) assert(status == StatusCodes.OK, response.toString) val responseJsonDoc = JsonLDUtil.parseJsonLD(responseStr) assert(!responseJsonDoc.body.value(OntologyConstants.KnoraApiV2Complex.CanDo).asInstanceOf[JsonLDBoolean].value) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala index c22456bd52..8da423a2b8 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala @@ -7,7 +7,7 @@ package org.knora.webapi.responders.v2.ontology import akka.actor.Props import org.knora.webapi.messages.IriConversions._ -import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.{SmartIri, StringFormatter} import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.settings.KnoraDispatchers import org.knora.webapi.store.triplestore.http.HttpTriplestoreConnector @@ -41,6 +41,8 @@ class DeleteCardinalitiesFromClassSpec extends IntegrationSpec(TestContainerFuse name = "httpTriplestoreConnector" ) + val freetestOntologyIri: SmartIri = "http://0.0.0.0:3333/ontology/0001/freetest/v2".toSmartIri + override def beforeAll(): Unit = { waitForReadyTriplestore(fusekiActor) loadTestData(fusekiActor, additionalTestData) @@ -49,39 +51,54 @@ class DeleteCardinalitiesFromClassSpec extends IntegrationSpec(TestContainerFuse // use started actor in tests instead of the store manager "DeleteCardinalitiesFromClass" should { "detect that property is in use, when used in a resource" in { - val FreetestOntologyIri = "http://0.0.0.0:3333/ontology/0001/freetest/v2".toSmartIri - val internalPropertyIri = FreetestOntologyIri.makeEntityIri("hasText").toOntologySchema(InternalSchema) + val internalPropertyIri = freetestOntologyIri.makeEntityIri("hasText").toOntologySchema(InternalSchema) + val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalPropertyIri) - resF map { res => println(res); assert(res, "property is used in resource (instance of resource class)") } + val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalClassIri, internalPropertyIri) + resF map { res => println(res); assert(res, "property is used in resource (instance of that resource class)") } + } + + "detect that property is not in use, when not used in a resource" in { + val internalPropertyIri = freetestOntologyIri.makeEntityIri("hasText").toOntologySchema(InternalSchema) + val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTestResourceClass").toOntologySchema(InternalSchema) + println(s"internalPropertyIri: $internalPropertyIri") + + val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalClassIri, internalPropertyIri) + resF map { res => + println(res); assert(!res, "property is not used in resource (instance of that resource class)") + } + } + + "detect that property is not in use, when not used in a resource of that class (even when used in another class)" in { + val internalPropertyIri = freetestOntologyIri.makeEntityIri("hasIntegerProperty").toOntologySchema(InternalSchema) + val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) + println(s"internalPropertyIri: $internalPropertyIri") + + val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalClassIri, internalPropertyIri) + resF map { res => + println(res); assert(!res, "property is not used in resource (instance of that resource class)") + } } "detect that link property is in use, when used in a resource" in { - val FreetestOntologyIri = "http://0.0.0.0:3333/ontology/0001/anything/v2".toSmartIri - val internalPropertyIri = FreetestOntologyIri.makeEntityIri("isPartOfOtherThing").toOntologySchema(InternalSchema) + val anythingOntologyIri = "http://0.0.0.0:3333/ontology/0001/anything/v2".toSmartIri + val internalPropertyIri = anythingOntologyIri.makeEntityIri("isPartOfOtherThing").toOntologySchema(InternalSchema) + val internalClassIri = anythingOntologyIri.makeEntityIri("Thing").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalPropertyIri) + val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(res, "property is used in resource (instance of resource class)") } } "detect that property is in use, when used in a resource of a subclass" in { - val FreetestOntologyIri = "http://0.0.0.0:3333/ontology/0001/freetest/v2".toSmartIri - val internalPropertyIri = FreetestOntologyIri.makeEntityIri("hasDecimal").toOntologySchema(InternalSchema) + val internalPropertyIri = freetestOntologyIri.makeEntityIri("hasDecimal").toOntologySchema(InternalSchema) + val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalPropertyIri) + val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(res, "property is used in a resource of subclass") } } - "detect that property is not in use, when not used in any resource" in { - val FreetestOntologyIri = "http://0.0.0.0:3333/ontology/0001/freetest/v2".toSmartIri - val internalPropertyIri = FreetestOntologyIri.makeEntityIri("hasInteger").toOntologySchema(InternalSchema) - println(s"internalPropertyIri: $internalPropertyIri") - - val resF = Cardinalities.isPropertyUsedInResources(settings, fusekiActor, internalPropertyIri) - resF map { res => println(res); assert(!res, "property is not used") } - } } }