Skip to content

Commit

Permalink
Update ontology entities (part 2) (#707)
Browse files Browse the repository at this point in the history
* feature (webapi): After saving a property definition, reload it to check that it's correct.

* feature (webapi): Change a property's labels (ongoing).

* feature (webapi): Change a property's rdfs:label or rdfs:comment (ongoing).

* feature (webapi): Add route for changing labels or comments of a property.

- Add unit test for that.

* test (webapi): Add r2r tests for changing property labels and comments.

- Fix bugs in the comparison of SPARQL-escaped input with data read from the triplestore.

* feature (webapi): Add a class to an ontology (ongoing).

* feature (webapi): Add a class definition (ongoing).

* fix (webapi): Fix build and test breakage after merging develop into this branch.

* feature (webapi): Add a class to an ontology.

- Refactor SparqlExtendedConstructResponse to distinguish between blank nodes and IRIs.

* feature (webapi): Add a class definition.

- Refactor the ontology responder to calculate cardinality inheritance,
  and recalculate class hierarchies, when adding a class definition.
- Do more error-checking.
- Fix getClassDefinition.scala.txt not to return bogus blank nodes.
- Add a test.

* fix (webapi): Fix stupid bug.

* test (webapi): Add more tests of resource class creation, and fix more bugs.

- Cache abstract classes in OntologyResponderV2, and hide them when necessary in OntologyResponderV1.

* test (webapi): Create properties and classes.

- More tests.

* test (webapi): More property creation tests.

* feature (webapi): Add cardinalities to a class (ongoing).

- When creating a class or adding cardinalities, if new
  cardinalities override inherited ones, check that they
  are at least as restrictive.

* test (webapi): Add cardinalities to a class.

* feature (webapi): Change the labels or comments of a class (ongoing).

- Fix incorrect SPARQL-unescaping.

* test (webapi): Change the labels or comments of a class.

* feature (webapi): Change the labels or comments of a class.

- Add an e2e test for that.

* feature (webapi): Don't allow adding cardinalities to a class if it's used in data.

* refactor (webapi): Remove redunant response schema argument.

* feature (webapi): Change a class's cardinalities.

* feature (webapi): Delete a class or property.

* fix (webapi): Fix #157.

* fix (webapi): Check for duplicate IRIs and cyclical inheritance hierarchies.

* test (webapi): Don't allow creating a property with a knora-api:objectType of xsd:string.

* test (webapi): Turn off extra debugging output in test.

* docs (webapi): Document API v2 ontology routes.

* docs (webapi): Mention consistency requirement for ontology update API.

* fix (webapi): Don't modify a class's cardinalities if it has a subclass.

- Clarify consistency rules in ontology API doc.
- Test edit conflict prevention.

* test (webapi): Fix search test after the addition of a BlueThing for another test.

* docs (webapi): Clarify creation of entity names.

* test (webapi): Do some of the review tasks for #707.

* feature (webapi): More review tasks.

* feature (webapi): Add knora-api:isValueClass.
  • Loading branch information
Benjamin Geer authored Feb 7, 2018
1 parent 6e50f2c commit f804346
Show file tree
Hide file tree
Showing 52 changed files with 7,465 additions and 637 deletions.
8 changes: 5 additions & 3 deletions docs/rst/knora-api-server/api_v2/knora-iris.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ possible future naming conflicts.
The range of project IDs from ``0001`` to ``00FF`` inclusive is reserved for local testing, and also the ID ``0000`` is
reserved for future use by the system. Thus, the first useful project will be ``0100``.

In the beginning, Unil will use the IDs ``0100`` to ``07FF``, and Unibas ``0800`` to ``08FF`.
In the beginning, Unil will use the IDs ``0100`` to ``07FF``, and Unibas ``0800`` to ``08FF``.

IRIs for Ontologies and Ontology Entities
-----------------------------------------
Expand Down Expand Up @@ -79,6 +79,8 @@ reserved words:
- ``ontology``
- ``simple``

.. _external-ontology-iris-v2:

External Ontology IRIs
^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -93,8 +95,8 @@ The IRI of an external Knora ontology has the form:
http://HOST[:PORT]/ontology/PROJECT_SHORTCODE/ONTOLOGY_NAME/API_VERSION

For built-in ontologies, the host is always ``api.knora.org``. Otherwise, the hostname and port
configured in ``application.conf`` under ``app.http.knora-api.host`` and ``app.http.knora-api.http-
port`` are used (the port is omitted if it is 80).
configured in ``application.conf`` under ``app.http.knora-api.host`` and ``app.http.knora-api.http-port``
are used (the port is omitted if it is 80).

This means that when a built-in external ontology IRI is dereferenced, the ontology can be served by
a Knora API server running at ``api.knora.org``. When a project-specific external ontology IRI is
Expand Down
1,077 changes: 1,076 additions & 1 deletion docs/rst/knora-api-server/api_v2/ontology-information.rst

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions webapi/_test_data/all_data/anything-data.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -876,3 +876,11 @@
knora-base:valueHasEndPrecision "DAY" ;
knora-base:valueCreationDate "2018-01-31T15:05:10Z"^^xsd:dateTimeStamp ;
knora-base:hasPermissions "V knora-base:UnknownUser|M knora-base:ProjectMember" .

<http://data.knora.org/a-blue-thing> a anything:BlueThing ;
knora-base:attachedToUser <http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q> ;
knora-base:attachedToProject <http://rdfh.ch/projects/anything> ;
knora-base:hasPermissions "V knora-base:UnknownUser|M knora-base:ProjectMember" ;
knora-base:creationDate "2016-10-17T19:16:04.916+02:00"^^xsd:dateTime ;
rdfs:label "A blue thing" ;
knora-base:isDeleted false .
8 changes: 8 additions & 0 deletions webapi/src/main/scala/org/knora/webapi/Exceptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ case class DuplicateValueException(message: String = "Duplicate values are not p
*/
case class OntologyConstraintException(message: String) extends RequestRejectedException(message)

/**
* An exception indicating that a requested update is not allowed because another user has edited the
* data that was to be updated.
*
* @param message a description of the error.
*/
case class EditConflictException(message: String) extends RequestRejectedException(message)

/**
* An exception indicating that the submitted standoff is not valid.
*
Expand Down
7 changes: 7 additions & 0 deletions webapi/src/main/scala/org/knora/webapi/LanguageCodes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,11 @@ object LanguageCodes {
val EN: String = "en"
val FR: String = "fr"
val IT: String = "it"

val SupportedLanguageCodes: Set[String] = Set(
DE,
EN,
FR,
IT
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ object OntologyConstants {
val String: IRI = XsdPrefixExpansion + "string"
val Boolean: IRI = XsdPrefixExpansion + "boolean"
val Integer: IRI = XsdPrefixExpansion + "integer"
val NonNegativeInteger: IRI = XsdPrefixExpansion + "nonNegativeInteger"
val Decimal: IRI = XsdPrefixExpansion + "decimal"
val Uri: IRI = XsdPrefixExpansion + "anyURI"
val Pattern: IRI = XsdPrefixExpansion + "pattern"
Expand Down Expand Up @@ -570,6 +571,7 @@ object OntologyConstants {
val IsLinkProperty: IRI = KnoraApiV2PrefixExpansion + "isLinkProperty"
val IsLinkValueProperty: IRI = KnoraApiV2PrefixExpansion + "isLinkValueProperty"
val CanBeInstantiated: IRI = KnoraApiV2PrefixExpansion + "canBeInstantiated"
val IsValueClass: IRI = KnoraApiV2PrefixExpansion + "isValueClass"
val IsInherited: IRI = KnoraApiV2PrefixExpansion + "isInherited"
val OntologyName: IRI = KnoraApiV2PrefixExpansion + "ontologyName"
val ProjectIri: IRI = KnoraApiV2PrefixExpansion + "projectIri"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ case class SparqlExtendedConstructRequest(sparql: String) extends TriplestoreReq
/**
* A response to a [[SparqlExtendedConstructRequest]].
*
* @param statements a map of subject IRIs to statements about each subject.
* @param statements a map of subjects to statements about each subject.
*/
case class SparqlExtendedConstructResponse(statements: Map[IRI, Map[IRI, Seq[LiteralV2]]])
case class SparqlExtendedConstructResponse(statements: Map[SubjectV2, Map[IRI, Seq[LiteralV2]]])

/**
* Represents a SPARQL Update operation to be performed.
Expand Down Expand Up @@ -230,43 +230,70 @@ case class InitializedResponse(initFinished: Boolean)
*/
case class RdfDataObject(path: String, name: String)

/**
* Represents the subject of a statement read from the triplestore.
*/
sealed trait SubjectV2

case class IriSubjectV2(value: IRI) extends SubjectV2 {
override def toString: IRI = value
}

case class BlankNodeSubjectV2(value: String) extends SubjectV2 {
override def toString: String = value
}

/**
* A case class for representing a literal coming from the triplestore. There are different subclasses
* representing literals with the extended type-information stored in the triplestore.
*
* @param value
* Represents a literal read from the triplestore. There are different subclasses
* representing literals with the extended type information stored in the triplestore.
*/
abstract class LiteralV2(value: String)
sealed trait LiteralV2

/**
* Represents an object IRI.
*
* @param value the IRI.
*/
case class IriLiteralV2(value: IRI) extends LiteralV2(value = value.toString)
case class IriLiteralV2(value: IRI) extends LiteralV2 {
override def toString: IRI = value
}

/**
* Represents a blank node identifier.
*
* @param value the identifier of the blank node.
*/
case class BlankNodeLiteralV2(value: String) extends LiteralV2 {
override def toString: String = value
}

/**
* Represents a string with an optional language tag.
*
* @param value the string value.
* @param language the optional language tag.
*/
case class StringLiteralV2(value: String, language: Option[String] = None) extends LiteralV2(value = value)
case class StringLiteralV2(value: String, language: Option[String] = None) extends LiteralV2 {
override def toString: String = value
}

/**
* Represents a boolean value.
*
* @param value the boolean value.
*/
case class BooleanLiteralV2(value: Boolean) extends LiteralV2(value = value.toString)
case class BooleanLiteralV2(value: Boolean) extends LiteralV2 {
override def toString: String = value.toString
}

/**
* Represents an integer value.
*
* @param value the boolean value.
*/
case class IntLiteralV2(value: Int) extends LiteralV2(value = value.toString)
case class IntLiteralV2(value: Int) extends LiteralV2 {
override def toString: String = value.toString
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JSON formatting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,6 @@ object ApiStatusCodesV1 extends Enumeration {

val UNSPECIFIED_ERROR = Value(999)

/**
* Converts an HTTP status code to a similar API status code.
*
* @param httpStatus an HTTP status code.
* @return an API status code.
*/
def fromHttpStatus(httpStatus: StatusCode): Value = {
httpStatus match {
case StatusCodes.OK => OK
case StatusCodes.BadRequest => INVALID_REQUEST_TYPE
case StatusCodes.Forbidden => NO_RIGHTS_FOR_OPERATION
case StatusCodes.InternalServerError => INTERNAL_SALSAH_ERROR
case StatusCodes.NotFound => NOT_FOUND
case StatusCodes.NotImplemented => NOT_YET_IMPLEMENTED
case StatusCodes.Unauthorized => CREDENTIALS_NOT_VALID
case StatusCodes.Conflict => UPDATE_NOT_PERFORMED
case other => UNSPECIFIED_ERROR
}
}

/**
* Converts an exception to a similar API status code.
*
Expand All @@ -115,12 +95,13 @@ object ApiStatusCodesV1 extends Enumeration {
case BadCredentialsException(_) => ApiStatusCodesV1.CREDENTIALS_NOT_VALID
case DuplicateValueException(_) => ApiStatusCodesV1.DUPLICATE_VALUE
case OntologyConstraintException(_) => ApiStatusCodesV1.ONTOLOGY_CONSTRAINT
case EditConflictException(_) => ApiStatusCodesV1.UPDATE_NOT_PERFORMED
case RequestRejectedException(_) => ApiStatusCodesV1.INVALID_REQUEST_TYPE

// Subclasses of InternalServerException (which must be last in this group)
case UpdateNotPerformedException(_) => ApiStatusCodesV1.UPDATE_NOT_PERFORMED
case InternalServerException(_) => ApiStatusCodesV1.INTERNAL_SALSAH_ERROR
case other => ApiStatusCodesV1.INTERNAL_SALSAH_ERROR
case _ => ApiStatusCodesV1.INTERNAL_SALSAH_ERROR
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ case class TextValueWithStandoffV1(utf8str: String,
case otherText: TextValueV1 =>

// unescape utf8str since it contains escaped sequences while the string returned by the triplestore does not
otherText.utf8str == stringFormatter.fromSparqlEncodedString(utf8str, throw InvalidStandoffException(s"Could not unescape utf8str $utf8str"))
otherText.utf8str == stringFormatter.fromSparqlEncodedString(utf8str)
case otherValue => throw InconsistentTriplestoreDataException(s"Cannot compare a $valueTypeIri to a ${otherValue.valueTypeIri}")
}
}
Expand All @@ -767,7 +767,7 @@ case class TextValueWithStandoffV1(utf8str: String,
case textValueWithStandoffV1: TextValueWithStandoffV1 =>

// compare utf8str (unescape utf8str since it contains escaped sequences while the string returned by the triplestore does not)
val utf8strIdentical: Boolean = textValueWithStandoffV1.utf8str == stringFormatter.fromSparqlEncodedString(utf8str, throw InvalidStandoffException(s"Could not unescape utf8str $utf8str"))
val utf8strIdentical: Boolean = textValueWithStandoffV1.utf8str == stringFormatter.fromSparqlEncodedString(utf8str)

// compare standoff nodes (sort them first, since the order does not make any difference )
val standoffIdentical: Boolean = textValueWithStandoffV1.standoff.sortBy(standoffNode => (standoffNode.standoffTagClassIri, standoffNode.startPosition)) == this.standoff.sortBy(standoffNode => (standoffNode.standoffTagClassIri, standoffNode.startPosition))
Expand Down
Loading

0 comments on commit f804346

Please sign in to comment.