1 | import { COVERAGECOLLECTION } from '../constants.js'
|
2 | import { asTime, isISODateAxis, isLongitudeAxis, getLongitudeWrapper } from '../domain/referencing.js'
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | export function addCollectionQueryFunction (collection) {
|
9 | if (collection.paging) {
|
10 | throw new Error('Paged collections not supported')
|
11 | }
|
12 | collection.query = () => new CollectionQuery(collection)
|
13 | }
|
14 |
|
15 | export class CollectionQuery {
|
16 | |
17 |
|
18 |
|
19 | constructor (collection) {
|
20 | this._collection = collection
|
21 | this._filter = {}
|
22 | this._subset = {}
|
23 | }
|
24 |
|
25 | |
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | filter (spec) {
|
41 | mergeInto(spec, this._filter)
|
42 | return this
|
43 | }
|
44 |
|
45 | |
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | subset (spec) {
|
55 | mergeInto(spec, this._subset)
|
56 | return this
|
57 | }
|
58 |
|
59 | |
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | execute () {
|
66 | let coll = this._collection
|
67 | let newcoll = {
|
68 | type: COVERAGECOLLECTION,
|
69 | coverages: [],
|
70 | parameters: coll.parameters,
|
71 | domainType: coll.domainType
|
72 | }
|
73 |
|
74 | let promises = []
|
75 | for (let cov of coll.coverages) {
|
76 | promises.push(cov.loadDomain().then(domain => {
|
77 | if (!matchesFilter(domain, this._filter)) {
|
78 | return
|
79 | }
|
80 |
|
81 | if (Object.keys(this._subset).length === 0) {
|
82 | newcoll.coverages.push(cov)
|
83 | } else {
|
84 | return cov.subsetByValue(this._subset).then(subsetted => {
|
85 | newcoll.coverages.push(subsetted)
|
86 | })
|
87 | }
|
88 | }))
|
89 | }
|
90 | return Promise.all(promises).then(() => {
|
91 | newcoll.query = () => new CollectionQuery(newcoll)
|
92 | return newcoll
|
93 | })
|
94 | }
|
95 | }
|
96 |
|
97 | function matchesFilter (domain, filter) {
|
98 | for (let axisName of Object.keys(filter)) {
|
99 | let condition = filter[axisName]
|
100 | if (!domain.axes.has(axisName)) {
|
101 | throw new Error('Axis "' + axisName + '" does not exist')
|
102 | }
|
103 | let axis = domain.axes.get(axisName)
|
104 | let vals = axis.values
|
105 |
|
106 | let [min, max] = [vals[0], vals[vals.length - 1]]
|
107 | if (typeof min !== 'number' && typeof min !== 'string') {
|
108 | throw new Error('Can only filter primitive axis values')
|
109 | }
|
110 | let {start, stop} = condition
|
111 |
|
112 |
|
113 | if (isISODateAxis(domain, axisName)) {
|
114 | [min, max] = [asTime(min), asTime(max)]
|
115 | ;[start, stop] = [asTime(start), asTime(stop)]
|
116 | } else if (isLongitudeAxis(domain, axisName)) {
|
117 | let lonWrapper = getLongitudeWrapper(domain, axisName)
|
118 | ;[start, stop] = [lonWrapper(start), lonWrapper(stop)]
|
119 | }
|
120 |
|
121 | if (min > max) {
|
122 | [min, max] = [max, min]
|
123 | }
|
124 | if (max < start || stop < min) {
|
125 | return false
|
126 | }
|
127 | }
|
128 |
|
129 | return true
|
130 | }
|
131 |
|
132 | function mergeInto (inputObj, targetObj) {
|
133 | for (let k of Object.keys(inputObj)) {
|
134 | targetObj[k] = inputObj[k]
|
135 | }
|
136 | }
|