1
+ const zip = require ( 'lodash/zip' )
2
+
1
3
const semver = require ( 'semver' )
2
4
3
5
const loadSchema = require ( '../../common/schema/loader' )
@@ -9,6 +11,19 @@ const { setParent } = require('../../utils/xml2js')
9
11
const { Hed2SchemaParser } = require ( './hed2' )
10
12
const { HedV8SchemaParser } = require ( './hed3' )
11
13
14
+ /**
15
+ * Determine whether a HED schema is based on the HED 3 spec.
16
+ *
17
+ * @param {object } xmlData HED XML data.
18
+ * @returns {boolean } Whether the schema is a HED 3 schema.
19
+ */
20
+ const isHed3Schema = function ( xmlData ) {
21
+ return (
22
+ xmlData . HED . $ . library !== undefined ||
23
+ semver . gte ( xmlData . HED . $ . version , '8.0.0-alpha.3' )
24
+ )
25
+ }
26
+
12
27
/**
13
28
* Build a schema attributes object from schema XML data.
14
29
*
@@ -18,32 +33,56 @@ const { HedV8SchemaParser } = require('./hed3')
18
33
const buildSchemaAttributesObject = function ( xmlData ) {
19
34
const rootElement = xmlData . HED
20
35
setParent ( rootElement , null )
21
- if ( semver . gte ( rootElement . $ . version , '8.0.0-alpha.3' ) ) {
36
+ if ( isHed3Schema ( xmlData ) ) {
22
37
return new HedV8SchemaParser ( rootElement ) . parse ( )
23
38
} else {
24
39
return new Hed2SchemaParser ( rootElement ) . parse ( )
25
40
}
26
41
}
27
42
28
43
/**
29
- * Build a schema container object from a base schema version or path description.
44
+ * Build a single schema container object from a base schema version or path description.
45
+ *
46
+ * @param {object } xmlData The schema's XML data
47
+ * @returns {Schema } The HED schema object.
48
+ */
49
+ const buildSchemaObject = function ( xmlData ) {
50
+ const schemaAttributes = buildSchemaAttributesObject ( xmlData )
51
+ const mapping = buildMappingObject ( xmlData )
52
+ let schema
53
+ if ( isHed3Schema ( xmlData ) ) {
54
+ schema = new Hed3Schema ( xmlData , schemaAttributes , mapping )
55
+ } else {
56
+ schema = new Hed2Schema ( xmlData , schemaAttributes , mapping )
57
+ }
58
+ return schema
59
+ }
60
+
61
+ /**
62
+ * Build a schema collection object from a schema specification.
30
63
*
31
- * @param {{path: string?, version: string?} } schemaDef The description of which base schema to use.
64
+ * @param {{path: string?, version: string?, libraries: object } } schemaDef The description of which base schema to use.
32
65
* @param {boolean } useFallback Whether to use a bundled fallback schema if the requested schema cannot be loaded.
33
66
* @return {Promise<never>|Promise<Schemas> } The schema container object or an error.
34
67
*/
35
68
const buildSchema = function ( schemaDef = { } , useFallback = true ) {
36
69
return loadSchema ( schemaDef , useFallback ) . then ( ( xmlData ) => {
37
- const schemaAttributes = buildSchemaAttributesObject ( xmlData )
38
- const mapping = buildMappingObject ( xmlData )
39
- const rootElement = xmlData . HED
40
- let baseSchema
41
- if ( semver . gte ( rootElement . $ . version , '8.0.0-alpha.3' ) ) {
42
- baseSchema = new Hed3Schema ( xmlData , schemaAttributes , mapping )
43
- } else {
44
- baseSchema = new Hed2Schema ( xmlData , schemaAttributes , mapping )
70
+ const baseSchema = buildSchemaObject ( xmlData )
71
+ if ( schemaDef . libraries === undefined ) {
72
+ return new Schemas ( baseSchema )
45
73
}
46
- return new Schemas ( baseSchema )
74
+ const [ libraryKeys , libraryDefs ] = zip (
75
+ ...Object . entries ( schemaDef . libraries ) ,
76
+ )
77
+ return Promise . all (
78
+ libraryDefs . map ( ( libraryDef ) => {
79
+ return loadSchema ( libraryDef , false )
80
+ } ) ,
81
+ ) . then ( ( libraryXmlData ) => {
82
+ const librarySchemaObjects = libraryXmlData . map ( buildSchemaObject )
83
+ const librarySchemas = new Map ( zip ( libraryKeys , librarySchemaObjects ) )
84
+ return new Schemas ( baseSchema , librarySchemas )
85
+ } )
47
86
} )
48
87
}
49
88
0 commit comments