From 6a40fc6f291b3cf3fbb3a1c6af2c61cbef49d19c Mon Sep 17 00:00:00 2001 From: Balduin Landolt <33053745+BalduinLandolt@users.noreply.github.com> Date: Wed, 1 Dec 2021 14:16:34 +0100 Subject: [PATCH] fix(create-ontology): within an ontology, references to the ontology itself are not possible (DEV-135) (#130) * refactor: add some typing * feat: improve schema * chore: make install command use pips editable install * fix: potential NPE * docs: update documentation * fix: not able to reference ontology in itself * fix: allow comma in PR title * refactor: simplify context handling * docs: improve documentation * docs: address errors in documentation * refactor: simplify context creation and improve comments * refactor: tidy up a bit --- .github/workflows/ckeck-pr-title.yml | 6 +- .gitignore | 3 + Makefile | 2 +- docs/dsp-tools-create-ontologies.md | 818 +++++++++++++++++++++ docs/dsp-tools-create.md | 772 +------------------ docs/dsp-tools-xmlupload.md | 15 +- knora/dsplib/models/connection.py | 2 +- knora/dsplib/models/helpers.py | 72 +- knora/dsplib/models/project.py | 2 +- knora/dsplib/models/resourceclass.py | 5 +- knora/dsplib/schemas/ontology.json | 5 + knora/dsplib/utils/onto_create_lists.py | 6 +- knora/dsplib/utils/onto_create_ontology.py | 7 +- mkdocs.yml | 29 +- 14 files changed, 924 insertions(+), 820 deletions(-) create mode 100644 docs/dsp-tools-create-ontologies.md diff --git a/.github/workflows/ckeck-pr-title.yml b/.github/workflows/ckeck-pr-title.yml index 7d2aafa67..e52642737 100644 --- a/.github/workflows/ckeck-pr-title.yml +++ b/.github/workflows/ckeck-pr-title.yml @@ -12,9 +12,9 @@ jobs: # check PR title - uses: deepakputhraya/action-pr-title@master with: - regex: '([a-z])+(\(([a-z\-_ ])+\))?!?: [a-z]([a-zA-Z-\.\d \(\)\[\]#_])+$' # Regex the title should match. - allowed_prefixes: 'fix,refactor,feat,docs,chore,style,test' # title should start with the given prefix - disallowed_prefixes: 'feature,hotfix' # title should not start with the given prefix + regex: '([a-z])+(\(([a-z\-_ ])+\))?!?: [a-z]([a-zA-Z-\.\d \(\)\[\]#_,])+$' # Regex the title should match. + allowed_prefixes: "fix,refactor,feat,docs,chore,style,test" # title should start with the given prefix + disallowed_prefixes: "feature,hotfix" # title should not start with the given prefix prefix_case_sensitive: true # title prefix are case insensitive min_length: 7 # Min length of the title max_length: 120 # Max length of the title diff --git a/.gitignore b/.gitignore index 7206f750b..3c20dcce5 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,6 @@ out.json # bazel /bazel-* /.ijwb/ + +# for testing in development +tmp/ diff --git a/Makefile b/Makefile index 0a9ca9cb1..775f999dc 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ install-requirements: ## install requirements .PHONY: install install: ## install from source (runs setup.py) python3 -m pip install --upgrade pip - pip3 install . + pip3 install -e . .PHONY: test test: clean local-tmp clone-dsp-repo dsp-stack ## run all tests diff --git a/docs/dsp-tools-create-ontologies.md b/docs/dsp-tools-create-ontologies.md new file mode 100644 index 000000000..28e15b587 --- /dev/null +++ b/docs/dsp-tools-create-ontologies.md @@ -0,0 +1,818 @@ +# Ontologies + +An ontology is a formal representation of a set of terminologies which finally represent real world objects. +Dependencies, attributes and relations of and between the individual components of the set are recorded in a logical, +formal language. In contrast to a taxonomy, which defines a mere hierarchical structure within a range of terms, an +ontology is much more a network of information of logical dependencies of term elements. Or, in other words, an ontology +defines a strict, formal "data model" for real world _concepts_ such as "Person", "Work", "Artist" etc. + +A full-fledged ontology thus has to offer at least *two* things: a set of _concepts_ or terms (called _resources_, +actually "resource classes") that represent _concepts_ of real world objects, as well as attributes or _properties_ +describing these resources. These properties are linked either to a final value or may define a relationship to another +resource. Let's assume that we define a resource called "Person" and two properties called "hasBirthday" and "hasParent" +. For a specific incarnation of a +"Person" (we call this an _instance_), "hasBirthday" will have a final value such as "1960-05-21", whereas +"hasParent" will link to another instance of a "Person". + +Within DSP, properties may be re-used for different resources. E.g. a property "description" may be used for a resource +called "image" as well as "movie". Therefore, the list of properties is separated from the list of resources. The +properties are assigned to the resources by defining "_cardinalities_". A cardinality indicates if a property is +mandatory or can be omitted (e.g. if unknown), and if a property may be used several times on the same instance of a +resource or not. The cardinality definitions are explained [further below](#cardinalities). + + +Example of an `ontologies` object: + +```json +{ + "ontologies": [ + { + "name": "seworon", + "label": "Secrets of the World Ontology", + "properties": [ + ... + ], + "resources": [ + ... + ] + }, + { + ... + }, + { + ... + } + ] +} +``` + +## Ontologies Object in Detail + +The following properties can occur within each object in `ontologies`. + +### Name + +(required) + +`"name": ""` + +The ontology's (short) name should be in the form of a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This +means a string without blanks or special characters but `-` and `_` are allowed (although not as first character). + +### Label + +(required) + +`"label": ""` + +A string that provides the full name of the ontology. + +### Properties + +(required) + +`"properties": [, , ...]` + +A `properties` array contains all properties used to describe resources in the ontology. A property has to be of a +certain data type. It is not possible to create a custom data type. + +The following fields are mandatory: + +- `name` +- `labels` +- `object` +- `gui_element` + +A detailed description of `properties` can be found [below](#properties-object-in-detail). + + + +### Resources + +(required) + +The resource classes are the primary entities of the data model. They are the actual objects inside a terminology space. +A resource class can be seen as a template for the representation of a real object that is represented in the DSP. A +resource class defines properties (_data fields_). For each of these properties a data type as well as the cardinality +has to be provided. + +`"resources": [, , ...]` + +A resource object needs to have the following fields: + +- `name` +- `labels` +- `super` +- `cardinalities` + +The following field is optional: + +- `comments` + +A detailed description of `resources` can be found [below](#properties-object-in-detail). + + + +## Properties Object in Detail + +Please note that `object` is used to define the data type. The `gui_element` depends on the value of the `object`. + +The `gui_attributes` depends on the value of the `gui_element`. + +### Name + +(required) + +`"name": ""` + +A name for the property, e.g. "pageOf", "hasBirthdate", "createdBy". It should be in the form of +a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This means a string without blanks or special characters +but `-` and `_` are allowed (although not as first character). + +By convention, property names start with a lower case letter. + +### Labels + +(required) + +`"labels": {"": "", ...}` + +Collection of `labels` for the property as strings with language tag (currently "en", "de", "fr" +and "it" are supported). + +### Object / gui_element / gui_attributes + +- `object`: required +- `gui_element`: required +- `gui_attributes`: optional + +`"object": ""` + +The `object` defines the data type of the value that the property will store. `gui_element` and `gui_attributes` depend on the data type. The following data types are allowed: + +- `TextValue` +- `ColorValue` +- `DateValue` +- `TimeValue` +- `DecimalValue` +- `GeomValue` +- `GeonameValue` +- `IntValue` +- `BooleanValue` +- `UriValue` +- `IntervalValue` +- `ListValue` +- `LinkValue` + +#### TextValue + +`"object": "TextValue"` + +Represents a text that may contain standoff markup. + +*gui_elements / gui_attributes*: + +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes are: + - _gui_attributes_: + - `maxlength=integer` (optional): maximal length (number of characters accepted) + - `size=integer` (optional): size (width) of widget +- `Textarea`: A GUI element for _TextValue_. Presents a multiline text entry box. The optional attributes are: + - _gui_attributes_: + - `cols=integer` (optional): number of columns of the textarea + - `rows=integer` (optional): number of rows of the textarea + - `width=percent` (optional): width of the textarea on screen + - `wrap=soft|hard` (optional): wrapping of text +- `Richtext`: A GUI element for _TextValue_. Provides a richtext editor. + - _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasPictureTitle", + "super": [ + "hasValue" + ], + "object": "TextValue", + "labels": { + "en": "Title" + }, + "gui_element": "SimpleText", + "gui_attributes": { + "maxlength": 255, + "size": 80 + } +} +``` + +#### ColorValue + +`"object": "ColorValue"` + +A string representation of the color in the hexadecimal form e.g. "#ff8000". + +*gui-elements / gui_attributes*: + +- `Colorpicker`: The only GUI element for _ColorValue_. It's used to choose a color. + - _gui_attributes_: + - `ncolors=integer` (optional): Number of colors the color picker should present. + +*Example:* + +```json +{ + "name": "hasColor", + "super": [ + "hasValue" + ], + "object": "ColorValue", + "labels": { + "en": "Color" + }, + "gui_element": "Colorpicker" +} +``` + +#### DateValue + +`object": "DateValue"` +Represents a date. It's a string with the format `calendar:start:end` + +Please note that the DateValue is an extremely flexible data type. It can represent an exact date or a date with a given +uncertainty, and the date can be given in several calendars (currently the Gregorian and the Julian calendars are +supported, with the Jewish and Islamic coming soon). Internally, a date is always represented as a start and end date. +If start and end date match, it's an exact date. A value like "1893" will automatically be expanded to a range from +January 1st 1893 to December 31st 1893. + +- _calendar_ is either _GREGORIAN_ or _JULIAN_ +- _start_ has the form _yyyy_-_mm_-_dd_. If only the year is given, the precision is to the year. If only the year and + month is given, the precision is to the month. +- _end_ is optional if the date represents a clearly defined period or uncertainty. + +In total, a DateValue has the following form: "GREGORIAN:1925:1927-03-22" +which means anytime in between 1925 and the 22nd March 1927. + +*gui_elements / gui_attributes*: + +- `Date`: The only GUI element for _DateValue_. A date picker gui. +- _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasDate", + "super": [ + "hasValue" + ], + "object": "DateValue", + "labels": { + "en": "Date" + }, + "gui_element": "Date" +} +``` + +#### TimeValue + +`"object": "TimeValue"` + +A time value represents a precise moment in time in the Gregorian calendar. Since nanosecond precision can be included, it is suitable for use as a timestamp. + +*gui-elements / gui_attributes*: + +- `TimeStamp`: A GUI element for _TimeValue_ which contains a date picker and a time picker. + - _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasTime", + "super": [ + "hasValue" + ], + "object": "TimeValue", + "labels": { + "en": "Time" + }, + "gui_element": "TimeStamp" +} +``` + +#### DecimalValue + +`"object": "DecimalValue"` + +A number with decimal point. + +*gui-elements / gui_attributes*: + +- `Slider`: A GUI element for _DecimalValue_. Provides a slider to select a decimal value. + - _gui_attributes_: + - `max=decimal` (mandatory): maximal value + - `min=decimal` (mandatory): minimal value +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes + "maxlength=integer" and "size=integer" are optional. + - _gui_attributes_: + - `maxlength=integer` (optional): maximum number of characters accepted + - `size=integer` (optional): size of the input field + +*Example:* + +```json +{ + "name": "hasDecimal", + "super": [ + "hasValue" + ], + "object": "DecimalValue", + "labels": { + "en": "Decimal number" + }, + "gui_element": "SimpleText", + "gui_attributes": { + "maxlength": 255, + "size": 80 + } +} +``` + +#### GeomValue + +`"object": "GeomValue"` + +Represents a geometrical shape as JSON. Geometrical shapes are used to define regions of interest (ROI) on still images +or moving images. + +*gui-elements / gui_attributes*: + +- `Geometry`: not yet implemented. + - _gui_attributes_: No attributes +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes + "maxlength=integer" and "size=integer" are optional. + - _gui_attributes_: + - `maxlength=integer` (optional): The maximum number of characters accepted + - `size=integer` (optional): The size of the input field + +*Example*: + +```json +{ + "name": "hasGeometry", + "super": [ + "hasValue" + ], + "object": "GeomValue", + "labels": "Geometry", + "gui_element": "SimpleText" +} +``` + +#### GeonameValue + +Represents a location ID in geonames.org. The DSP platform uses identifiers provided by +[geonames.org](https://geonames.orgs) to identify geographical locations. + +*gui-elements / gui_attributes*: + +- `Geonames`: The only valid GUI element for _GeonameValue_. It interfaces are with geonames.org and it allows to select + a location. + - _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasGeoname", + "super": [ + "hasValue" + ], + "object": "GeonameValue", + "labels": { + "en": "Geoname" + }, + "gui_element": "Geonames" +} +``` + +#### IntValue + +`"object": "IntValue"` + +Represents an integer value. + +*gui-elements / gui_attributes*: + +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes + "maxlength=integer" and "size=integer" are optional. + - _gui_attributes_: + - `maxlength=integer` (optional): The maximum number of characters accepted + - `size=integer` (optional): The size of the input field +- `Spinbox`: A GUI element for _IntegerValue_. A text field with and "up"- and "down"-button for increment/decrement. + The attributes "max=decimal" and "min=decimal" are optional. + - _gui_attributes_: + - `max=decimal` (optional): Maximal value + - `min=decimal` (optional): Minimal value + +*Example:* + +```json +{ + "name": "hasInteger", + "super": [ + "hasValue" + ], + "object": "IntValue", + "labels": { + "en": "Integer" + }, + "gui_element": "Spinbox", + "gui_attributes": { + "max": 10.0, + "min": 0.0 + } +} +``` + +#### BooleanValue + +`"object": "BooleanValue"` + +Represents a Boolean ("true" or "false). + +*gui-elements / gui_attributes*: + +- `Checkbox`: A GUI element for _BooleanValue_. + - _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasBoolean", + "super": [ + "hasValue" + ], + "object": "BooleanValue", + "labels": { + "en": "Boolean value" + }, + "gui_element": "Checkbox" +} +``` + +#### UriValue + +`"object": "UriValue"` + +Represents an URI + +*gui-elements / gui_attributes*: + +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes + "maxlength=integer" and "size=integer" are optional. + - _gui_attributes_: + - `maxlength=integer` (optional): The maximum number of characters accepted + - `size=integer` (optional): The size of the input field + +*Example:* + +```json +{ + "name": "hasUri", + "super": [ + "hasValue" + ], + "object": "UriValue", + "labels": { + "en": "URI" + }, + "gui_element": "SimpleText", + "gui_attributes": { + "maxlength": 255, + "size": 80 + } +} +``` + +#### IntervalValue + +`"object": "IntervalValue"` + +Represents a time-interval + +*gui-elements / gui_attributes*: + +- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes + "maxlength=integer" and "size=integer" are optional. + - _gui_attributes_: + - `maxlength=integer` (optional): The maximum number of characters accepted + - `size=integer` (optional): The size of the input field +- `Interval`: not yet implemented. + - _gui_attributes_: No attributes + +*Example:* + +```json +{ + "name": "hasInterval", + "super": [ + "hasValue" + ], + "object": "IntervalValue", + "labels": { + "en": "Time interval" + }, + "gui_element": "Interval" +} +``` + +#### ListValue + +`"object": "ListValue"` + +Represents a node of a (possibly hierarchical) list + +*gui-elements / gui_attributes*: + +- `Radio`: A GUI element for _ListValue_. A set of radio buttons. This works only with flat lists. + - _gui_attributes_: + - `hlist=` (required): The reference of a [list](#lists) root node +- `List`: A GUI element for _ListValue_. A list of values to select one from. This GUI element should be chosen for + hierarchical lists or flat lists that could be expanded to hierarchical lists in the future. + - _gui_attributes_: + - `hlist=` (required): The reference of a [list](#lists) root node + +*Example:* + +```json +{ + "name": "hasListItem", + "super": [ + "hasValue" + ], + "object": "ListValue", + "labels": { + "en": "List element" + }, + "gui_element": "List", + "gui_attributes": { + "hlist": "treelistroot" + } +} +``` + +#### LinkValue + +`"object": ":"` + +LinkValues do not follow the pattern of the previous data types, because they do not connect to a final value but to +another resource which has to be defined. Thus, the "object" denominates the resource class the link will point to. If +the resource is defined in the same ontology, the name has to be prepended by a ":", if the resource is defined in +another (previously defined) +ontology, the ontology name has to be prepended separated by a colon ":", e.g. +"other-onto:MyResource". The "super"-element has to be "hasLinkTo" or at least derived from "hasLinkTo" (how to derive a +resource or property from another one is not part of this documentation). + +*gui-elements/gui_attributes*: + +- `Searchbox`: Has to be used with _hasLinkTo_ property. Allows searching resources by entering a resource that the given resource + should link to. It has one gui_attribute that indicates how many properties of the found resources should be + indicated. This is mandatory. + - _gui_attributes_: + - `numprops=integer` (optional): While dynamically displaying the search result, the number of properties that + should be displayed. + +*Example:* + +```json +{ + "name": "hasOtherThing", + "super": [ + "hasLinkTo" + ], + "object": ":Thing", + "labels": "Another thing", + "gui_element": "Searchbox" +} +``` + +Like already mentioned before: The following two fields are optional (can be omitted), with the notable exception of +the "super" +clause in case of LinkValues where the super clause is mandatory: + +### Super + +`"super": ["", ", ...]` + +A property has to be derived from at least one base property. The most generic base property that the DSP offers is +_hasValue_. In addition, the property may be a sub-property of properties defined in external or other ontologies. +External ontologies like `dcterms` or `foaf` must be defined in the "prefix" section. + +In this case the qualified name - including the prefix of the external or internal ontology - has to be given. + +The following base properties are defined by DSP: + +- `hasValue`: This is the most generic base. +- `hasLinkTo`: This value represents a link to another resource. You have to indicate the "_object_" as a prefixed name + that identifies the resource class this link points to (a ":" prepended to the name is sufficient if the resource is + defined in the current ontology). +- `hasColor`: Defines a color value (_ColorValue_) +- `hasComment`: Defines a "standard" comment +- `hasGeometry`: Defines a geometry value (a JSON describing a polygon, circle or rectangle), see _ColorValue_ +- `isPartOf`: A special variant of _hasLinkTo_. It says that an instance of the given resource class is an integral part + of another resource class. E.g. a "page" is part of a "book". +- `isRegionOf`: A special variant of _hasLinkTo_. It means that the given resource class is a "region" of another + resource class. This is typically used to describe regions of interest in images. +- `isAnnotationOf`: A special variant of _hasLinkTo_. It denotes the given resource class as an annotation to another + resource class. +- `seqnum`: An integer that is used to define a sequence number in an ordered set of instances, e.g. the ordering of the + pages in a book (independent of the page naming) + +Example of a `properties` object: + +```json +{ + "properties": [ + { + "name": "schulcode", + "object": "TextValue", + "super": [ + "hasValue" + ], + "labels": { + "de": "Schulcode" + }, + "gui_element": "SimpleText", + "gui_attributes": { + "size": 32, + "maxlength": 128 + } + }, + { + "name": "schulname", + "object": "TextValue", + "super": [ + "hasValue" + ], + "labels": { + "de": "Name der Schule" + }, + "gui_element": "SimpleText", + "gui_attributes": { + "size": 32, + "maxlength": 128 + } + } + ] +} +``` + + +## Resources Object in Detail + + +### Name + +(required) + +`"name": ""` + +A name for the resource, e.g. "Book", "Manuscript", "Person". It should be in the form of +a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This means a string without blanks or special characters +but `-` and `_` are allowed (although not as first character). + +By convention, resource names start with a upper case letter. + +### Labels + +(required) + +`"labels": {"": "", ...}` + +Collection of `labels` for the resource as strings with language tag (currently "en", "de", "fr" +and "it" are supported). + +### Super + +(required) + +`"super": ["", "", ...]` + +A resource is always derived from at least one other resource. The most generic resource class for DSP is `Resource`. A resource may be derived from resources defined in external ontologies. + +The following predefined resources are provided by DSP: + +- `Resource`: A generic resource that represents an item from the real world +- `StillImageRepresentation`: An object that is connected to a still image +- `TextRepresentation`: An object that is connected to an (external) text (not yet implemented) +- `AudioRepresentation`: An object representing audio data (not yet implemented) +- `DDDRepresentation`: An object representing a 3-D representation (not yet implemented) +- `DocumentRepresentation`: An object representing an opaque document (e.g. a PDF) +- `MovingImageRepresentation`: An object representing a moving image (video, film) +- `ArchiveRepresentation`: An object representing a archive file (e.g. Zip) +- `Annotation`: A predefined annotation object. It has automatically the following predefined properties defined: + - `hasComment` (1-n) + - `isAnnotationOf` (1) +- `LinkObj`: A resource class linking together several other, generic, resource classes. The class has the following + properties: + - `hasComment` (1-n) + - `hasLinkTo` (1-n) +- `Region`: Represents a simple region. The class has the following properties: + - `hasColor` (1) + - `isRegionOf` (1) + - `hasGeometry` (1) + - `hasComment` (0-n) + +Additionally, resources can be derived from external ontologies or from resources specified in the present document. + +### Cardinalities + +(required) + +`"cardinalities": [...]` + +An array that contains information about the relation between resources and properties. It tells what properties a +resource can have as well as how many times the relation is established. + +- `cardinalities`: Array of references to the properties that the resource may hold including the cardinality. A + cardinality has the following properties: + - `propname` (1): The name of the property. If it's used in the form `:my_propname`, the current ontology is referenced. + Otherwise, the prefix of the ontology the property is part of has to be used. + - `gui_order` (0-1): An integer number which will help the GUI to display the properties in the desired order (optional) + - `cardinality` (1): Indicates how often a given property may occur. The possible values are: + - `"1"`: exactly once (mandatory one value and only one) + - `"0-1"`: The value may be omitted, but can occur only once. + - `"1-n"`: At least one value must be present, but multiple values may be present. + - `"0-n"`: The value may be omitted, but may also occur multiple times. + +### Comments + +(optional) + +`"comments": { "": "", "": "", ... }` + +Comments with language tags. The `comments` element is optional. Currently, "de", "en", "fr" and "it" are supported. + +Example for a resource definition: + +```json +{ + "resources": [ + { + "name": "Schule", + "labels": { + "de": "Schule", + "en": "School", + "fr": "Ecole", + "it": "Scuola" + }, + "super": "Resource", + "comments": { + "de": "Ein Kommentar", + "en": "A comment", + "fr": "Une commentaire", + "it": "Un commento" + }, + "cardinalities": [ + { + "propname": ":schulcode", + "gui_order": 1, + "cardinality": "1" + }, + { + "propname": ":schulname", + "gui_order": 2, + "cardinality": "1" + }, + { + "propname": ":bildungsgang", + "gui_order": 3, + "cardinality": "1" + } + ] + } + ] +} +``` + + +## Referencing Ontologies + +For several fields, such as `super` in both `resources` and `properties` or `propname` in `cardinalities`, +it is necessary to reference entities that are defined elsewhere. The following cases are possible. + +- DSP-API internals: These must be written *without* leading colon and should not be a fully qualified IRI. + E.g. `Resource`, `DocumentRepresentation` or `hasValue` +- An external ontology: The ontology must be defined in the [prefixes](dsp-tools-create.md#prefixes-object) + This prefix should be used for referencing the ontology. + E.g. `foaf:familyName` or `sdo:Organization` +- The current ontology: Within an ontology definition, references can be made by prepending a colon without a prefix. + E.g. `:hasName` + Optionally, an explicit prefix can be used, in this case the ontology must be added to the + [prefixes](dsp-tools-create.md#prefixes-object) and the prefix must be identical to the ontology's `name`. +- A different ontology defined in the same file: Within one data model file, multiple ontologies can be defined. + These will be created in the exact order they appear in the `ontologies` array. Once an ontology has been created, + it can be referenced by the following ontologies, provided it is added in the + [prefixes](dsp-tools-create.md#prefixes-object). diff --git a/docs/dsp-tools-create.md b/docs/dsp-tools-create.md index 4ebab9be1..4209cfa07 100644 --- a/docs/dsp-tools-create.md +++ b/docs/dsp-tools-create.md @@ -48,6 +48,8 @@ A complete data model definition for DSP looks like this: ### "prefixes" object +(optional) + `"prefixes": { "prefix": "", ...}` The `prefixes` object contains the prefixes of external ontologies that are used in the current project. All prefixes @@ -64,14 +66,21 @@ full qualified IRI each time it is used. So, instead of writing a property calle } ``` +Note that prefixes can be defined for the ontologies defined in this file, but this is only necessary if the ontology +needs to be referred to explicitly by another ontology within the same file. + ### "$schema" object +(required) + The `$schema` object refers to the JSON schema for DSP data model definitions and is mandatory. `"$schema": "https://raw.githubusercontent.com/dasch-swiss/dsp-tools/main/knora/dsplib/schemas/ontology.json"` ### "project" object +(required) + `"project": {"key": "", ...}` The `project` object contains all resources and properties of the ontology as well as some information about the @@ -128,12 +137,16 @@ In the following section all fields of the `project` object are explained in det ### Shortcode +(required) + `"shortcode": "<4-hex-characters>"` The shortcode has to be unique and is represented by a 4 digit hexadecimal string. The shortcode has to be provided by the DaSCH. ### Shortname +(required) + `"shortname": ""` The shortname has to be unique. It should be in the form of a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This means a @@ -141,12 +154,16 @@ string without blanks or special characters but `-` and `_` are allowed (althoug ### Longname +(required) + `"longname": ""` The longname is a string that provides the full name of the project. ### Descriptions +(required) + `"descriptions": {"": "", ...}` The description is represented as a collection of strings with language tags (currently "en", "de", "fr" and "it" are @@ -154,12 +171,16 @@ supported). It is the description of the project. ### Keywords +(required) + `"keywords": ["", "", ...]` Keywords are represented as an array of strings and are used to describe and/or tag the project. ### Lists +(optional) + `"lists": [,,...]` Lists can be used to provide controlled vocabularies and can be "flat" or "hierarchical". One advantage of the use of @@ -331,6 +352,8 @@ The `lists` element is optional. If not used, it should be omitted. ### Groups +(optional) + `"groups": [, ,...]` The `groups` object contains groups definitions. This is used to specify the permissions a user gets. A project may @@ -364,6 +387,8 @@ The `groups` element is optional. If not used, it should be omitted. It is curre ### Users +(optional) + `"users": [, ,...]` This object contains user definitions. A user has the following elements: @@ -410,754 +435,19 @@ The `users` element is optional. If not used, it should be omitted. ### Ontologies -An ontology is a formal representation of a set of terminologies which finally represent real world objects. -Dependencies, attributes and relations of and between the individual components of the set are recorded in a logical, -formal language. In contrast to a taxonomy, which defines a mere hierarchical structure within a range of terms, an -ontology is much more a network of information of logical dependencies of term elements. Or, in other words, an ontology -defines a strict, formal "data model" for real world _concepts_ such as "Person", "Work", "Artist" etc. - -A full-fledged ontology thus has to offer at least *two* things: a set of _concepts_ or terms (called _resources_, -actually "resource classes") that represent _concepts_ of real world objects, as well as attributes or _properties_ -describing these resources. These properties are linked either to a final value or may define a relationship to another -resource. Let's assume that we define a resource called "Person" and two properties called "hasBirthday" and "hasParent" -. For a specific incarnation of a -"Person" (we call this an _instance_), "hasBirthday" will have a final value such as "1960-05-21", whereas -"hasParent" will link to another instance of a "Person". - -Within DSP, properties may be re-used for different resources. E.g. a property "description" may be used for a resource -called "image" as well as "movie". Therefore, the list of properties is separated from the list of resources. The -properties are assigned to the resources by defining "_cardinalities_". A cardinality indicates if a property is -mandatory or can be omitted (e.g. if unknown), and if a property may be used several times on the same instance of a -resource or not. The cardinality definitions are explained [further below](#cardinalities). +(required) `"ontologies": [, , ...]` Inside the `ontologies` section all resources and properties are described. A project may have multiple ontologies. It requires the following data fields: -- name -- label -- properties -- resources - -Example of an `ontologies` object: - -```json -{ - "ontologies": [ - { - "name": "seworon", - "label": "Secrets of the World Ontology", - "properties": [ - ... - ], - "resources": [ - ... - ] - }, - { - ... - }, - { - ... - } - ] -} -``` - -#### Name - -`"name": ""` - -The ontology's (short) name should be in the form of a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This -means a string without blanks or special characters but `-` and `_` are allowed (although not as first character). - -#### Label - -`"label": ""` - -A string that provides the full name of the ontology. - -#### Properties - -`"properties": [, , ...]` - -A `properties` array contains all properties used to describe resources in the ontology. A property has to be of a -certain data type. It is not possible to create a custom data type. - -The following fields are mandatory: - -- name -- labels -- object -- gui_element - -Please note that `object` is used to define the data type. The `gui_element` depends on the value of the `object`. - -The following fields are optional (they can be omitted): - -- super -- gui_attributes - -The `gui_attributes` depends on the value of the `gui_element`. - -##### Name - -`"name": ""` - -A name for the property, e.g. "pageOf", "hasBirthdate", "createdBy". It should be in the form of -a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This means a string without blanks or special characters -but `-` and `_` are allowed (although not as first character). - -##### Labels - -`"labels": {"": "", ...}` - -Collection of `labels` for the property as strings with language tag (currently "en", "de", "fr" -and "it" are supported). - -##### Object / gui_element / gui_attribute - -`"object": ""` - -The `object` defines the data type of the value that the property will store. The following data types are allowed: - -###### TextValue - -`"object": "TextValue"` - -Represents a text that may contain standoff markup. - -*gui\_elements / gui\_attributes*: - -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes are: - - _gui_attributes_: - - `maxlength=integer` (optional): maximal length (number of characters accepted) - - `size=integer` (optional): size (width) of widget -- `Textarea`: A GUI element for _TextValue_. Presents a multiline text entry box. The optional attributes are: - - _gui_attributes_: - - `cols=integer` (optional): number of columns of the textarea - - `rows=integer` (optional): number of rows of the textarea - - `width=percent` (optional): width of the textarea on screen - - `wrap=soft|hard` (optional): wrapping of text -- `Richtext`: A GUI element for _TextValue_. Provides a richtext editor. - - _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasPictureTitle", - "super": [ - "hasValue" - ], - "object": "TextValue", - "labels": { - "en": "Title" - }, - "gui_element": "SimpleText", - "gui_attributes": { - "maxlength": 255, - "size": 80 - } -} -``` - -###### ColorValue - -`"object": "ColorValue"` - -A string representation of the color in the hexadecimal form e.g. "#ff8000". - -*gui-elements / gui_attributes*: - -- `Colorpicker`: The only GUI element for _ColorValue_. It's used to choose a color. - - _gui_attributes_: - - `ncolors=integer` (optional): Number of colors the color picker should present. - -*Example:* - -```json -{ - "name": "hasColor", - "super": [ - "hasValue" - ], - "object": "ColorValue", - "labels": { - "en": "Color" - }, - "gui_element": "Colorpicker" -} -``` - -###### DateValue - -`object": "DateValue"` -Represents a date. It's a string with the format `calendar:start:end` - -Please note that the DateValue is an extremely flexible data type. It can represent an exact date or a date with a given -uncertainty, and the date can be given in several calendars (currently the Gregorian and the Julian calendars are -supported, with the Jewish and Islamic coming soon). Internally, a date is always represented as a start and end date. -If start and end date match, it's an exact date. A value like "1893" will automatically be expanded to a range from -January 1st 1893 to December 31st 1893. - -- _calendar_ is either _GREGORIAN_ or _JULIAN_ -- _start_ has the form _yyyy_-_mm_-_dd_. If only the year is given, the precision is to the year. If only the year and - month is given, the precision is to the month. -- _end_ is optional if the date represents a clearly defined period or uncertainty. - -In total, a DateValue has the following form: "GREGORIAN:1925:1927-03-22" -which means anytime in between 1925 and the 22nd March 1927. - -*gui-elements / gui_attributes*: - -- `Date`: The only GUI element for _DateValue_. A date picker gui. -- _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasDate", - "super": [ - "hasValue" - ], - "object": "DateValue", - "labels": { - "en": "Date" - }, - "gui_element": "Date" -} -``` - -###### TimeValue - -`"object": "TimeValue"` - -A time value represents a precise moment in time in the Gregorian calendar. Since nanosecond precision can be included, it is suitable for use as a timestamp. - -*gui-elements / gui_attributes*: - -- `TimeStamp`: A GUI element for _TimeValue_ which contains a date picker and a time picker. - - _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasTime", - "super": [ - "hasValue" - ], - "object": "TimeValue", - "labels": { - "en": "Time" - }, - "gui_element": "TimeStamp" -} -``` - -###### DecimalValue - -`"object": "DecimalValue"` - -A number with decimal point. - -*gui-elements / gui_attributes*: - -- `Slider`: A GUI element for _DecimalValue_. Provides a slider to select a decimal value. - - _gui_attributes_: - - `max=decimal` (mandatory): maximal value - - `min=decimal` (mandatory): minimal value -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes - "maxlength=integer" and "size=integer" are optional. - - _gui_attributes_: - - `maxlength=integer` (optional): maximum number of characters accepted - - `size=integer` (optional): size of the input field - -*Example:* - -```json -{ - "name": "hasDecimal", - "super": [ - "hasValue" - ], - "object": "DecimalValue", - "labels": { - "en": "Decimal number" - }, - "gui_element": "SimpleText", - "gui_attributes": { - "maxlength": 255, - "size": 80 - } -} -``` - -###### GeomValue - -`"object": "GeomValue"` - -Represents a geometrical shape as JSON. Geometrical shapes are used to define regions of interest (ROI) on still images -or moving images. - -*gui-elements / gui_attributes*: - -- `Geometry`: not yet implemented. - - _gui_attributes_: No attributes -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes - "maxlength=integer" and "size=integer" are optional. - - _gui_attributes_: - - `maxlength=integer` (optional): The maximum number of characters accepted - - `size=integer` (optional): The size of the input field - -*Example*: - -```json -{ - "name": "hasGeometry", - "super": [ - "hasValue" - ], - "object": "GeomValue", - "labels": "Geometry", - "gui_element": "SimpleText" -} -``` - -###### GeonameValue - -Represents a location ID in geonames.org. The DSP platform uses identifiers provided by -[geonames.org](https://geonames.orgs) to identify geographical locations. - -*gui-elements / gui_attributes*: - -- `Geonames`: The only valid GUI element for _GeonameValue_. It interfaces are with geonames.org and it allows to select - a location. - - _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasGeoname", - "super": [ - "hasValue" - ], - "object": "GeonameValue", - "labels": { - "en": "Geoname" - }, - "gui_element": "Geonames" -} -``` - -###### IntValue - -`"object": "IntValue"` - -Represents an integer value. +- `name` +- `label` +- `properties` +- `resources` -*gui-elements / gui_attributes*: - -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes - "maxlength=integer" and "size=integer" are optional. - - _gui_attributes_: - - `maxlength=integer` (optional): The maximum number of characters accepted - - `size=integer` (optional): The size of the input field -- `Spinbox`: A GUI element for _IntegerValue_. A text field with and "up"- and "down"-button for increment/decrement. - The attributes "max=decimal" and "min=decimal" are optional. - - _gui_attributes_: - - `max=decimal` (optional): Maximal value - - `min=decimal` (optional): Minimal value - -*Example:* - -```json -{ - "name": "hasInteger", - "super": [ - "hasValue" - ], - "object": "IntValue", - "labels": { - "en": "Integer" - }, - "gui_element": "Spinbox", - "gui_attributes": { - "max": 10.0, - "min": 0.0 - } -} -``` - -###### BooleanValue - -`"object": "BooleanValue"` - -Represents a Boolean ("true" or "false). - -*gui-elements / gui_attributes*: - -- `Checkbox`: A GUI element for _BooleanValue_. - - _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasBoolean", - "super": [ - "hasValue" - ], - "object": "BooleanValue", - "labels": { - "en": "Boolean value" - }, - "gui_element": "Checkbox" -} -``` - -###### UriValue - -`"object": "UriValue"` - -Represents an URI - -*gui-elements / gui_attributes*: - -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes - "maxlength=integer" and "size=integer" are optional. - - _gui_attributes_: - - `maxlength=integer` (optional): The maximum number of characters accepted - - `size=integer` (optional): The size of the input field - -*Example:* - -```json -{ - "name": "hasUri", - "super": [ - "hasValue" - ], - "object": "UriValue", - "labels": { - "en": "URI" - }, - "gui_element": "SimpleText", - "gui_attributes": { - "maxlength": 255, - "size": 80 - } -} -``` - -###### IntervalValue - -`"object": "IntervalValue"` - -Represents a time-interval - -*gui-elements / gui_attributes*: - -- `SimpleText`: A GUI element for _TextValue_. A simple text entry box (one line only). The attributes - "maxlength=integer" and "size=integer" are optional. - - _gui_attributes_: - - `maxlength=integer` (optional): The maximum number of characters accepted - - `size=integer` (optional): The size of the input field -- `Interval`: not yet implemented. - - _gui_attributes_: No attributes - -*Example:* - -```json -{ - "name": "hasInterval", - "super": [ - "hasValue" - ], - "object": "IntervalValue", - "labels": { - "en": "Time interval" - }, - "gui_element": "Interval" -} -``` - -###### ListValue - -`"object": "ListValue"` - -Represents a node of a (possibly hierarchical) list - -*gui-elements / gui_attributes*: - -- `Radio`: A GUI element for _ListValue_. A set of radio buttons. This works only with flat lists. - - _gui_attributes_: - - `hlist=` (mandatory): The reference of a [list](#lists) root node -- `List`: A GUI element for _ListValue_. A list of values to select one from. This GUI element should be chosen for - hierarchical lists or flat lists that could be expanded to hierarchical lists in the future. - - _gui_attributes_: - - `hlist=` (mandatory): The reference of a [list](#lists) root node - -*Example:* - -```json -{ - "name": "hasListItem", - "super": [ - "hasValue" - ], - "object": "ListValue", - "labels": { - "en": "List element" - }, - "gui_element": "List", - "gui_attributes": { - "hlist": "treelistroot" - } -} -``` - -###### LinkValue - -`"object": ":"` - -LinkValues do not follow the pattern of the previous data types, because they do not connect to a final value but to -another resource which has to be defined. Thus, the "object" denominates the resource class the link will point to. If -the resource is defined in the same ontology, the name has to be prepended by a ":", if the resource is defined in -another (previously defined) -ontology, the ontology name has to be prepended separated by a colon ":", e.g. -"other-onto:MyResource". The "super"-element has to be "hasLinkTo" or at least derived from "hasLinkTo" (how to derive a -resource or property from another one is not part of this documentation). - -*gui-elements/gui_attributes*: - -- `Searchbox`: Has to be used with _hasLinkTo_ property. Allows searching resources by entering a resource that the given resource - should link to. It has one gui_attribute that indicates how many properties of the found resources should be - indicated. This is mandatory. - - _gui_attributes_: - - `numprops=integer` (optional): While dynamically displaying the search result, the number of properties that - should be displayed. - -*Example:* - -```json -{ - "name": "hasOtherThing", - "super": [ - "hasLinkTo" - ], - "object": ":Thing", - "labels": "Another thing", - "gui_element": "Searchbox" -} -``` - -Like already mentioned before: The following two fields are optional (can be omitted), with the notable exception of -the "super" -clause in case of LinkValues where the super clause is mandatory: - -##### Super - -`"super": ["", ", ...]` - -A property has to be derived from at least one base property. The most generic base property that the DSP offers is -_hasValue_. In addition, the property may be a sub-property of properties defined in external or other ontologies. -External ontologies like `dcterms` or `foaf` must be defined in the "prefix" section. - -In this case the qualified name - including the prefix of the external or internal ontology - has to be given. - -The following base properties are defined by DSP: - -- `hasValue`: This is the most generic base. -- `hasLinkTo`: This value represents a link to another resource. You have to indicate the "_object_" as a prefixed name - that identifies the resource class this link points to (a ":" prepended to the name is sufficient if the resource is - defined in the current ontology). -- `hasColor`: Defines a color value (_ColorValue_) -- `hasComment`: Defines a "standard" comment -- `hasGeometry`: Defines a geometry value (a JSON describing a polygon, circle or rectangle), see _ColorValue_ -- `isPartOf`: A special variant of _hasLinkTo_. It says that an instance of the given resource class is an integral part - of another resource class. E.g. a "page" is part of a "book". -- `isRegionOf`: A special variant of _hasLinkTo_. It means that the given resource class is a "region" of another - resource class. This is typically used to describe regions of interest in images. -- `isAnnotationOf`: A special variant of _hasLinkTo_. It denotes the given resource class as an annotation to another - resource class. -- `seqnum`: An integer that is used to define a sequence number in an ordered set of instances, e.g. the ordering of the - pages in a book (independent of the page naming) - -Example of a `properties` object: - -```json -{ - "properties": [ - { - "name": "schulcode", - "object": "TextValue", - "super": [ - "hasValue" - ], - "labels": { - "de": "Schulcode" - }, - "gui_element": "SimpleText", - "gui_attributes": { - "size": 32, - "maxlength": 128 - } - }, - { - "name": "schulname", - "object": "TextValue", - "super": [ - "hasValue" - ], - "labels": { - "de": "Name der Schule" - }, - "gui_element": "SimpleText", - "gui_attributes": { - "size": 32, - "maxlength": 128 - } - } - ] -} -``` - -#### Resources - -The resource classes are the primary entities of the data model. They are the actual objects inside a terminology space. -A resource class can be seen as a template for the representation of a real object that is represented in the DSP. A -resource class defines properties (_data fields_). For each of these properties a data type as well as the cardinality -has to be provided. - -`"resources": [, , ...]` - -A resource object needs to have the following fields: - -- name -- labels -- super -- cardinalities - -The following field is optional: - -- comments - -##### Name - -`"name": ""` - -A name for the resource, e.g. "Book", "Manuscript", "Person". It should be in the form of -a [xsd:NCNAME](https://www.w3.org/TR/xmlschema11-2/#NCName). This means a string without blanks or special characters -but `-` and `_` are allowed (although not as first character). - -##### Labels - -`"labels": {"": "", ...}` - -Collection of `labels` for the resource as strings with language tag (currently "en", "de", "fr" -and "it" are supported). - -##### Super - -`"super": ["", "", ...]` - -A resource is always derived from at least one other resource. The most generic resource class for DSP is `Resource`. A -resource may be derived from resources defined in external ontologies. - -The following predefined resources are provided by DSP: - -- `Resource`: A generic resource that represents an item from the real world -- `StillImageRepresentation`: An object that is connected to a still image -- `TextRepresentation`: An object that is connected to an (external) text (not yet implemented) -- `AudioRepresentation`: An object representing audio data (not yet implemented) -- `DDDRepresentation`: An object representing a 3-D representation (not yet implemented) -- `DocumentRepresentation`: An object representing an opaque document (e.g. a PDF) -- `MovingImageRepresentation`: An object representing a moving image (video, film) -- `ArchiveRepresentation`: An object representing a archive file (e.g. Zip) -- `Annotation`: A predefined annotation object. It has automatically the following predefined properties defined: - - `hasComment` (1-n) - - `isAnnotationOf` (1) -- `LinkObj`: A resource class linking together several other, generic, resource classes. The class has the following - properties: - - `hasComment` (1-n) - - `hasLinkTo` (1-n) -- `Region`: Represents a simple region. The class has the following properties: - - `hasColor` (1) - - `isRegionOf` (1) - - `hasGeometry` (1) - - `isRegionOf` (1) - - `hasComment` (0-n) - -##### Cardinalities - -`"cardinalities": [...]` - -An array that contains information about the relation between resources and properties. It tells what properties a -resource can have as well as how many times the relation is established. - -- `cardinalities`: Array of references to the properties that the resource may hold including the cardinality. A - cardinality has the following properties: - - `propname`: The name of the property. If it's used in the form `:my_propname`, the current ontology is referenced. - Otherwise, the prefix of the ontology the property is part of has to be used. - - `gui_order`: An integer number which will help the GUI to display the properties in the desired order (optional) - - `cardinality`: Indicates how often a given property may occur. The possible values are: - - `"1"`: exactly once (mandatory one value and only one) - - `"0-1"`: The value may be omitted, but can occur only once. - - `"1-n"`: At least one value must be present, but multiple values may be present. - - `"0-n"`: The value may be omitted, but may also occur multiple times. - -##### Comments - -`"comments": { "": "", "": "", ... }` - -Comments with language tags. The `comments` element is optional. Currently, "de", "en", "fr" and "it" are supported. - -Example for a resource definition: - -```json -{ - "resources": [ - { - "name": "Schule", - "labels": { - "de": "Schule", - "en": "School", - "fr": "Ecole", - "it": "Scuola" - }, - "super": "Resource", - "comments": { - "de": "Ein Kommentar", - "en": "A comment", - "fr": "Une commentaire", - "it": "Un commento" - }, - "cardinalities": [ - { - "propname": ":schulcode", - "gui_order": 1, - "cardinality": "1" - }, - { - "propname": ":schulname", - "gui_order": 2, - "cardinality": "1" - }, - { - "propname": ":bildungsgang", - "gui_order": 3, - "cardinality": "1" - } - ] - } - ] -} -``` +A detailed description of `ontologies` can be found [here](dsp-tools-create-ontologies.md) ## Fully fleshed out example ontology diff --git a/docs/dsp-tools-xmlupload.md b/docs/dsp-tools-xmlupload.md index d9b95aec9..6bf0df73f 100644 --- a/docs/dsp-tools-xmlupload.md +++ b/docs/dsp-tools-xmlupload.md @@ -189,8 +189,8 @@ Example for a property element of type text (``) with two value eleme ``` -| ⚠ Look out | -|:----------| +| ⚠ Look out | +| :--------------------------------------------------------------------------------------------------------------------------------------------- | | In case of a cardinality 1-n, multiple `` tags have to be created inside the `` tag (do not use multiple `` tags). | The following property elements exist: @@ -617,14 +617,15 @@ following abbreviations describe this form: 0001 is the lexical representation of the year 1 of the Common Era (also known as 1 AD). The value cannot be 0000. - `mm`: a two-digit numeral that represents the month - `dd`: a two-digit numeral that represents the day -- `hh`: a two-digit numeral (with leading zeros as required) that represents the hours. The value must be between -14 - and +14, inclusive. +- `hh`: a two-digit numeral representing the hours. Must be between 0 and 23 - `mm`: a two-digit numeral that represents the minutes - `ss`: a two-digit numeral that represents the seconds - `ssssssssssss`: If present, a 1-to-12-digit numeral that represents the fractional seconds (optional) -- `zzzzzz`: represents the time zone (required). Each part of the datetime value that is expressed as a numeric value is - constrained to the maximum value within the interval that is determined by the next higher part of the datetime value. - For example, the day value can never be 32 and cannot be 29 for month 02 and year 2002 (February 2002). +- `zzzzzz`: represents the time zone (required). + +Each part of the datetime value that is expressed as a numeric value is constrained to the maximum value within the +interval that is determined by the next higher part of the datetime value. +For example, the day value can never be 32 and cannot be 29 for month 02 and year 2002 (February 2002). The timezone is defined as follows: diff --git a/knora/dsplib/models/connection.py b/knora/dsplib/models/connection.py index 6b02e734d..8babf45cd 100644 --- a/knora/dsplib/models/connection.py +++ b/knora/dsplib/models/connection.py @@ -69,7 +69,7 @@ def get_token(self) -> str: def token(self) -> str: return self._token - def start_logging(self): + def start_logging(self) -> None: self._log = True def stop_logging(self): diff --git a/knora/dsplib/models/helpers.py b/knora/dsplib/models/helpers.py index 72faaab9e..615f0bdca 100644 --- a/knora/dsplib/models/helpers.py +++ b/knora/dsplib/models/helpers.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import Enum, unique from traceback import format_exc -from typing import NewType, List, Dict, Optional, Any, Union, Pattern +from typing import NewType, List, Dict, Optional, Any, Tuple, Union, Pattern from pystrict import strict @@ -26,7 +26,7 @@ class OntoInfo: ContextType = NewType("ContextType", Dict[str, OntoInfo]) -def LINE(): +def LINE() -> int: return sys._getframe(1).f_lineno @@ -94,7 +94,7 @@ def __init__(self, context: 'Context'): self._prefixes = [x for x in self._context.context] self._index = 0 - def __next__(self): + def __next__(self) -> Tuple[Optional[str], Optional[OntoInfo]]: if len(self._context.context) == 0 and self._index == 0: return None, None elif self._index < len(self._context.context): @@ -112,9 +112,9 @@ class Context: """ _context: ContextType _rcontext: Dict[str, str] - _exp: Pattern + _exp: Pattern[str] - common_ontologies: ContextType = { + common_ontologies = ContextType({ "foaf": OntoInfo("http://xmlns.com/foaf/0.1/", False), "dc": OntoInfo("http://purl.org/dc/elements/1.1/", False), "dcterms": OntoInfo("http://purl.org/dc/terms/", False), @@ -123,19 +123,19 @@ class Context: "bibtex": OntoInfo("http://purl.org/net/nknouf/ns/bibtex", True), "bibo": OntoInfo("http://purl.org/ontology/bibo/", False), "cidoc": OntoInfo("http://purl.org/NET/cidoc-crm/core", True) - } + }) - knora_ontologies: ContextType = { + knora_ontologies = ContextType({ "knora-api": OntoInfo("http://api.knora.org/ontology/knora-api/v2", True), "salsah-gui": OntoInfo("http://api.knora.org/ontology/salsah-gui/v2", True) - } + }) - base_ontologies: ContextType = { + base_ontologies = ContextType({ "rdf": OntoInfo("http://www.w3.org/1999/02/22-rdf-syntax-ns", True), "rdfs": OntoInfo("http://www.w3.org/2000/01/rdf-schema", True), "owl": OntoInfo("http://www.w3.org/2002/07/owl", True), "xsd": OntoInfo("http://www.w3.org/2001/XMLSchema", True) - } + }) def __is_iri(self, val: str) -> bool: """ @@ -155,40 +155,26 @@ def __init__(self, context: Optional[Dict[str, str]] = None): ontology-iri *must* end with "#"! :param context: A dict of prefix - ontology-iri pairs """ - # # regexp to test for a complete IRI (including fragment identifier) - # self._exp = re.compile("^(http)s?://([\\w\\.\\-~]+)?(:\\d{,6})?(/[\\w\\-~]+)*(#[\\w\\-~]*)?") - + self._context = ContextType({}) + + # add ontologies from context, if any if context: - cleaned_input: Dict[str, str] = {prefix: onto for (prefix, onto) in context.items() - if self.base_ontologies.get(prefix) is None and self.knora_ontologies.get( - prefix) is None} - self._context = {} - for prefix, onto in cleaned_input.items(): - self._context[prefix] = OntoInfo(onto[:-1], True) if onto.endswith('#') else OntoInfo(onto, False) - # - # we always want the base ontologies/prefixes included in the context - # - for cc in self.base_ontologies.items(): - if self._context.get(cc[0]) is None: - self._context[cc[0]] = cc[1] - # - # we always want the knora ontologies/prefixes included in the context - # - for cc in self.knora_ontologies.items(): - if self._context.get(cc[0]) is None: - self._context[cc[0]] = cc[1] - else: - self._context = { - "rdf": OntoInfo("http://www.w3.org/1999/02/22-rdf-syntax-ns", True), - "rdfs": OntoInfo("http://www.w3.org/2000/01/rdf-schema", True), - "owl": OntoInfo("http://www.w3.org/2002/07/owl", True), - "xsd": OntoInfo("http://www.w3.org/2001/XMLSchema", True), - "knora-api": OntoInfo("http://api.knora.org/ontology/knora-api/v2", True), - "salsah-gui": OntoInfo("http://api.knora.org/ontology/salsah-gui/v2", True) - } - self._rcontext = dict(map(lambda x: (x[1].iri, x[0]), self._context.items())) + for prefix, onto in context.items(): + self._context[prefix] = OntoInfo(onto.removesuffix('#'), onto.endswith('#')) + + # add standard ontologies (rdf, rdfs, owl, xsl) + for k, v in self.base_ontologies.items(): + if not self._context.get(k): + self._context[k] = v + + # add DSP-API internal ontologies (knora-api, salsah-gui) + for k, v in self.knora_ontologies.items(): + if not self._context.get(k): + self._context[k] = v + + self._rcontext = {v.iri: k for k, v in self._context.items()} def __len__(self) -> int: return len(self._context) @@ -196,7 +182,7 @@ def __len__(self) -> int: def __getitem__(self, key: str) -> OntoInfo: return self._context[key] - def __setitem__(self, key: str, value: OntoInfo): + def __setitem__(self, key: str, value: OntoInfo) -> None: self._context[key] = value self._rcontext[value.iri] = key @@ -283,7 +269,7 @@ def iri_from_prefix(self, prefix: str) -> Optional[str]: def prefix_from_iri(self, iri: str) -> Optional[str]: """ - Get the IRI from a full context that has or has not a a trailing "#". It first searches in the normal list + Get the IRI from a full context that has or has not a trailing "#". It first searches in the normal list of contexted. If the iri is not found there, it looks in the list common (external) ontologies. If the ontology is found there, this ontology is added to the list of known ontology and it's prefix is returned. If nothing is found, None is returns diff --git a/knora/dsplib/models/project.py b/knora/dsplib/models/project.py index fd6539a69..36776c8c6 100644 --- a/knora/dsplib/models/project.py +++ b/knora/dsplib/models/project.py @@ -515,7 +515,7 @@ def getAllProjects(con: Connection) -> List['Project']: raise BaseError("Request got no projects!") return list(map(lambda a: Project.fromJsonObj(con, a), result['projects'])) - def print(self): + def print(self) -> None: """ print info to stdout diff --git a/knora/dsplib/models/resourceclass.py b/knora/dsplib/models/resourceclass.py index 58a407669..3e7d7bb86 100644 --- a/knora/dsplib/models/resourceclass.py +++ b/knora/dsplib/models/resourceclass.py @@ -669,12 +669,11 @@ def toJsonObj(self, lastModificationDate: LastModificationDate, action: Actions, def resolve_resref(resref: str): tmp = resref.split(':') if len(tmp) > 1: - if tmp[0]: + if tmp[0] and self._context.iri_from_prefix(tmp[0]) != self._ontology_id: self._context.add_context(tmp[0]) return {"@id": resref} # fully qualified name in the form "prefix:name" else: - return {"@id": self._context.prefix_from_iri(self._ontology_id) + ':' + tmp[ - 1]} # ":name" in current ontology + return {"@id": self._context.prefix_from_iri(self._ontology_id) + ':' + tmp[1]} # ":name" in current ontology else: return {"@id": "knora-api:" + resref} # no ":", must be from knora-api! diff --git a/knora/dsplib/schemas/ontology.json b/knora/dsplib/schemas/ontology.json index 5fe7eb707..df088c44d 100644 --- a/knora/dsplib/schemas/ontology.json +++ b/knora/dsplib/schemas/ontology.json @@ -221,12 +221,14 @@ }, "properties": { "type": "array", + "minItems": 1, "items": { "$ref": "#/definitions/property" } }, "resources": { "type": "array", + "minItems": 1, "items": { "$ref": "#/definitions/resource" } @@ -482,6 +484,7 @@ }, "keywords": { "type": "array", + "minItems": 1, "items": { "type": "string" } @@ -512,6 +515,7 @@ }, "ontologies": { "type": "array", + "minItems": 1, "items": { "$ref": "#/definitions/ontology" } @@ -521,6 +525,7 @@ "shortcode", "shortname", "longname", + "descriptions", "ontologies", "keywords" ], diff --git a/knora/dsplib/utils/onto_create_lists.py b/knora/dsplib/utils/onto_create_lists.py index b11c4a9d3..e0cc86cc3 100644 --- a/knora/dsplib/utils/onto_create_lists.py +++ b/knora/dsplib/utils/onto_create_lists.py @@ -1,5 +1,5 @@ import json -from typing import List +from typing import Any, Dict, List from .expand_all_lists import expand_lists_from_excel from .onto_validate import validate_ontology @@ -8,7 +8,7 @@ from ..models.project import Project -def list_creator(con: Connection, project: Project, parent_node: ListNode, nodes: List[dict]): +def list_creator(con: Connection, project: Project, parent_node: ListNode, nodes: List[Dict[Any, Any]]) -> List[Dict[Any, Any]]: """ Creates the list on the DSP server @@ -35,7 +35,7 @@ def list_creator(con: Connection, project: Project, parent_node: ListNode, nodes def create_lists(input_file: str, lists_file: str, server: str, user: str, password: str, verbose: bool, - dump: bool = False): + dump: bool = False) -> Dict[str, Any]: """ Creates the lists on the DSP server diff --git a/knora/dsplib/utils/onto_create_ontology.py b/knora/dsplib/utils/onto_create_ontology.py index 0c7d5ac2e..a4ec1d0ea 100644 --- a/knora/dsplib/utils/onto_create_ontology.py +++ b/knora/dsplib/utils/onto_create_ontology.py @@ -82,7 +82,7 @@ def create_ontology(input_file: str, con.start_logging() # read the prefixes of external ontologies that may be used - context = Context(data_model["prefixes"]) + context = Context(data_model.get("prefixes") or {}) # create or update the project project = None @@ -347,7 +347,7 @@ def create_ontology(input_file: str, newontology.lastModificationDate = last_modification_date except BaseError as err: print("Creating resource class failed:", err.message) - exit(105) + exit(1) newresclasses[newresclass.id] = newresclass if verbose: print("New resource class:") @@ -378,7 +378,8 @@ def create_ontology(input_file: str, if tmp[0]: object = propclass["object"] # fully qualified name else: - newontology.print() + if verbose: + newontology.print() object = newontology.name + ':' + tmp[1] else: object = "knora-api:" + propclass["object"] diff --git a/mkdocs.yml b/mkdocs.yml index ac03ffbfb..646d567ba 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,31 +5,32 @@ repo_name: dasch-swiss/dsp-tools edit_uri: blob/main/docs/ copyright: "© 2017 - Data and Service Center for the Humanities (DaSCH)" - nav: - - Overview: index.md - - Installation and usage: dsp-tools-usage.md - - JSON data model format: dsp-tools-create.md - - Bulk data import: dsp-tools-xmlupload.md - - Excel file processing: dsp-tools-excel.md - - Information for developers: dsp-tools-information-for-developers.md - - Changelog: changelog.md + - Overview: index.md + - Installation and usage: dsp-tools-usage.md + - JSON data model format: + - Overview: dsp-tools-create.md + - Ontologies: dsp-tools-create-ontologies.md + - Bulk data import: dsp-tools-xmlupload.md + - Excel file processing: dsp-tools-excel.md + - Information for developers: dsp-tools-information-for-developers.md + - Changelog: changelog.md theme: name: material - logo: 'assets/images/dasch-icon-white.svg' - favicon: 'assets/images/dasch-favicon.ico' + logo: "assets/images/dasch-icon-white.svg" + favicon: "assets/images/dasch-favicon.ico" palette: - primary: 'deep blue' - accent: 'deep blue' + primary: "deep blue" + accent: "deep blue" feature: tabs: false extra_css: - - 'assets/style/theme.css' + - "assets/style/theme.css" markdown_extensions: - - attr_list + - attr_list plugins: - search