import * as path from 'path' ; import * as utils from './utils' ; import { ObjectContext } from './object-context' ; export interface ObjectWithType { _type : string ; } ; export interface TypeDef { typeName : string ; description ? : string ; moduleName : string ; functionName : string ; override ? : boolean ; exampleObjects ? : any [ ] ; } export interface FactoryMethod { ( input , context ? ) : any ; } export interface ObjectFactory { create ( input , context ? ) : any ; supports ( typeName ) : boolean ; } export class TypeRegistry implements ObjectFactory { private _typeToFactoryMethod : Map < string , FactoryMethod > = new Map < string , FactoryMethod > ( ) ; public create ( input , context ? ) { if ( input == null ) { return null ; } let typeName ; if ( Array . isArray ( input ) ) { if ( ( < ObjectWithType [ ] > input ) . length == 0 ) { return [ ] ; } typeName = ( < ObjectWithType [ ] > input ) [ 0 ] . _type ; for ( let elem of input ) { if ( elem . _type !== typeName ) { throw new Error ( "Property '_type' must be the same for all elements in input array when calling ObjectFactory.create." ) ; } } } else { typeName = ( < ObjectWithType > input ) . _type ; } if ( this . supports ( typeName ) ) { return this . _typeToFactoryMethod . get ( typeName ) ( input , context ) ; } throw new Error ( "Not supported type: '" + typeName + "'." ) ; } public register ( type , creator ) { this . _typeToFactoryMethod . set ( type , creator ) ; } public supports ( typeName ) { return this . _typeToFactoryMethod . has ( typeName ) ; } public static fromDefinition ( typeDefCollection , baseDir ) { let registry = new TypeRegistry ( ) ; if ( typeDefCollection != null ) { typeDefCollection . forEach ( def => { let moduleName = def . moduleName ; if ( def . moduleName . startsWith ( "." ) ) { moduleName = path . resolve ( baseDir , moduleName ) ; } let creator = utils . loadFunction ( moduleName , def . functionName ) ; registry . register ( def . typeName , creator ) ; } ) ; } return registry ; } } const SCHEMA_DIR = path . resolve ( __dirname , '../schema' ) ; export class TypeConfig { private static readonly OBJECT_TYPE_CONFIG_SCHEMA : utils . JsonSchema = new utils . JsonSchema ( path . resolve ( SCHEMA_DIR , "object-type-config.schema.json" ) ) ; private static _transform : utils . Transform = new utils . SetDefaultValue ( { 'override' : false } ) ; public static fromConfigObject ( jsValue , validateSchema = true ) { if ( validateSchema ) { utils . ensureSchema ( jsValue , this . OBJECT_TYPE_CONFIG_SCHEMA ) ; } jsValue . forEach ( obj => { this . _transform . apply ( obj ) ; } ) ; return jsValue ; } public static fromConfig ( objectTypeConfig ) { return utils . appendMessageOnException ( "Error found in object type definition file '" + objectTypeConfig + "'." , ( ) => { return this . fromConfigObject ( utils . readConfig ( objectTypeConfig ) ) ; } ) ; } }