Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ontology): Don't accept list values without gui attribute (DEV-775) #2089

Merged
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
36f54c7
add test data
Jun 22, 2022
c2800e6
fix bug and add test
Jun 27, 2022
d18b15c
Merge branch 'main' into wip/dev-775-dont-accept-list-values-without-…
Jun 27, 2022
65b71f3
add missing import
Jun 27, 2022
b8b88d7
fix typo in test data
Jun 27, 2022
754ca13
add checks for all gui elements that need a gui attribute
Jun 27, 2022
539fc92
update freetest data
Jun 27, 2022
f972fc9
fix typo in test data
Jun 27, 2022
14c79dc
check more values
Jun 27, 2022
3e338bf
add tests
Jun 27, 2022
b3b0e31
remove prints
Jun 27, 2022
e2564d5
wip
Jul 4, 2022
f21f89e
Merge branch 'main' into wip/dev-775-dont-accept-list-values-without-…
Jul 4, 2022
1dbb6ca
remove featureFactoryConfig from new tests
Jul 4, 2022
ec1253c
refactor schema domain
Jul 4, 2022
def9cb2
remove make() from option
Jul 5, 2022
4f24363
bump zio prelude version
Jul 5, 2022
b627f2a
rename decision file
Jul 7, 2022
010aa66
rename file
Jul 11, 2022
f60a310
add value objects
Jul 12, 2022
c17efa3
move salsah-gui constants to shared project
Jul 13, 2022
acac270
rename SalsahGuiApiV2WithValueObjects
Jul 13, 2022
3aa8db1
improve value objects
Jul 13, 2022
0e67f18
improve validation
Jul 13, 2022
a264eb3
use val instead of string
Jul 13, 2022
4115ef0
small improvements
Jul 13, 2022
e6bfe6a
Merge branch 'main' into wip/dev-775-dont-accept-list-values-without-…
Jul 13, 2022
2c4710c
add more tests
Jul 14, 2022
103fae7
improve docs
Jul 14, 2022
8404e85
add r2r test
Jul 14, 2022
15f9b8d
update expected client test data
Jul 14, 2022
6ac39e3
Update expected-client-test-data.txt
Jul 14, 2022
14994c7
Merge branch 'main' into wip/dev-775-dont-accept-list-values-without-…
Jul 14, 2022
13a0ff2
Update expected-client-test-data.txt
Jul 14, 2022
129402d
Merge branch 'wip/dev-775-dont-accept-list-values-without-gui-attribu…
Jul 14, 2022
4baf026
make unit tests more readable
Jul 18, 2022
5b180b7
add new error type for validation fails
Jul 18, 2022
b987f2a
improve error messages
Jul 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/03-apis/api-v2/editing-resources.md
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
-->

# Editing Resources
# Creating and Editing Resources

## Creating a Resource

