From 86c0dcbfe1027b8d9f739b9039c4077b90fb2e43 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Wed, 28 Dec 2016 14:04:57 +0200 Subject: [PATCH] Support inherited discriminator (only one at the moment) --- lib/components/JsonSchema/json-schema.ts | 17 +++++---- lib/components/SchemaSample/schema-sample.ts | 4 +-- lib/utils/spec-manager.ts | 38 ++++++++++++++++++-- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/lib/components/JsonSchema/json-schema.ts b/lib/components/JsonSchema/json-schema.ts index 19ec9449..323cf8af 100644 --- a/lib/components/JsonSchema/json-schema.ts +++ b/lib/components/JsonSchema/json-schema.ts @@ -45,8 +45,8 @@ export class JsonSchema extends BaseComponent implements OnInit { }); activeDescendant.active = true; - this.pointer = activeDescendant.$ref; - this.schema = this.specMgr.byPointer(this.pointer); + this.schema = this.specMgr.getDescendant(activeDescendant, this.componentSchema); + this.pointer = this.schema._pointer || activeDescendant.$ref; this.normalizer.reset(); this.schema = this.normalizer.normalize(this.schema, this.normPointer, {resolved: true}); @@ -54,19 +54,22 @@ export class JsonSchema extends BaseComponent implements OnInit { } initDescendants() { - this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer); + this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer, this.schema); if (!this.descendants.length) return; this.hasDescendants = true; let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator']; - let discrProperty = this.schema._properties && - this.schema._properties.filter((prop) => prop.name === discriminator)[0]; + let discrProperty = this.schema.properties && + this.schema.properties[discriminator]; if (discrProperty && discrProperty.enum) { let enumOrder = {}; discrProperty.enum.forEach((enumItem, idx) => { - enumOrder[enumItem.val] = idx; + enumOrder[enumItem] = idx; }); - this.schema._descendants.sort((a, b) => { + this.descendants = this.descendants + .filter(a => { + return enumOrder[a.name] != undefined; + }).sort((a, b) => { return enumOrder[a.name] > enumOrder[b.name] ? 1 : -1; }); } diff --git a/lib/components/SchemaSample/schema-sample.ts b/lib/components/SchemaSample/schema-sample.ts index 40cedfff..79a533d2 100644 --- a/lib/components/SchemaSample/schema-sample.ts +++ b/lib/components/SchemaSample/schema-sample.ts @@ -51,11 +51,11 @@ export class SchemaSample extends BaseComponent implements OnInit { let discriminator = this.componentSchema.discriminator || this.componentSchema['x-discriminatorBasePointer']; if (discriminator) { - let descendants = this.specMgr.findDerivedDefinitions(this.componentSchema._pointer || this.pointer); + let descendants = this.specMgr.findDerivedDefinitions(this.componentSchema._pointer || this.pointer, this.componentSchema); if (descendants.length) { // TODO: sync up with dropdown selectedDescendant = descendants[0]; - let descSchema = this.specMgr.byPointer(selectedDescendant.$ref); + let descSchema = this.specMgr.getDescendant(selectedDescendant, this.componentSchema); this.componentSchema = this._normalizer.normalize(Object.assign({}, descSchema), selectedDescendant.$ref, {omitParent: false}); } diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index 7a9e3c94..e9356895 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -7,6 +7,10 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { MdRenderer } from './md-renderer'; +function getDiscriminator(obj) { + return obj.discriminator || obj['x-extendedDiscriminator']; +} + export class SpecManager { public _schema: any = {}; public apiUrl: string; @@ -158,8 +162,8 @@ export class SpecManager { return tagsMap; } - findDerivedDefinitions(defPointer) { - let definition = this.byPointer(defPointer); + findDerivedDefinitions(defPointer, schema) { + let definition = schema || this.byPointer(defPointer); if (!definition) throw new Error(`Can't load schema at ${defPointer}`); if (!definition.discriminator && !definition['x-extendedDiscriminator']) return []; @@ -172,7 +176,20 @@ export class SpecManager { !def['x-derived-from']) continue; let subTypes = def['x-derived-from'] || def.allOf.map(subType => subType._pointer || subType.$ref); - let idx = subTypes.findIndex(ref => ref === defPointer); + + let pointers; + if (definition['x-derived-from']) { + pointers = [defPointer, ...definition['x-derived-from']]; + } else { + pointers = [defPointer]; + } + let idx = -1; + + for (let ptr of pointers) { + idx = subTypes.findIndex(ref => ptr && ref === ptr); + if (idx >= 0) break; + } + if (idx < 0) continue; let derivedName = defName; @@ -188,4 +205,19 @@ export class SpecManager { return res; } + getDescendant(descendant, componentSchema) { + let res; + if (!getDiscriminator(componentSchema) && componentSchema.allOf) { + // discriminator inherited from parents + // only one discriminator and only one level of inheritence is supported at the moment + res = Object.assign({}, componentSchema); + let idx = res.allOf.findIndex(subSpec => !!getDiscriminator(subSpec)); + res.allOf[idx] = this.byPointer(descendant.$ref); + } else { + // this.pointer = activeDescendant.$ref; + res = this.byPointer(descendant.$ref); + } + return res; + } + }