Merge remote-tracking branch 'origin/new_schema'
This commit is contained in:
commit
6dfa3da0db
|
@ -2,6 +2,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
|
||||
# Changelog for gCube Catalogue (gCat) Service
|
||||
|
||||
## [v2.5.1-SNAPSHOT]
|
||||
|
||||
- Started to use improved schema version
|
||||
|
||||
|
||||
## [v2.5.0]
|
||||
|
||||
|
|
|
@ -0,0 +1,484 @@
|
|||
---
|
||||
title: Welcome to gCube Catalogue Service (aka gCat) documentation
|
||||
---
|
||||
|
||||
gCat is a RESTful application which exposes operations via REST-API.
|
||||
|
||||
See the available [REST-API docs](../api-docs/index.html).
|
||||
|
||||
Base URL
|
||||
========
|
||||
|
||||
In the production environment, its current value is
|
||||
<https://api.d4science.org/gcat>
|
||||
|
||||
Authorization
|
||||
=============
|
||||
|
||||
D4Science adopts state-of-the-art industry standards for authentication
|
||||
and authorization. Specifically, the implementation fully adopts [OIDC
|
||||
(OpenID Connect)](https://openid.net/connect) for authentication and UMA
|
||||
2 (User-Managed Authorization) for authorization flows. [JSON Web Token
|
||||
(JWT) Access token](https://jwt.io/) are used for both authentication
|
||||
and authorization.
|
||||
|
||||
Obtain your Bearer token here:
|
||||
<https://dev.d4science.org/how-to-access-resources>
|
||||
|
||||
Service
|
||||
=======
|
||||
|
||||
You can call the methods of the Web Service by writing your own REST
|
||||
client application or using existing REST client plugins.
|
||||
|
||||
HTTP Statuses
|
||||
-------------
|
||||
|
||||
Any successful operation returns *200 OK* HTTP status code. The create
|
||||
operation returns *201 Created*. Any Background operation returns *202
|
||||
Accepted*. Any operation which does not provide any content return *204
|
||||
No Content*.
|
||||
|
||||
The most common error status a client can obtain are:
|
||||
|
||||
- **400 Bad Request** used to indicate a clients error
|
||||
<https://tools.ietf.org/html/rfc7231#section-6.5.1>;
|
||||
- **401 Unauthorized** used to indicate that the client does not
|
||||
provide the authorization token in the HTTP Header or the client has
|
||||
not enough right to perform such request
|
||||
<https://tools.ietf.org/html/rfc7235#section-3.1>;
|
||||
- **404 Not Found** used to indicate that the requested instance does
|
||||
not exist <https://tools.ietf.org/html/rfc7231#section-6.5.4>;
|
||||
- **405 Method Not Allowed** the used HTTP method is not supported for
|
||||
the requested URL
|
||||
<https://tools.ietf.org/html/rfc7231#section-6.5.5>. The response
|
||||
contains the *Allow* HTTP Header indicating the supported HTTP
|
||||
method for such URL
|
||||
<https://tools.ietf.org/html/rfc7231#section-7.4.1>;
|
||||
- **409 Conflict** the request could not be completed due to a
|
||||
conflict with the current state of the target resource (e.g. the
|
||||
name of the resource already exists)
|
||||
<https://tools.ietf.org/html/rfc7231#section-6.5.8>;
|
||||
- **500 Internal Server Error** indicate a server failure
|
||||
<https://tools.ietf.org/html/rfc7231#section-6.6.1>.
|
||||
|
||||
You can find a complete list of HTTP Status at
|
||||
<https://httpstatuses.com/>
|
||||
|
||||
If you get a *500 Internal Server Error*, please report it in the [gCube
|
||||
ticketing system](https://support.d4science.org).
|
||||
|
||||
Please use this checklist before reporting an error:
|
||||
|
||||
- Replicate the request;
|
||||
- The failure could be temporal due to network error, server issue and
|
||||
many other temporal issues. For this reason, please retry the
|
||||
request after a certain amount of time before reporting the issue;
|
||||
- indicate how to replicate the error;
|
||||
- indicate the time when the error occurred (this simplifies
|
||||
identifying the issue).
|
||||
|
||||
HTTP Methods
|
||||
------------
|
||||
|
||||
gCat is a pure RESTful service. It uses standard HTTP Methods to perform
|
||||
listing of collections and CRUD (Create Read Update Delete) operations
|
||||
on instances.
|
||||
|
||||
:::{table} Supported operations
|
||||
:align: center
|
||||
:widths: grid
|
||||
|
||||
|
||||
| Operation | HTTP Method | URL | Success HTTP Status | Safe | Idempotent |
|
||||
|-----------|-------------|-----|---------------------|------|------------|
|
||||
| **Supported<br/>HTTP Methods** | OPTIONS | /{COLLECTION} | 204 No Content | Y | Y |
|
||||
| **List** | GET | /{COLLECTION} | 200 OK | Y | Y |
|
||||
| **Count** | GET | /{COLLECTION}?count=true | 200 OK | Y | Y |
|
||||
| **Exists** | HEAD | /{COLLECTION} | 204 No Content | Y | Y |
|
||||
| **Create** | POST | /{COLLECTION} | 201 Created | N | N |
|
||||
| **Supported<br/>HTTP Methods** | OPTIONS | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | Y | Y |
|
||||
| **Exist** | HEAD | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | Y | Y |
|
||||
| **Read** | GET | /{COLLECTION}/{INSTANCE_ID} | 200 OK | Y | Y |
|
||||
| **Update** | PUT | /{COLLECTION}/{INSTANCE_ID} | 200 OK | N | Y |
|
||||
| **Patch** | PATCH | /{COLLECTION}/{INSTANCE_ID} | 200 OK | N | Y |
|
||||
| **Delete** | DELETE | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | N | N |
|
||||
| **Purge** | PURGE | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | N | N |
|
||||
| **Purge** | DELETE | /{COLLECTION}/{INSTANCE_ID}?purge=true | 204 No Content | N | N |
|
||||
|
||||
|
||||
### About URL
|
||||
|
||||
The presented URL uses the following convention:
|
||||
|
||||
- **{COLLECTION}** is the plural name of the entity type;
|
||||
- **{INSTANCE\_ID}** is an identification that enables univocally
|
||||
identifying the instance in the collection.
|
||||
|
||||
### About Safety and Idempotency properties
|
||||
|
||||
- A method is *Safe* if it does not produce any side effects. \"This
|
||||
does not prevent an implementation from including behaviour that is
|
||||
potentially harmful, that is not entirely read-only, or that causes
|
||||
side effects while invoking a safe method\"
|
||||
<https://tools.ietf.org/html/rfc7231#section-4.2.1>;
|
||||
- A method is *Idempotent* if the same operation repeated multiple
|
||||
times has the same side effect than using it one time. \"repeating
|
||||
the request will have the same intended effect, even if the original
|
||||
request succeeded, though the response might differ\"
|
||||
<https://tools.ietf.org/html/rfc7231#section-4.2.2>.
|
||||
|
||||
You can find more information about HTTP Methods at
|
||||
<https://restfulapi.net/http-methods/>
|
||||
|
||||
### Uncommon HTTP Methods
|
||||
|
||||
- PATCH method allows to perform a differential update (i.e. an update
|
||||
which provides only the differences and not the whole new
|
||||
representation);
|
||||
- PURGE method is not a standard but is widely used in service which
|
||||
requires this action (e.g.
|
||||
[Varnish](https://varnish-cache.org/docs/3.0/tutorial/purging.html),
|
||||
[Squid](https://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache.3F)).
|
||||
gCat provides support for this method, but to support a wider range
|
||||
of clients, it also provides the Purge action via *DELETE* with the
|
||||
additional get parameter `purge=true`.
|
||||
|
||||
Content-Type
|
||||
------------
|
||||
|
||||
Any request must contain an indication of the interesting content type.
|
||||
|
||||
The client must specify the **Accept** HTTP Header for any operation
|
||||
returning a result.
|
||||
|
||||
``` {.rest}
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
For any operation sending content to the service, it is necessary to
|
||||
specify the **Content-Type** HTTP Header.
|
||||
|
||||
``` {.rest}
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
The service accepts and returns only JSON objects.
|
||||
|
||||
[Profile Collection](../api-docs/resource\_Profile.html) instead can be
|
||||
manipulated in XML only.
|
||||
|
||||
Collections
|
||||
-----------
|
||||
|
||||
The following collections are available to any user. Catalogue-Editor or
|
||||
above can invoke Non-safe methods only.
|
||||
|
||||
- [Item Collection](../api-docs/resource_Item.html);
|
||||
- [Resource Collection](../api-docs/resource_Resource.html);
|
||||
- [Profile Collection](../api-docs/resource_Profile.html);
|
||||
- [Namespace Collection](../api-docs/resource_Namespace.html);
|
||||
- [License Collection](../api-docs/resource_License.html);
|
||||
- [Trash Collection](../api-docs/resource_Trash.html);
|
||||
|
||||
The following collections are available for Catalogue-Admins or above
|
||||
only:
|
||||
|
||||
- [Group Collection](../api-docs/resource_Group.html);
|
||||
- [Organization Collection](../api-docs/resource_Organization.html);
|
||||
- [User Collection](../api-docs/resource_User.html);
|
||||
- [Configuration Collection](../api-docs/resource_Configuration.html).
|
||||
|
||||
An overview of the available collections is available at
|
||||
[../api-docs/index.html](../api-docs/index.html);
|
||||
|
||||
Roles
|
||||
-----
|
||||
|
||||
Any user has one or more roles in the catalogue. Only the VRE Manager
|
||||
can assign roles to VRE users.
|
||||
|
||||
The catalogue uses the following hierarchic roles:
|
||||
|
||||
**Catalogue-Member**:
|
||||
|
||||
: A user with such a role is mainly capable of listing and reading
|
||||
items;
|
||||
|
||||
**Catalogue-Editor**:
|
||||
|
||||
: A user with such a role is capable of managing the items he/she
|
||||
creates and capable of using other safe APIs;
|
||||
|
||||
**Catalogue-Admin**:
|
||||
|
||||
: A user with such a role is capable of administrating many aspects of
|
||||
the catalogue;
|
||||
|
||||
**Catalogue-Manager**:
|
||||
|
||||
: A user with such a role can use all the APIs exposed by the service
|
||||
except item moderation APIs (e.g. approve, reject, \...).
|
||||
|
||||
Another role that is not in the role hierarchy:
|
||||
|
||||
**Catalogue-Moderator**:
|
||||
|
||||
: A user with such a role is capable of invoking the item moderation
|
||||
APIs.
|
||||
|
||||
::: {.tip}
|
||||
::: {.title}
|
||||
Tip
|
||||
:::
|
||||
:::
|
||||
|
||||
Please note that not all catalogues are moderated.
|
||||
|
||||
Moderated Catalogues
|
||||
====================
|
||||
|
||||
Any catalogues can be declared as moderated. This means that, a
|
||||
**Catalogue-Moderator** must approve any submitted items to make them
|
||||
available to the other users of the catalogue.
|
||||
|
||||
In a moderated catalogue, an item can be in the following states:
|
||||
|
||||
**pending**:
|
||||
|
||||
: The item published by any allowed author (a Catalogue-Editor or
|
||||
above) but not available to the other users of the catalogue. A
|
||||
Catalogue-Moderator has to approve or reject it;
|
||||
|
||||
**approved**:
|
||||
|
||||
: A Catalogue-Moderator has approved the item published by any allowed
|
||||
users;
|
||||
|
||||
**rejected**:
|
||||
|
||||
: A Catalogue-Moderator has rejected the item published by any allowed
|
||||
users.
|
||||
|
||||
The following are the moderation operations that an allowed user can
|
||||
perform on an item. To present the moderation operations, we use the
|
||||
following convention:
|
||||
|
||||
> `initial_state` \-\--**operation** (*User/Role performing the
|
||||
> operation*)\-\--\> `final_state`
|
||||
|
||||
`initial_state` can be `none`, meaning the item does not exist.
|
||||
|
||||
The following are the allowed moderation operation on an item
|
||||
|
||||
> `none` \-\--**create** (*Author*)\-\--\> `pending`
|
||||
>
|
||||
> `pending` \-\--**reject** (*Catalogue-Moderator*)\-\--\> `rejected`
|
||||
>
|
||||
> `pending` \-\--**approve** (*Catalogue-Moderator*)\-\--\> `approved`
|
||||
>
|
||||
> `rejected` \-\--**update** (*Author*)\-\--\> `pending`
|
||||
>
|
||||
> `approved` \-\--**update** (*Author*)\-\--\> `pending`
|
||||
|
||||
Please check the table below whcih summarise the item collection
|
||||
operation and the allowed users/roles.
|
||||
|
||||
In a moderated catalogue, both the Catalogue-Moderators and the item
|
||||
author can send messages to discuss the approval process of the item.
|
||||
The messages are related to a specific item. Any Catalogue-Moderators
|
||||
receive a message sent by an Author. The author receives a message sent
|
||||
by a Catalogue-Moderator as well as the other Catalogue-Moderators (if
|
||||
any).
|
||||
|
||||
Messages can be sent both with an action which changes the status of the
|
||||
item or as explicit action which does not change the status of the item:
|
||||
|
||||
> `pending` \-\--**message** (*Author OR Catalogue-Moderator*)\-\--\>
|
||||
> `pending`
|
||||
>
|
||||
> `rejected` \-\--**message** (*Author OR Catalogue-Moderator*)\-\--\>
|
||||
> `rejected`
|
||||
>
|
||||
> `approved` \-\--**message** (*Author OR Catalogue-Moderator*)\-\--\>
|
||||
> `approved`
|
||||
|
||||
The following table summarize the allowed/forbidden operations depending
|
||||
on: the role of the user and the state of the item.
|
||||
|
||||
The Moderation process has associated notification to authors and
|
||||
Catalogue-Moderators. Please note that the user who has acted is not
|
||||
self-notified, e.g. approve operation made by a Catalogue-Moderator
|
||||
notifies the item author and the other Catalogue-Moderators of the VRE.
|
||||
|
||||
The following table summarises the addressee of the notification for any
|
||||
action.
|
||||
|
||||
Java Client
|
||||
===========
|
||||
|
||||
We provide the following Java Client out-of-the-box.
|
||||
|
||||
> ::: {.tip}
|
||||
> ::: {.title}
|
||||
> Tip
|
||||
> :::
|
||||
>
|
||||
> If you\'re coding in Java, it is recommended that you use this Java
|
||||
> Client.
|
||||
> :::
|
||||
|
||||
**Maven Coordinates**
|
||||
|
||||
``` {.xml}
|
||||
<groupId>org.gcube.data-catalogue</groupId>
|
||||
<artifactId>gcat-client</artifactId>
|
||||
<version>[2.2.0, 3.0.0-SNAPSHOT)</version>
|
||||
```
|
||||
|
||||
**Methods Result**
|
||||
|
||||
The service exposes [its methods](../api-docs/index.html) using a
|
||||
standard naming approach. Moreover, they accept (in the case of HTTP
|
||||
POST/PUT methods) JSON objects.
|
||||
|
||||
> ::: {.important}
|
||||
> ::: {.title}
|
||||
> Important
|
||||
> :::
|
||||
>
|
||||
> The result of all methods is always a JSON object as per below:
|
||||
> :::
|
||||
|
||||
``` {.javascript}
|
||||
{
|
||||
"rating": 0.0,
|
||||
"license_title": "Creative Commons Attribution Share-Alike 4.0",
|
||||
"maintainer": "Frosini Luca",
|
||||
"relationships_as_object": [],
|
||||
"private": false,
|
||||
"maintainer_email": "luca.frosini@isti.cnr.it",
|
||||
"num_tags": 1,
|
||||
"id": "17051d86-c127-4928-9296-d3d7590161fe",
|
||||
"metadata_created": "2022-10-17T12:45:53.118318",
|
||||
"metadata_modified": "2022-10-18T10:30:03.362756",
|
||||
"author": "Frosini Luca",
|
||||
"author_email": "luca.frosini@isti.cnr.it",
|
||||
"state": "active",
|
||||
"version": null,
|
||||
"creator_user_id": "f1b0265c-9983-4f97-a7b6-be3cc0544b27",
|
||||
"type": "dataset",
|
||||
"resources": [],
|
||||
"num_resources": 0,
|
||||
"tags": [
|
||||
{
|
||||
"vocabulary_id": null,
|
||||
"state": "active",
|
||||
"display_name": "Test",
|
||||
"id": "fec9de86-51a2-41b0-aef4-ba06eb39e16d",
|
||||
"name": "Test"
|
||||
}
|
||||
],
|
||||
"groups": [],
|
||||
"license_id": "CC-BY-SA-4.0",
|
||||
"relationships_as_subject": [],
|
||||
"organization": {
|
||||
"description": "",
|
||||
"created": "2016-05-30T11:30:41.710079",
|
||||
"title": "devVRE",
|
||||
"name": "devvre",
|
||||
"is_organization": true,
|
||||
"state": "active",
|
||||
"image_url": "",
|
||||
"revision_id": "a7eee485-a6d5-4a7b-8f73-b0ed999d5b03",
|
||||
"type": "organization",
|
||||
"id": "3571cca5-b0ae-4dc6-b791-434a8e062ce5",
|
||||
"approval_status": "approved"
|
||||
},
|
||||
"name": "my_test_item_devvre",
|
||||
"isopen": true,
|
||||
"url": "http://www.d4science.org",
|
||||
"notes": "A test item of Luca Frosini",
|
||||
"extras": [
|
||||
{
|
||||
"key": "Item URL",
|
||||
"value": "https://data.dev.d4science.org/ctlg/devVRE/my_test_item_devvre"
|
||||
},
|
||||
{
|
||||
"key": "Language",
|
||||
"value": "EN"
|
||||
},
|
||||
{
|
||||
"key": "system:cm_item_status",
|
||||
"value": "approved"
|
||||
},
|
||||
{
|
||||
"key": "system:cm_item_visibility",
|
||||
"value": "public"
|
||||
},
|
||||
{
|
||||
"key": "system:type",
|
||||
"value": "EmptyProfile"
|
||||
}
|
||||
],
|
||||
"license_url": "https://creativecommons.org/licenses/by-sa/4.0/",
|
||||
"ratings_count": 0,
|
||||
"title": "My Test Item",
|
||||
"revision_id": "bc0d1f2a-4e97-4810-b951-8b72e8279719"
|
||||
}
|
||||
```
|
||||
|
||||
*Inputs are automatically validated before the request is served.*
|
||||
|
||||
**Usage examples**
|
||||
|
||||
- Example 1
|
||||
|
||||
``` {.java}
|
||||
import org.gcube.gcat.client.Item;
|
||||
|
||||
// count item number
|
||||
Item item = new Item();
|
||||
int count = item.count();
|
||||
...
|
||||
```
|
||||
|
||||
Service Discovery on IS
|
||||
=======================
|
||||
|
||||
The service can be discovered in the gCore IS as gCore Endpoint with the
|
||||
following parameter:
|
||||
|
||||
``` {.xml}
|
||||
<ServiceClass>org.gcube.data-catalogue</ServiceClass>
|
||||
<ServiceName>gcat</ServiceName>
|
||||
```
|
||||
|
||||
The service can be discovered in the Facet Based IS as EService with the
|
||||
following json query:
|
||||
|
||||
``` {.json}
|
||||
{
|
||||
"@class": "EService",
|
||||
"consistsOf": [
|
||||
{
|
||||
"@class": "IsIdentifiedBy",
|
||||
"target": {
|
||||
"@class": "SoftwareFacet",
|
||||
"group": "org.gcube.data-catalogue",
|
||||
"name": "gcat"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Service Maven Coordinates
|
||||
=========================
|
||||
|
||||
The maven coordinates of gCat service are:
|
||||
|
||||
``` {.xml}
|
||||
<groupId>org.gcube.data-catalogue</groupId>
|
||||
<artifactId>gcat</artifactId>
|
||||
```
|
17
pom.xml
17
pom.xml
|
@ -12,7 +12,7 @@
|
|||
<groupId>org.gcube.data-catalogue</groupId>
|
||||
<artifactId>gcat</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.5.0</version>
|
||||
<version>2.5.1-SNAPSHOT</version>
|
||||
<name>gCube Catalogue (gCat) Service</name>
|
||||
<description>
|
||||
This service allows any client to publish on the gCube Catalogue.
|
||||
|
@ -35,7 +35,7 @@
|
|||
<dependency>
|
||||
<groupId>org.gcube.distribution</groupId>
|
||||
<artifactId>gcube-smartgears-bom</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<version>2.5.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
@ -62,7 +62,7 @@
|
|||
<dependency>
|
||||
<groupId>org.gcube.data-catalogue</groupId>
|
||||
<artifactId>gcat-api</artifactId>
|
||||
<version>[2.3.2, 3.0.0-SNAPSHOT)</version>
|
||||
<version>[2.3.2-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.social-networking</groupId>
|
||||
|
@ -72,7 +72,7 @@
|
|||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>authorization-utils</artifactId>
|
||||
<version>[2.1.0, 3.0.0-SNAPSHOT)</version>
|
||||
<version>[2.1.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
|
@ -337,6 +337,15 @@
|
|||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<attachClasses>true</attachClasses>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -21,16 +21,14 @@ import org.gcube.gcat.api.configuration.CatalogueConfiguration;
|
|||
import org.gcube.gcat.configuration.service.FacetBasedISServiceCatalogueConfiguration;
|
||||
import org.gcube.gcat.configuration.service.ServiceCKANDB;
|
||||
import org.gcube.gcat.configuration.service.ServiceCatalogueConfiguration;
|
||||
import org.gcube.informationsystem.model.impl.properties.HeaderImpl;
|
||||
import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl;
|
||||
import org.gcube.informationsystem.model.impl.relations.ConsistsOfImpl;
|
||||
import org.gcube.informationsystem.model.reference.entities.Entity;
|
||||
import org.gcube.informationsystem.model.reference.properties.Header;
|
||||
import org.gcube.informationsystem.model.reference.properties.Encrypted;
|
||||
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
|
||||
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint;
|
||||
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.DeleteConstraint;
|
||||
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint;
|
||||
import org.gcube.informationsystem.model.reference.properties.Vault;
|
||||
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
|
||||
import org.gcube.informationsystem.queries.templates.reference.entities.QueryTemplate;
|
||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
||||
|
@ -249,7 +247,7 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
propagationConstraint.setRemoveConstraint(RemoveConstraint.keep);
|
||||
propagationConstraint.setDeleteConstraint(DeleteConstraint.keep);
|
||||
EService gcatEService = new EServiceImpl();
|
||||
gcatEService.setHeader(new HeaderImpl(gcatEServiceUUID));
|
||||
gcatEService.setID(gcatEServiceUUID);
|
||||
VirtualService virtualService = queryVirtualService();
|
||||
callsFor = new CallsForImpl<EService, VirtualService>(gcatEService, virtualService, propagationConstraint);
|
||||
callsFor = resourceRegistryPublisher.create(callsFor);
|
||||
|
@ -337,9 +335,8 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
}
|
||||
|
||||
protected ServiceCatalogueConfiguration setConfigurationInfoFromSimpleFacet(SimpleFacet configurationSimpleFacet, ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
|
||||
Header header = configurationSimpleFacet.getHeader();
|
||||
if(header!=null && header.getUUID()!=null) {
|
||||
catalogueConfiguration.setID(header.getUUID().toString());
|
||||
if(configurationSimpleFacet.getID()!=null) {
|
||||
catalogueConfiguration.setID(configurationSimpleFacet.getID().toString());
|
||||
}
|
||||
|
||||
catalogueConfiguration.setModerationEnabled((boolean) configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.MODERATION_ENABLED_KEY));
|
||||
|
@ -386,8 +383,8 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
public ServiceCatalogueConfiguration setCkanServiceInfo(ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
|
||||
AccessPointFacet ckanServiceAccessPointFacet = queryCkanServiceAccessPointFacet();
|
||||
catalogueConfiguration.setCkanURL(ckanServiceAccessPointFacet.getEndpoint().toString());
|
||||
Vault vault = (Vault) ckanServiceAccessPointFacet.getAdditionalProperty(CatalogueConfiguration.SYS_ADMIN_TOKEN_KEY);
|
||||
String encryptedPassword = vault.getValue();
|
||||
Encrypted encrypted = (Encrypted) ckanServiceAccessPointFacet.getAdditionalProperty(CatalogueConfiguration.SYS_ADMIN_TOKEN_KEY);
|
||||
String encryptedPassword = encrypted.getValue();
|
||||
catalogueConfiguration.setSysAdminToken(encryptedPassword);
|
||||
return catalogueConfiguration;
|
||||
}
|
||||
|
@ -397,8 +394,8 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
ServiceCKANDB ckanDB = new ServiceCKANDB();
|
||||
String ckanDbURL = postgresCkanDBAccessPointFacet.getEndpoint().toString();
|
||||
ckanDB.setUrl(ckanDbURL);
|
||||
Vault vault = (Vault) postgresCkanDBAccessPointFacet.getAdditionalProperty(ServiceCKANDB.PASSWORD_KEY);
|
||||
String encryptedPassword = vault.getValue();
|
||||
Encrypted encrypted = (Encrypted) postgresCkanDBAccessPointFacet.getAdditionalProperty(ServiceCKANDB.PASSWORD_KEY);
|
||||
String encryptedPassword = encrypted.getValue();
|
||||
ckanDB.setEncryptedPassword(encryptedPassword);
|
||||
String username = (String) postgresCkanDBAccessPointFacet.getAdditionalProperty(ServiceCKANDB.USERNAME_KEY);
|
||||
ckanDB.setUsername(username);
|
||||
|
@ -419,7 +416,7 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
UUID uuid = null;
|
||||
try {
|
||||
uuid = UUID.fromString(catalogueConfiguration.getID());
|
||||
simpleFacet.getHeader().setUUID(uuid);
|
||||
simpleFacet.setID(uuid);
|
||||
}catch (Exception e) {
|
||||
|
||||
}
|
||||
|
@ -477,14 +474,14 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
try {
|
||||
resourceRegistryPublisher.delete(simpleFacet);
|
||||
} catch (Exception e) {
|
||||
throw new InternalServerErrorException("Unable to delete SimpleFacet with UUID " + simpleFacet.getHeader().getUUID().toString(), e);
|
||||
throw new InternalServerErrorException("Unable to delete SimpleFacet with UUID " + simpleFacet.getID().toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServiceCatalogueConfiguration createOnIS() throws Exception {
|
||||
UUID uuid = configurationSimpleFacet.getHeader().getUUID();
|
||||
UUID uuid = configurationSimpleFacet.getID();
|
||||
if(uuid==null) {
|
||||
Configuration gcatConfiguration = queryGcatConfiguration();
|
||||
ConsistsOf<Configuration, SimpleFacet> co = new ConsistsOfImpl<>(gcatConfiguration, configurationSimpleFacet);
|
||||
|
@ -509,8 +506,7 @@ public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleF
|
|||
|
||||
@Override
|
||||
protected ServiceCatalogueConfiguration updateOnIS() throws Exception {
|
||||
Header header = configurationSimpleFacet.getHeader();
|
||||
if(header!=null && header.getUUID()!=null) {
|
||||
if(configurationSimpleFacet.getID()!=null) {
|
||||
configurationSimpleFacet = getSimpleFacetFromConfiguration(catalogueConfiguration);
|
||||
configurationSimpleFacet = resourceRegistryPublisher.update(configurationSimpleFacet);
|
||||
setConfigurationInfoFromSimpleFacet(configurationSimpleFacet, catalogueConfiguration);
|
||||
|
|
|
@ -95,7 +95,7 @@ public class Item extends REST<CKANPackage> implements org.gcube.gcat.api.interf
|
|||
*
|
||||
* <h4>Filtering options based on Solr query parameters</h4>
|
||||
* <p>
|
||||
* It accepts the following query parameters (a subset of Solr search query parameters, see Solr Query Syntax):
|
||||
* It accepts the following query parameters (a subset of Solr search query parameters, see {@see <a href="https://solrtutorial.com/solr-query-syntax.html">Solr Query Syntax</a>}):
|
||||
* </p>
|
||||
* <dl>
|
||||
* <dt>q (string)</dt>
|
||||
|
|
|
@ -28,5 +28,5 @@
|
|||
"fullname": "Brown Mister",
|
||||
"id": "7445ef41-08d8-4559-8750-3232eb0e1914",
|
||||
"number_created_packages": 0
|
||||
},
|
||||
}
|
||||
]
|
|
@ -1,18 +1,29 @@
|
|||
package org.gcube.gcat.profile;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.File;
|
||||
import java.io.StringReader;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import javax.xml.validation.Validator;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.gcube.gcat.ContextTest;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
public class ProfileTest extends ContextTest {
|
||||
|
||||
|
@ -74,15 +85,41 @@ public class ProfileTest extends ContextTest {
|
|||
profile.delete("TestProfile");
|
||||
}
|
||||
|
||||
public static String PROFILE_EXAMPLE_FILENAME = "EmptyProfileExample.xml";
|
||||
public File getResourcesDirectory() throws Exception {
|
||||
URL logbackFileURL = this.getClass().getClassLoader().getResource("logback-test.xml");
|
||||
File logbackFile = new File(logbackFileURL.toURI());
|
||||
File resourcesDirectory = logbackFile.getParentFile();
|
||||
return resourcesDirectory;
|
||||
}
|
||||
|
||||
public File getProfilesDirectory() throws Exception {
|
||||
File resourcesDirectory = getResourcesDirectory();
|
||||
return new File(resourcesDirectory, "profile_examples");
|
||||
}
|
||||
|
||||
public File getSchemaDirectory() throws Exception {
|
||||
File resourcesDirectory = getResourcesDirectory();
|
||||
return new File(resourcesDirectory, "profile_schemas");
|
||||
}
|
||||
|
||||
public static String PROFILE_NAME_EXAMPLE = "EmptyProfile";
|
||||
public static String PROFILE_EXAMPLE_FILENAME = PROFILE_NAME_EXAMPLE + ".xml";
|
||||
|
||||
public String fileToString(File file) throws Exception {
|
||||
try (Stream<String> lines = Files.lines(file.toPath())) {
|
||||
String content = lines.collect(Collectors.joining(System.lineSeparator()));
|
||||
return content;
|
||||
}catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateUpdateDeleteGenericResource() throws Exception {
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(PROFILE_EXAMPLE_FILENAME);
|
||||
String xml = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
|
||||
logger.debug("Body\n{}", xml);
|
||||
File profilesDirectory = getProfilesDirectory();
|
||||
File profileFile = new File(profilesDirectory, PROFILE_EXAMPLE_FILENAME);
|
||||
String xml = fileToString(profileFile);
|
||||
|
||||
ISProfile profile = new ISProfile();
|
||||
profile.createOrUpdate(PROFILE_NAME_EXAMPLE, xml);
|
||||
/*
|
||||
|
@ -93,4 +130,37 @@ public class ProfileTest extends ContextTest {
|
|||
*/
|
||||
}
|
||||
|
||||
|
||||
protected File getSchemaFile() throws Exception {
|
||||
File schemaDirectory = getSchemaDirectory();
|
||||
return new File(schemaDirectory, "profile5.xsd");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateAgainstXSD() throws Exception {
|
||||
File profilesDirectory = getProfilesDirectory();
|
||||
File schemaFile = getSchemaFile();
|
||||
|
||||
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
Schema schema = factory.newSchema(schemaFile.toURI().toURL());
|
||||
Validator validator = schema.newValidator();
|
||||
|
||||
for(File profileFile : profilesDirectory.listFiles()) {
|
||||
|
||||
String xmlString = fileToString(profileFile);
|
||||
|
||||
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document doc = db.parse( new InputSource(new StringReader(xmlString)));
|
||||
DOMSource xml = new DOMSource(doc);
|
||||
|
||||
try {
|
||||
validator.validate(xml);
|
||||
logger.info("File {} has been successfuly validated against schema.", profileFile.getName());
|
||||
}catch (Exception e) {
|
||||
logger.error("Error while validating file {}", profileFile.getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<metadataformat type="DataMiner Process">
|
||||
<metadatafield categoryref="DataMiner Process">
|
||||
<fieldName>Input Parameter</fieldName>
|
||||
<mandatory>false</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<note>Input parameter expected for the execution of the process</note>
|
||||
</metadatafield>
|
||||
<metadatafield categoryref="DataMiner Process">
|
||||
<fieldName>Output Parameter</fieldName>
|
||||
<mandatory>false</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<note>Output parameter expected from the execution of the process </note>
|
||||
</metadatafield>
|
||||
<metadatafield categoryref="DataMiner Process">
|
||||
<fieldName>Process Author</fieldName>
|
||||
<mandatory>false</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<maxOccurs>*</maxOccurs>
|
||||
<defaultValue/>
|
||||
<note>The name of the author, with email and ORCID. The format should be: family, given[, email][, ORCID]. Example: Smith, John, js@acme.org, orcid.org/0000-0002-1825-0097</note>
|
||||
<validator>
|
||||
<regularExpression>^[a-zA-ZÀ-ÿ .'-]+, [a-zA-ZÀ-ÿ .'-]+[,]*([a-zA-Z0-9_!#$%’*+=?`{|}~^.-]+@[a-zA-Z0-9À-ÿ.-]+)?[,]*(orcid.org\/0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d\d\d-\d\d\d[\dX])?$</regularExpression>
|
||||
</validator>
|
||||
</metadatafield>
|
||||
<metadatafield categoryref="DataMiner Process">
|
||||
<fieldName>Process Maintainer</fieldName>
|
||||
<mandatory>false</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<maxOccurs>*</maxOccurs>
|
||||
<defaultValue/>
|
||||
<note>The name of the author, with email and ORCID. The format should be: family, given[, email][, ORCID]. Example: Smith, John, js@acme.org, orcid.org/0000-0002-1825-0097</note>
|
||||
<validator>
|
||||
<regularExpression>^[a-zA-ZÀ-ÿ .'-]+, [a-zA-ZÀ-ÿ .'-]+[,]*([a-zA-Z0-9_!#$%’*+=?`{|}~^.-]+@[a-zA-Z0-9À-ÿ.-]+)?[,]*(orcid.org\/0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d\d\d-\d\d\d[\dX])?$</regularExpression>
|
||||
</validator>
|
||||
</metadatafield>
|
||||
</metadataformat>
|
|
@ -0,0 +1,10 @@
|
|||
<metadataformat type="F2DSItem">
|
||||
<metadatafield>
|
||||
<fieldName>catalogue_title</fieldName>
|
||||
<mandatory>true</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<defaultValue/>
|
||||
<note>The catalogue_title the item belongs to.</note>
|
||||
<grouping create="true">onValue</grouping>
|
||||
</metadatafield>
|
||||
</metadataformat>
|
|
@ -0,0 +1,36 @@
|
|||
<metadataformat type="SimpleProfile" version="5">
|
||||
<metadatafield>
|
||||
<fieldId>test</fieldId>
|
||||
<fieldName>My Test</fieldName>
|
||||
<mandatory>false</mandatory>
|
||||
<dataType>String</dataType>
|
||||
<maxOccurs>1</maxOccurs>
|
||||
<note>Test Field</note>
|
||||
<tags>
|
||||
<tag create="true">
|
||||
<fixedValue>My Tag</fixedValue>
|
||||
<ifFieldValueMatch>
|
||||
<regex>^(o|O)(k|K)$</regex>
|
||||
</ifFieldValueMatch>
|
||||
</tag>
|
||||
<tag create="true" separator="-">
|
||||
<how>onFieldName_onValue</how>
|
||||
<ifFieldValueMatch>
|
||||
<regex>^(k|K)(o|O)$</regex>
|
||||
</ifFieldValueMatch>
|
||||
</tag>
|
||||
</tags>
|
||||
<groups>
|
||||
<group create="false" propagateUp="true">
|
||||
<fixedValue>My Group</fixedValue>
|
||||
<ifFieldValueMatch>
|
||||
<regex>^true$</regex>
|
||||
</ifFieldValueMatch>
|
||||
</group>
|
||||
</groups>
|
||||
<extra>
|
||||
<srcField>myTest</srcField>
|
||||
<aux>this is just a desc</aux>
|
||||
</extra>
|
||||
</metadatafield>
|
||||
</metadataformat>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
|
||||
vc:minVersion="1.1">
|
||||
|
||||
<xs:redefine schemaLocation="profile5.xsd">
|
||||
<xs:complexType name="ExtraMetadataFieldType">
|
||||
<xs:complexContent>
|
||||
<xs:restriction base="ExtraMetadataFieldType">
|
||||
<xs:sequence>
|
||||
<xs:element type="GRSFType" name="grsf" minOccurs="1" maxOccurs="1" />
|
||||
</xs:sequence>
|
||||
</xs:restriction>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ExtraMetadataFormatType">
|
||||
<xs:complexContent>
|
||||
<xs:restriction base="ExtraMetadataFormatType">
|
||||
<xs:sequence>
|
||||
<xs:element name="grsfFields" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="GRSFType" name="grsfField" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:restriction>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:redefine>
|
||||
|
||||
<xs:complexType name="GRSFType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="srcField" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element type="SrcType" name="srcType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="mandatory" minOccurs="1" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
<xs:enumeration value="aggregated"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:boolean" name="isSensitive" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="dstTypes" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="DestinationType" name="dstType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element type="xs:string" name="topField" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="comments" minOccurs="0" maxOccurs="1" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="BaseDestinationType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Field"/>
|
||||
<xs:enumeration value="Resource"/>
|
||||
<xs:enumeration value="TimeSeries"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="DestinationType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="BaseDestinationType">
|
||||
<xs:attribute type="xs:string" name="maxOccur" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="FieldType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="id" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element type="xs:string" name="type" minOccurs="1" maxOccurs="1" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="SrcType">
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<xs:element name="simpleType" minOccurs="1" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="String"/>
|
||||
<xs:enumeration value="Boolean"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element type="VocabularyType" name="vocabulary" minOccurs="1" maxOccurs="1" />
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="complexType" minOccurs="1" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="JsonArray"/>
|
||||
<xs:enumeration value="JsonObject"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="fields" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="FieldType" name="field" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema attributeFormDefault="unqualified"
|
||||
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="metadataformat">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="metadatafield" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="fieldName" />
|
||||
<xs:element type="xs:boolean" name="mandatory"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="dataType">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="String" />
|
||||
<xs:enumeration value="Time" />
|
||||
<xs:enumeration value="Time_Interval" />
|
||||
<xs:enumeration value="Times_ListOf" />
|
||||
<xs:enumeration value="Text" />
|
||||
<xs:enumeration value="Boolean" />
|
||||
<xs:enumeration value="Number" />
|
||||
<xs:enumeration value="GeoJSON" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="maxOccurs"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element type="xs:string" name="defaultValue"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element type="xs:string" name="note" minOccurs="0"
|
||||
maxOccurs="1" />
|
||||
<xs:element name="vocabulary" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="vocabularyField"
|
||||
minOccurs="1" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:boolean" name="isMultiSelection" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="validator" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="regularExpression" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="tagging" type="TaggingType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
</xs:element>
|
||||
<xs:element name="grouping" type="GroupingType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="categoryref" use="optional" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="NotEmpty" use="required" name="type" />
|
||||
<xs:attribute name="version" type="xs:integer" use="optional" fixed="3"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:simpleType name="TaggingGroupingValue">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="onFieldName" />
|
||||
<xs:enumeration value="onValue" />
|
||||
<xs:enumeration value="onFieldName_onValue" />
|
||||
<xs:enumeration value="onValue_onFieldName" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="TaggingType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="NotEmpty" name="separator" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="GroupingType">
|
||||
<xs:simpleContent id="TaggingGroupingValue">
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="xs:boolean" name="propagateUp" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="NotEmpty">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema attributeFormDefault="unqualified"
|
||||
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="metadataformat">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="metadatafield" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="fieldId" minOccurs="0"/>
|
||||
<xs:element type="xs:string" name="fieldName" />
|
||||
<xs:element type="xs:boolean" name="mandatory"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="dataType">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="String" />
|
||||
<xs:enumeration value="Time" />
|
||||
<xs:enumeration value="Time_Interval" />
|
||||
<xs:enumeration value="Times_ListOf" />
|
||||
<xs:enumeration value="Text" />
|
||||
<xs:enumeration value="Boolean" />
|
||||
<xs:enumeration value="Number" />
|
||||
<xs:enumeration value="GeoJSON" />
|
||||
<xs:enumeration value="File" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="maxOccurs"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element type="xs:string" name="defaultValue"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<xs:element type="xs:string" name="note" minOccurs="0"
|
||||
maxOccurs="1" />
|
||||
<xs:element name="vocabulary" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="vocabularyField"
|
||||
minOccurs="1" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:boolean" name="isMultiSelection" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="validator" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="regularExpression" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="tagging" type="TaggingType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
</xs:element>
|
||||
<xs:element name="grouping" type="GroupingType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="categoryref" use="optional" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="NotEmpty" use="required" name="type" />
|
||||
<xs:attribute name="version" type="xs:integer" use="optional" fixed="4"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:simpleType name="TaggingGroupingValue">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="onFieldName" />
|
||||
<xs:enumeration value="onValue" />
|
||||
<xs:enumeration value="onFieldName_onValue" />
|
||||
<xs:enumeration value="onValue_onFieldName" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="TaggingType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="NotEmpty" name="separator" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="GroupingType">
|
||||
<xs:simpleContent id="TaggingGroupingValue">
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="xs:boolean" name="propagateUp" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="NotEmpty">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,250 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
|
||||
vc:minVersion="1.1">
|
||||
<xs:element name="metadataformat">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="ExtendedMetadataFieldType" name="metadatafield" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element type="ExtraMetadataFormatType" name="extra" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Any additional tag in this 'extra' tag.
|
||||
This tag and its content are ignored by the validators.
|
||||
They are used by any external tools producing/consuming the profile definition and instances.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="NotEmpty" use="required" name="type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The type (i.e the name) of the profile.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="version" type="xs:integer" use="optional" fixed="5">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This XSD is valid for gCube Metadata Profile version 5. Any XML conform to this schema must declare such a version as attibute in the root tag.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:complexType name="TagGroupType">
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:element name="how" minOccurs="1" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="onFieldName"/>
|
||||
<xs:enumeration value="onValue"/>
|
||||
<xs:enumeration value="onFieldName_onValue"/>
|
||||
<xs:enumeration value="onValue_onFieldName"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:sequence>
|
||||
<xs:element type="NotEmpty" name="fixedValue" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:choice>
|
||||
<xs:element name="ifFieldValueMatch" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="NotEmpty" name="regex" minOccurs="1" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:boolean" name="create"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="TagType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="TagGroupType">
|
||||
<xs:attribute type="NotEmpty" name="separator" default="_"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="GroupType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="TagGroupType">
|
||||
<xs:attribute type="xs:boolean" name="propagateUp" default="false"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="NotEmpty">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="MetadataFieldType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="fieldId" minOccurs="0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
It declares (if present in the profile) the value that will be used to specify the field name in the Document (e.g. JSON Document) passed to Service that will store the resulting Document. If the 'fieldId' is absent in the profile, the value of the 'fieldName' (which is mandatory) will be used as field name in the Document.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="fieldName">
|
||||
<xs:annotation>
|
||||
<xs:documentation>It contains the name of the metadata field.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element type="xs:boolean" name="mandatory" minOccurs="0"
|
||||
maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
It declares if the 'metadatafield' is a field mandatory (by using 'true') or not (by using 'false').
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="dataType">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="String"/>
|
||||
<xs:enumeration value="Time"/>
|
||||
<xs:enumeration value="Time_Interval"/>
|
||||
<xs:enumeration value="Times_ListOf"/>
|
||||
<xs:enumeration value="Text"/>
|
||||
<xs:enumeration value="Boolean"/>
|
||||
<xs:enumeration value="Number"/>
|
||||
<xs:enumeration value="GeoJSON"/>
|
||||
<xs:enumeration value="File"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="maxOccurs" minOccurs="0"
|
||||
maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
It specifies the maximum number of times that the'metadatafield' can occur: N (as number): if the field must appear N times; * (as char asterisk): if the field can appear an unlimited number of times.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="defaultValue" minOccurs="0"
|
||||
maxOccurs="1"/>
|
||||
<xs:element type="xs:string" name="note" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element type="VocabularyType" name="vocabulary" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="validator" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="regularExpression"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:choice>
|
||||
<xs:element name="tags" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="TagType" name="tag" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="tagging" type="TaggingType" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
This tagging method is deprecated. Please use the tag 'tags' instead.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
<xs:choice>
|
||||
<xs:element name="groups" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element type="GroupType" name="group" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="grouping" type="GroupingType" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
This grouping method is deprecated. Please use the tag 'groups' instead.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
<xs:element type="xs:boolean" name="remove" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
When this field is true the field is removed from metadata.
|
||||
This allows to use a field to add tag and groups depending on
|
||||
any logic of this field.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="categoryref" use="optional" type="xs:string" />
|
||||
</xs:complexType>
|
||||
<xs:complexType name="VocabularyType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="vocabularyField"
|
||||
minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:boolean" name="isMultiSelection"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ExtraMetadataFieldType">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Any tags are allowed</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:any>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ExtraMetadataFormatType">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Any tags are allowed</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:any>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ExtendedMetadataFieldType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="MetadataFieldType">
|
||||
<xs:sequence>
|
||||
<xs:element type="ExtraMetadataFieldType" name="extra" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Any additional tag in this 'extra' tag.
|
||||
This tag and its content are ignored by the validators.
|
||||
They are used by any external tools producing/consuming the profile definition and instances.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<!-- Maintain backward compatibility -->
|
||||
<xs:simpleType name="TaggingGroupingValue">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="onFieldName" />
|
||||
<xs:enumeration value="onValue" />
|
||||
<xs:enumeration value="onFieldName_onValue" />
|
||||
<xs:enumeration value="onValue_onFieldName" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="TaggingType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="NotEmpty" name="separator" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="GroupingType">
|
||||
<xs:simpleContent id="TaggingGroupingValue">
|
||||
<xs:extension base="TaggingGroupingValue">
|
||||
<xs:attribute type="xs:boolean" name="create" />
|
||||
<xs:attribute type="xs:boolean" name="propagateUp" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
Loading…
Reference in New Issue