Expand All @@ -17,7 +17,7 @@ The body of the request is a JSON-LD document in the
[complex API schema](introduction.md#api-schema), specifying the type,`rdfs:label`, and its Knora resource properties
and their values. The representation of the resource is the same as when it is returned in a `GET` request, except that
its `knora-api:attachedToUser` is not given, and the resource IRI and those of its values can be optionally specified.
The format of the values submitted is described in [Editing Values](editing-values.md). If there are multiple values for
The format of the values submitted is described in [Creating and Editing Values](editing-values.md). If there are multiple values for
a property, these must be given in an array.

For example, here is a request to create a resource with various value types:
Expand Down Expand Up @@ -222,7 +222,7 @@ of the resource.

## Modifying a Resource's Values

See [Editing Values](editing-values.md).
See [Creating and Editing Values](editing-values.md).

## Modifying a Resource's Metadata

Expand Down
2 changes: 1 addition & 1 deletion docs/03-apis/api-v2/editing-values.md
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
-->

# Editing Values
# Creating and Editing Values

## Creating a Value

Expand Down
4 changes: 2 additions & 2 deletions docs/03-apis/api-v2/index.md
Expand Up @@ -13,8 +13,8 @@
- [Getting Lists](getting-lists.md)
- [XML to Standoff Mapping](xml-to-standoff-mapping.md)
- [Gravsearch: Virtual Graph Search](query-language.md)
- [Editing Resources](editing-resources.md)
- [Editing Values](editing-values.md)
- [Creating and Editing Resources](editing-resources.md)
- [Creating and Editing Values](editing-values.md)
- [Querying, Creating, and Updating Ontologies](ontology-information.md)
- [TEI/XML](tei-xml.md)
- [Permalinks](permalinks.md)
@@ -1,7 +1,6 @@
/*
* Copyright © 2021 - 2022 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*
*/

package dsp.schema.domain
Expand All @@ -11,11 +10,11 @@ import zio.prelude.Validation
object SchemaDomain extends App {
// implicitly["".type =:= "".type]

type IRI = String
type UserID = String
type IRI = String
type UserID = String
type UserProfile = String
type SchemaID = String
type Schema = String
type SchemaID = String
type Schema = String

final case class OntologyInfo(name: String, projectIri: IRI, label: String, comment: String)
final case class OntologyClass[A <: Singleton with String](name: A, label: String, comment: String) { self =>
Expand Down Expand Up @@ -62,19 +61,19 @@ object SchemaDomain extends App {
ct: CardinalityType
): WithTags[oc.Tag, op.Tag] =
new Cardinality {
type ClassTag = oc.Tag
type ClassTag = oc.Tag
type PropertyTag = op.Tag

val ontologyClass = oc
val ontologyClass = oc
val ontologyProperty = op
val cardinalityType = ct
val cardinalityType = ct
}
}

sealed trait CardinalityType
object CardinalityType {
case object MaxCardinalityOne extends CardinalityType
case object MinCardinalityOne extends CardinalityType
case object MaxCardinalityOne extends CardinalityType
case object MinCardinalityOne extends CardinalityType
case object MinCardinalityZero extends CardinalityType
}

Expand Down Expand Up @@ -214,16 +213,16 @@ object SchemaDomain extends App {
//trying it out
val ontoInfo = OntologyInfo("test", "http://example.org/test", "Test", "Test")

val classOne = OntologyClass("ClassOne", "Class One", "Class One")
val classOne = OntologyClass("ClassOne", "Class One", "Class One")
val propertyOne = OntologyProperty("PropertyOne", "Property One", "Property One", "http://example.org/test")

val classTwo = OntologyClass("ClassTwo", "Class Two", "Class Two")
val classTwo = OntologyClass("ClassTwo", "Class Two", "Class Two")
val propertyTwo = OntologyProperty("PropertyTwo", "Property Two", "Property Two", "http://example.org/test")

val cardOne = Cardinality(classOne, propertyOne, CardinalityType.MinCardinalityOne)
val cardTwo = Cardinality(classTwo, propertyTwo, CardinalityType.MinCardinalityOne)
val cardOne = Cardinality(classOne, propertyOne, CardinalityType.MinCardinalityOne)
val cardTwo = Cardinality(classTwo, propertyTwo, CardinalityType.MinCardinalityOne)
val cardThree = Cardinality(classOne, propertyTwo, CardinalityType.MinCardinalityOne)
val cardFour = Cardinality(classTwo, propertyOne, CardinalityType.MinCardinalityOne)
val cardFour = Cardinality(classTwo, propertyOne, CardinalityType.MinCardinalityOne)

val exampleOnto: Ontology[Any with "ClassOne" with "ClassTwo", Any with "PropertyOne"] =
Ontology
Expand Down
119 changes: 119 additions & 0 deletions dsp-shared/src/main/scala/dsp/constants/SalsahGui.scala
@@ -0,0 +1,119 @@
/*
* Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/

package dsp.constants

import dsp.errors._

/**
* Contains string constants for IRIs from ontologies used by the application.
*/
object SalsahGui {

/**
* `IRI` is a synonym for `String`, used to improve code readability.
*/
type IRI = String

val InternalOntologyStart = "http://www.knora.org/ontology"

val SalsahGuiOntologyLabel: String = "salsah-gui"
val SalsahGuiOntologyIri: IRI = InternalOntologyStart + "/" + SalsahGuiOntologyLabel
val SalsahGuiPrefixExpansion: IRI = SalsahGuiOntologyIri + "#"
irinaschubert marked this conversation as resolved.
Show resolved Hide resolved

val GuiAttribute: IRI = SalsahGuiPrefixExpansion + "guiAttribute"
val GuiAttributeDefinition: IRI = SalsahGuiPrefixExpansion + "guiAttributeDefinition"
val GuiOrder: IRI = SalsahGuiPrefixExpansion + "guiOrder"
val GuiElementProp: IRI = SalsahGuiPrefixExpansion + "guiElement"
val GuiElementClass: IRI = SalsahGuiPrefixExpansion + "Guielement"

val SimpleText: IRI = SalsahGuiPrefixExpansion + "SimpleText"
val Textarea: IRI = SalsahGuiPrefixExpansion + "Textarea"
val Pulldown: IRI = SalsahGuiPrefixExpansion + "Pulldown"
val Slider: IRI = SalsahGuiPrefixExpansion + "Slider"
val Spinbox: IRI = SalsahGuiPrefixExpansion + "Spinbox"
val Searchbox: IRI = SalsahGuiPrefixExpansion + "Searchbox"
val Date: IRI = SalsahGuiPrefixExpansion + "Date"
val Geometry: IRI = SalsahGuiPrefixExpansion + "Geometry"
val Colorpicker: IRI = SalsahGuiPrefixExpansion + "Colorpicker"
val List: IRI = SalsahGuiPrefixExpansion + "List"
val Radio: IRI = SalsahGuiPrefixExpansion + "Radio"
val Checkbox: IRI = SalsahGuiPrefixExpansion + "Checkbox"
val Richtext: IRI = SalsahGuiPrefixExpansion + "Richtext"
val Interval: IRI = SalsahGuiPrefixExpansion + "Interval"
val TimeStamp: IRI = SalsahGuiPrefixExpansion + "TimeStamp"
val Geonames: IRI = SalsahGuiPrefixExpansion + "Geonames"
val Fileupload: IRI = SalsahGuiPrefixExpansion + "Fileupload"
irinaschubert marked this conversation as resolved.
Show resolved Hide resolved

val GuiElements = scala.collection.immutable.List(
SimpleText,
Textarea,
Pulldown,
Slider,
Spinbox,
Searchbox,
Date,
Geometry,
Colorpicker,
List,
Radio,
Checkbox,
Richtext,
Interval,
TimeStamp,
Geonames,
Fileupload
)

val GuiAttributes = scala.collection.immutable.List(
"ncolors",
"hlist",
"numprops",
"size",
"maxlength",
"min",
"max",
"cols",
"rows",
"width",
"wrap"
)

object SalsahGuiAttributeType extends Enumeration {

val Integer: Value = Value(0, "integer")
val Percent: Value = Value(1, "percent")
val Decimal: Value = Value(2, "decimal")
val Str: Value = Value(3, "string")
val Iri: Value = Value(4, "iri")

val valueMap: Map[String, Value] = values.map(v => (v.toString, v)).toMap

def lookup(name: String): Value =
valueMap.get(name) match {
case Some(value) => value
case None => throw InconsistentRepositoryDataException(s"salsah-gui attribute type not found: $name")
}
}
irinaschubert marked this conversation as resolved.
Show resolved Hide resolved

object External {
// external representation of salsah-gui entities of the form: http://api.knora.org/ontology/salsah-gui/v2#...
val ApiOntologyHostname: String = "http://api.knora.org"
val ApiOntologyStart: String = ApiOntologyHostname + "/ontology/"
val VersionSegment = "/v2"
val SalsahGuiOntologyIri: IRI = ApiOntologyStart + SalsahGui.SalsahGuiOntologyLabel + VersionSegment
val SalsahGuiPrefixExpansion: IRI = SalsahGuiOntologyIri + "#"

val GuiAttribute: IRI = SalsahGuiPrefixExpansion + "guiAttribute"
val GuiOrder: IRI = SalsahGuiPrefixExpansion + "guiOrder"
val GuiElementProp: IRI = SalsahGuiPrefixExpansion + "guiElement"
val GuiAttributeDefinition: IRI = SalsahGuiPrefixExpansion + "guiAttributeDefinition"
val GuiElementClass: IRI = SalsahGuiPrefixExpansion + "Guielement"
val Geometry: IRI = SalsahGuiPrefixExpansion + "Geometry"
val Colorpicker: IRI = SalsahGuiPrefixExpansion + "Colorpicker"
val Fileupload: IRI = SalsahGuiPrefixExpansion + "Fileupload"
val Richtext: IRI = SalsahGuiPrefixExpansion + "Richtext"
}
}
22 changes: 22 additions & 0 deletions dsp-shared/src/main/scala/dsp/valueobjects/Iri.scala
Expand Up @@ -137,6 +137,27 @@ object Iri {
}
}
}

/**
* PropertyIri value object.
*/
sealed abstract case class PropertyIri private (value: String) extends Iri
object PropertyIri {
def make(value: String): Validation[Throwable, PropertyIri] =
if (value.isEmpty) {
Validation.fail(BadRequestException(IriErrorMessages.PropertyIriMissing))
} else {
// TODO all the following needs to be checked when validating a property iri (see string formatter for the implementations of these methods)
// if (
// !(propertyIri.isKnoraApiV2EntityIri &&
// propertyIri.getOntologySchema.contains(ApiV2Complex) &&
// propertyIri.getOntologyFromEntity == externalOntologyIri)
// ) {
// throw BadRequestException(s"Invalid property IRI: $propertyIri")
// }
irinaschubert marked this conversation as resolved.
Show resolved Hide resolved
Validation.succeed(new PropertyIri(value) {})
}
}
}

object IriErrorMessages {
Expand All @@ -149,4 +170,5 @@ object IriErrorMessages {
val UserIriMissing = "User IRI cannot be empty."
val UserIriInvalid = "User IRI is invalid."
val UuidVersionInvalid = "Invalid UUID used to create IRI. Only versions 4 and 5 are supported."
val PropertyIriMissing = "Property IRI cannot be empty."
}