Support inherited discriminator (only one at the moment)

This commit is contained in:
Roman Hotsiy 2016-12-28 14:04:57 +02:00
parent d3af2e6867
commit 86c0dcbfe1
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
3 changed files with 47 additions and 12 deletions

View File

@ -45,8 +45,8 @@ export class JsonSchema extends BaseComponent implements OnInit {
}); });
activeDescendant.active = true; activeDescendant.active = true;
this.pointer = activeDescendant.$ref; this.schema = this.specMgr.getDescendant(activeDescendant, this.componentSchema);
this.schema = this.specMgr.byPointer(this.pointer); this.pointer = this.schema._pointer || activeDescendant.$ref;
this.normalizer.reset(); this.normalizer.reset();
this.schema = this.normalizer.normalize(this.schema, this.normPointer, this.schema = this.normalizer.normalize(this.schema, this.normPointer,
{resolved: true}); {resolved: true});
@ -54,19 +54,22 @@ export class JsonSchema extends BaseComponent implements OnInit {
} }
initDescendants() { initDescendants() {
this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer); this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer, this.schema);
if (!this.descendants.length) return; if (!this.descendants.length) return;
this.hasDescendants = true; this.hasDescendants = true;
let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator']; let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator'];
let discrProperty = this.schema._properties && let discrProperty = this.schema.properties &&
this.schema._properties.filter((prop) => prop.name === discriminator)[0]; this.schema.properties[discriminator];
if (discrProperty && discrProperty.enum) { if (discrProperty && discrProperty.enum) {
let enumOrder = {}; let enumOrder = {};
discrProperty.enum.forEach((enumItem, idx) => { 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; return enumOrder[a.name] > enumOrder[b.name] ? 1 : -1;
}); });
} }

View File

@ -51,11 +51,11 @@ export class SchemaSample extends BaseComponent implements OnInit {
let discriminator = this.componentSchema.discriminator || this.componentSchema['x-discriminatorBasePointer']; let discriminator = this.componentSchema.discriminator || this.componentSchema['x-discriminatorBasePointer'];
if (discriminator) { 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) { if (descendants.length) {
// TODO: sync up with dropdown // TODO: sync up with dropdown
selectedDescendant = descendants[0]; 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, this.componentSchema = this._normalizer.normalize(Object.assign({}, descSchema), selectedDescendant.$ref,
{omitParent: false}); {omitParent: false});
} }

View File

@ -7,6 +7,10 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { MdRenderer } from './md-renderer'; import { MdRenderer } from './md-renderer';
function getDiscriminator(obj) {
return obj.discriminator || obj['x-extendedDiscriminator'];
}
export class SpecManager { export class SpecManager {
public _schema: any = {}; public _schema: any = {};
public apiUrl: string; public apiUrl: string;
@ -158,8 +162,8 @@ export class SpecManager {
return tagsMap; return tagsMap;
} }
findDerivedDefinitions(defPointer) { findDerivedDefinitions(defPointer, schema) {
let definition = this.byPointer(defPointer); let definition = schema || this.byPointer(defPointer);
if (!definition) throw new Error(`Can't load schema at ${defPointer}`); if (!definition) throw new Error(`Can't load schema at ${defPointer}`);
if (!definition.discriminator && !definition['x-extendedDiscriminator']) return []; if (!definition.discriminator && !definition['x-extendedDiscriminator']) return [];
@ -172,7 +176,20 @@ export class SpecManager {
!def['x-derived-from']) continue; !def['x-derived-from']) continue;
let subTypes = def['x-derived-from'] || let subTypes = def['x-derived-from'] ||
def.allOf.map(subType => subType._pointer || subType.$ref); 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; if (idx < 0) continue;
let derivedName = defName; let derivedName = defName;
@ -188,4 +205,19 @@ export class SpecManager {
return res; 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;
}
} }