Skip to content

Commit 497c182

Browse files
authored
feat: Create asset summaries (#157)
* feat: Require 'linz:asset_summaries' root property * feat: Require asset summary 'created' propert * feat: require asset summary created 'minimum' property * feat: require asset summary created minimum property be a string * feat: require asset summary created minimum property be a datetime * feat: require asset summary created minimum property be a UTC datetime * refactor: Pull out UTC datetime definition * docs: Set asset/metadata summary created/updated titles * feat: require asset summary created 'maximum' property * feat: require asset summary created maximum property be a UTC datetime * feat: require asset summary 'updated' property * feat: require asset summary updated 'minimum' property * feat: require asset summary updated minimum property be a UTC datetime * feat: require asset summary updated 'maximum' property * feat: require asset summary updated maximum property be a UTC datetime * docs: Move asset summary documentation to right property
1 parent 56e130e commit 497c182

File tree

4 files changed

+164
-36
lines changed

4 files changed

+164
-36
lines changed

extensions/linz/README.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,34 @@ See [ISO/IEC 13249-3:2016(en)](https://www.iso.org/obp/ui/#!iso:std:60343:en) fo
6363

6464
## Collection Fields
6565

66-
| Field Name | Type | Description |
67-
| ---------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
68-
| title | string | **REQUIRED**. Collection title. |
69-
| linz:geospatial_type | string | **REQUIRED**. A general description of the type of content that can be found in the dataset. See the [list of accepted geospatial types](#geospatial-types). |
70-
| linz:history | string | **REQUIRED**. A descriptive statement about the lineage/history of a dataset |
71-
| linz:lifecycle | string | **REQUIRED**. Lifecycle Status of Collection. Must be one of `under development`, `preview`, `ongoing`, `completed`, `deprecated`. |
72-
| linz:providers | LINZ Provider Object | **REQUIRED**. The object provides information about a provider with additional roles defined by Toitū Te Whenua LINZ. A provider is any of the organizations that captures or processes the content of the assets and therefore influences the data offered by the STAC implementation. See [LINZ Provider Object](#linz-provider-object). |
73-
| providers | Provider Object | **REQUIRED**. The object provides information about a provider. A provider is any of the organizations that captures or processes the content of the assets and therefore influences the data offered by the STAC implementation. See [Provider Object](#provider-object). |
74-
| linz:security_classification | string | **REQUIRED**. New Zealand Government [Security Classification](https://www.digital.govt.nz/standards-and-guidance/governance/managing-online-channels/security-and-privacy-for-websites/foundations/classify-information/). Must be one of `unclassified`, `in-confidence`, `sensitive`, `restricted`, `confidential`, `secret` or `top-secret`. |
75-
| linz:update_frequency | string | Recommended. Indicates how frequently an updated dataset may be distributed to the publication platform. Must follow the format for durations as defined in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#appendix-A). For example, `P3D` expresses a duration of 3 days. |
76-
| processing:software | Map<string, string> | Recommended. The software and versions which were used to generate the dataset. See [reference](https://github.com/stac-extensions/processing). |
77-
78-
### Collection Summaries Object Fields
66+
| Field Name | Type | Description |
67+
| ---------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
68+
| title | string | **REQUIRED**. Collection title. |
69+
| linz:asset_summaries | Map<string, Map<string, string>> | **REQUIRED**. See [Custom Collection Summaries Object Fields](#custom-collection-summaries-object-fields). |
70+
| linz:geospatial_type | string | **REQUIRED**. A general description of the type of content that can be found in the dataset. See the [list of accepted geospatial types](#geospatial-types). |
71+
| linz:history | string | **REQUIRED**. A descriptive statement about the lineage/history of a dataset |
72+
| linz:lifecycle | string | **REQUIRED**. Lifecycle Status of Collection. Must be one of `under development`, `preview`, `ongoing`, `completed`, `deprecated`. |
73+
| linz:providers | LINZ Provider Object | **REQUIRED**. The object provides information about a provider with additional roles defined by Toitū Te Whenua LINZ. A provider is any of the organizations that captures or processes the content of the assets and therefore influences the data offered by the STAC implementation. See [LINZ Provider Object](#linz-provider-object). |
74+
| providers | Provider Object | **REQUIRED**. The object provides information about a provider. A provider is any of the organizations that captures or processes the content of the assets and therefore influences the data offered by the STAC implementation. See [Provider Object](#provider-object). |
75+
| linz:security_classification | string | **REQUIRED**. New Zealand Government [Security Classification](https://www.digital.govt.nz/standards-and-guidance/governance/managing-online-channels/security-and-privacy-for-websites/foundations/classify-information/). Must be one of `unclassified`, `in-confidence`, `sensitive`, `restricted`, `confidential`, `secret` or `top-secret`. |
76+
| linz:update_frequency | string | Recommended. Indicates how frequently an updated dataset may be distributed to the publication platform. Must follow the format for durations as defined in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#appendix-A). For example, `P3D` expresses a duration of 3 days. |
77+
| processing:software | Map<string, string> | Recommended. The software and versions which were used to generate the dataset. See [reference](https://github.com/stac-extensions/processing). |
78+
79+
### Custom Collection Summaries Object Fields
7980

8081
| Field Name | Type | Description |
8182
| --------------- | --------- | -------------------------------------------------------------------- |
82-
| title | string | **REQUIRED**. Collection title. |
8383
| created/minimum | date-time | **REQUIRED**. Earliest [asset created value](#asset-fields), in UTC. |
8484
| created/maximum | date-time | **REQUIRED**. Latest [asset created value](#asset-fields), in UTC. |
8585
| updated/minimum | date-time | **REQUIRED**. Earliest [asset updated value](#asset-fields), in UTC. |
8686
| updated/maximum | date-time | **REQUIRED**. Latest [asset updated value](#asset-fields), in UTC. |
8787

88+
### Collection Summaries Object Fields
89+
90+
| Field Name | Type | Description |
91+
| ---------- | ------ | ------------------------------- |
92+
| title | string | **REQUIRED**. Collection title. |
93+
8894
### LINZ Provider Object Fields
8995

9096
This expands on the [provider object in the STAC spec](https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md#provider-object). Only differences from that definition are mentioned here.

extensions/linz/examples/collection.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
"title": "A title",
1313
"description": "A description",
1414
"license": "Apache-2.0",
15+
"linz:asset_summaries": {
16+
"created": {
17+
"minimum": "1999-01-01T00:00:00Z",
18+
"maximum": "2010-01-01T00:00:00Z"
19+
},
20+
"updated": {
21+
"minimum": "1999-01-01T00:00:00Z",
22+
"maximum": "2010-01-01T00:00:00Z"
23+
}
24+
},
1525
"linz:lifecycle": "under development",
1626
"linz:providers": [
1727
{

extensions/linz/schema.json

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
{
3535
"type": "object",
3636
"required": [
37+
"linz:asset_summaries",
3738
"linz:geospatial_type",
3839
"linz:history",
3940
"linz:lifecycle",
@@ -131,15 +132,11 @@
131132
"properties": {
132133
"created": {
133134
"title": "Creation time",
134-
"type": "string",
135-
"format": "date-time",
136-
"pattern": "(\\+00:00|Z)$"
135+
"$ref": "#/definitions/utc_datetime"
137136
},
138137
"updated": {
139138
"title": "Last update time",
140-
"type": "string",
141-
"format": "date-time",
142-
"pattern": "(\\+00:00|Z)$"
139+
"$ref": "#/definitions/utc_datetime"
143140
},
144141
"linz:language": {
145142
"title": "IETF RFC 5646 language tag",
@@ -940,6 +937,37 @@
940937
}
941938
}
942939
},
940+
"linz:asset_summaries": {
941+
"required": ["created", "updated"],
942+
"properties": {
943+
"created": {
944+
"required": ["minimum", "maximum"],
945+
"properties": {
946+
"minimum": {
947+
"title": "Earliest asset creation time",
948+
"$ref": "#/definitions/utc_datetime"
949+
},
950+
"maximum": {
951+
"title": "Latest asset creation time",
952+
"$ref": "#/definitions/utc_datetime"
953+
}
954+
}
955+
},
956+
"updated": {
957+
"required": ["minimum", "maximum"],
958+
"properties": {
959+
"minimum": {
960+
"title": "Earliest asset updated time",
961+
"$ref": "#/definitions/utc_datetime"
962+
},
963+
"maximum": {
964+
"title": "Latest asset updated time",
965+
"$ref": "#/definitions/utc_datetime"
966+
}
967+
}
968+
}
969+
}
970+
},
943971
"linz:geospatial_type": {},
944972
"linz:history": {
945973
"title": "History",
@@ -1047,16 +1075,12 @@
10471075
"required": ["minimum", "maximum"],
10481076
"properties": {
10491077
"minimum": {
1050-
"title": "Earliest asset creation time",
1051-
"type": "string",
1052-
"format": "date-time",
1053-
"pattern": "(\\+00:00|Z)$"
1078+
"title": "Earliest metadata creation time",
1079+
"$ref": "#/definitions/utc_datetime"
10541080
},
10551081
"maximum": {
1056-
"title": "Latest asset creation time",
1057-
"type": "string",
1058-
"format": "date-time",
1059-
"pattern": "(\\+00:00|Z)$"
1082+
"title": "Latest metadata creation time",
1083+
"$ref": "#/definitions/utc_datetime"
10601084
}
10611085
}
10621086
},
@@ -1065,16 +1089,12 @@
10651089
"required": ["minimum", "maximum"],
10661090
"properties": {
10671091
"minimum": {
1068-
"title": "Earliest asset updated time",
1069-
"type": "string",
1070-
"format": "date-time",
1071-
"pattern": "(\\+00:00|Z)$"
1092+
"title": "Earliest metadata updated time",
1093+
"$ref": "#/definitions/utc_datetime"
10721094
},
10731095
"maximum": {
1074-
"title": "Latest asset updated time",
1075-
"type": "string",
1076-
"format": "date-time",
1077-
"pattern": "(\\+00:00|Z)$"
1096+
"title": "Latest metadata updated time",
1097+
"$ref": "#/definitions/utc_datetime"
10781098
}
10791099
}
10801100
}
@@ -1089,6 +1109,11 @@
10891109
"^(?!linz:)": {}
10901110
},
10911111
"additionalProperties": false
1112+
},
1113+
"utc_datetime": {
1114+
"type": "string",
1115+
"format": "date-time",
1116+
"pattern": "(\\+00:00|Z)$"
10921117
}
10931118
}
10941119
}

extensions/linz/tests/linz_collection.test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,93 @@ o.spec('LINZ collection', () => {
205205
).equals(true)(JSON.stringify(validate.errors));
206206
});
207207

208+
o("Example without the mandatory 'linz:asset_summaries' property should fail validation", async () => {
209+
// given
210+
const example = JSON.parse(await fs.readFile(examplePath));
211+
delete example['linz:asset_summaries'];
212+
213+
// when
214+
let valid = validate(example);
215+
216+
// then
217+
o(valid).equals(false);
218+
o(
219+
validate.errors.some(
220+
(error) => error.instancePath === '' && error.message === "must have required property 'linz:asset_summaries'",
221+
),
222+
).equals(true)(JSON.stringify(validate.errors));
223+
});
224+
225+
o("Asset summary without the mandatory 'created'/'updated' properties should fail validation", async () => {
226+
for (const property of ['created', 'updated']) {
227+
// given
228+
const example = JSON.parse(await fs.readFile(examplePath));
229+
delete example['linz:asset_summaries'][property];
230+
231+
// when
232+
let valid = validate(example);
233+
234+
// then
235+
o(valid).equals(false);
236+
o(
237+
validate.errors.some(
238+
(error) =>
239+
error.instancePath === '/linz:asset_summaries' &&
240+
error.message === `must have required property '${property}'`,
241+
),
242+
).equals(true)(JSON.stringify(validate.errors));
243+
}
244+
});
245+
246+
o(
247+
"Asset summary created/updated without the mandatory 'minimum'/'maximum' properties should fail validation",
248+
async () => {
249+
for (const outerProperty of ['created', 'updated']) {
250+
for (const innerProperty of ['minimum', 'maximum']) {
251+
// given
252+
const example = JSON.parse(await fs.readFile(examplePath));
253+
delete example['linz:asset_summaries'][outerProperty][innerProperty];
254+
255+
// when
256+
let valid = validate(example);
257+
258+
// then
259+
o(valid).equals(false);
260+
o(
261+
validate.errors.some(
262+
(error) =>
263+
error.instancePath === `/linz:asset_summaries/${outerProperty}` &&
264+
error.message === `must have required property '${innerProperty}'`,
265+
),
266+
).equals(true)(JSON.stringify(validate.errors));
267+
}
268+
}
269+
},
270+
);
271+
272+
o("Asset summary created/updated with invalid 'minimum'/'maximum' value should fail validation", async () => {
273+
for (const outerProperty of ['created', 'updated']) {
274+
for (const innerProperty of ['minimum', 'maximum']) {
275+
// given
276+
const example = JSON.parse(await fs.readFile(examplePath));
277+
example['linz:asset_summaries'][outerProperty][innerProperty] = '1999-01-01T00:00:00';
278+
279+
// when
280+
let valid = validate(example);
281+
282+
// then
283+
o(valid).equals(false);
284+
o(
285+
validate.errors.some(
286+
(error) =>
287+
error.instancePath === `/linz:asset_summaries/${outerProperty}/${innerProperty}` &&
288+
error.message === 'must match pattern "(\\+00:00|Z)$"',
289+
),
290+
).equals(true)(JSON.stringify(validate.errors));
291+
}
292+
}
293+
});
294+
208295
o("Example without the mandatory 'linz:history' field should fail validation", async () => {
209296
// given
210297
const example = JSON.parse(await fs.readFile(examplePath));

0 commit comments

Comments
 (0)