| 'use strict'; |
| |
| /*eslint-disable max-len*/ |
| |
| var YAMLException = require('./exception'); |
| var Type = require('./type'); |
| |
| |
| function compileList(schema, name) { |
| var result = []; |
| |
| schema[name].forEach(function (currentType) { |
| var newIndex = result.length; |
| |
| result.forEach(function (previousType, previousIndex) { |
| if (previousType.tag === currentType.tag && |
| previousType.kind === currentType.kind && |
| previousType.multi === currentType.multi) { |
| |
| newIndex = previousIndex; |
| } |
| }); |
| |
| result[newIndex] = currentType; |
| }); |
| |
| return result; |
| } |
| |
| |
| function compileMap(/* lists... */) { |
| var result = { |
| scalar: {}, |
| sequence: {}, |
| mapping: {}, |
| fallback: {}, |
| multi: { |
| scalar: [], |
| sequence: [], |
| mapping: [], |
| fallback: [] |
| } |
| }, index, length; |
| |
| function collectType(type) { |
| if (type.multi) { |
| result.multi[type.kind].push(type); |
| result.multi['fallback'].push(type); |
| } else { |
| result[type.kind][type.tag] = result['fallback'][type.tag] = type; |
| } |
| } |
| |
| for (index = 0, length = arguments.length; index < length; index += 1) { |
| arguments[index].forEach(collectType); |
| } |
| return result; |
| } |
| |
| |
| function Schema(definition) { |
| return this.extend(definition); |
| } |
| |
| |
| Schema.prototype.extend = function extend(definition) { |
| var implicit = []; |
| var explicit = []; |
| |
| if (definition instanceof Type) { |
| // Schema.extend(type) |
| explicit.push(definition); |
| |
| } else if (Array.isArray(definition)) { |
| // Schema.extend([ type1, type2, ... ]) |
| explicit = explicit.concat(definition); |
| |
| } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { |
| // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] }) |
| if (definition.implicit) implicit = implicit.concat(definition.implicit); |
| if (definition.explicit) explicit = explicit.concat(definition.explicit); |
| |
| } else { |
| throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' + |
| 'or a schema definition ({ implicit: [...], explicit: [...] })'); |
| } |
| |
| implicit.forEach(function (type) { |
| if (!(type instanceof Type)) { |
| throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); |
| } |
| |
| if (type.loadKind && type.loadKind !== 'scalar') { |
| throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); |
| } |
| |
| if (type.multi) { |
| throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.'); |
| } |
| }); |
| |
| explicit.forEach(function (type) { |
| if (!(type instanceof Type)) { |
| throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); |
| } |
| }); |
| |
| var result = Object.create(Schema.prototype); |
| |
| result.implicit = (this.implicit || []).concat(implicit); |
| result.explicit = (this.explicit || []).concat(explicit); |
| |
| result.compiledImplicit = compileList(result, 'implicit'); |
| result.compiledExplicit = compileList(result, 'explicit'); |
| result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); |
| |
| return result; |
| }; |
| |
| |
| module.exports = Schema; |