import TypeDef from './typedef' ; import MemberDef from './memberdef' ; import ErrorCodes from '../errors/io-error-codes' ; import KeyValueCollection from '../header' ; import { TypedefRegistry } from './typedef-registry' ; import { doCommonTypeCheck } from './utils' ; import { ParserTreeValue , Node } from '../parser/index' ; import { isParserTree , isKeyVal , isUndefined } from '../utils/is' ; import { InternetObjectError , InternetObjectSyntaxError } from '../errors/io-error' ; /**
 * Represents the ObjectTypeDef which is reponsible for parsing,
 * validating, loading and serializing Objects.
 */ class ObjectDef implements TypeDef { private _keys : any = null ; /**
     * Returns the type this instance is going to handle.
     * Always returns object
     */ getType ( ) { return 'object' ; } /**
     * Parses the object in IO format into JavaScript object.
     */ parse = ( data , memberDef , vars ? ) : any => { const value = isParserTree ( data ) ? data . values : undefined ; return this . _process ( memberDef , value , data , vars ) ; } ; /**
     * Loads the JavaScript object.
     */ load = ( data , memberDef ) : any => { return this . _process ( memberDef , data ) ; } ; /**
     * Serializes the object into IO format.
     */ public serialize = ( data , memberDef , isRoot = false ) : string => { if ( memberDef . type !== 'object' ) { throw new InternetObjectError ( ErrorCodes . invalidObject ) ; } const validatedData = doCommonTypeCheck ( memberDef , data ) ; const serialized = [ ] ; const schema = memberDef . schema ; schema . keys . forEach ( ( key , index ) => { const memberDef = schema . defs [ key ] ; const typeDef = TypedefRegistry . get ( memberDef . type ) ; const value = validatedData [ key ] ; const serializedValue = typeDef . serialize ( value , memberDef ) ; serialized . push ( serializedValue ) ; } ) ; if ( isRoot ) { return serialized . join ( ',' ) . replace ( /,+$/g , '' ) ; } return `{${ serialized . join ( ',' ) . replace ( /,+$/g , '' ) }}` ; } ; private _process = ( memberDef , value , node ? , vars ? ) => { const validatedData = doCommonTypeCheck ( memberDef , value , node ) ; if ( validatedData !== value || validatedData === null || validatedData === undefined ) { return validatedData ; } const schema = memberDef . schema ; const object = { } ; const fn = isParserTree ( node ) ? 'parse' : 'load' ; let indexMode = true ; if ( isParserTree ( node ) ) { node . values . forEach ( ( dataItem , index ) => { let key ; let memberDef ; let dataValue ; if ( isKeyVal ( dataItem ) ) { indexMode = false ; key = dataItem . key ; memberDef = schema . defs [ key ] ; dataValue = dataItem . value ; } else if ( indexMode || dataItem === undefined ) { key = schema . keys [ index ] ; memberDef = schema . defs [ key ] ; dataValue = dataItem ; } else { throw new InternetObjectSyntaxError ( ErrorCodes . positionalMemberAfterKeywordMember ) ; } if ( isUndefined ( memberDef ) ) return ; const typeDef = TypedefRegistry . get ( memberDef . type ) ; object [ key ] = typeDef . parse ( dataValue , memberDef , vars ) ; } ) ; schema . keys . forEach ( ( key ) => { if ( key in object ) return ; const memberDef = schema . defs [ key ] ; const typeDef = TypedefRegistry . get ( memberDef . type ) ; object [ key ] = typeDef . parse ( undefined , memberDef , vars ) ; } ) ; } else { const keys = schema . keys ; keys . forEach ( ( key ) => { const memberDef = schema . defs [ key ] ; if ( isUndefined ( memberDef ) ) return ; const typeDef = TypedefRegistry . get ( memberDef . type ) ; const dataItem = value [ key ] ; object [ key ] = typeDef . load ( dataItem , memberDef ) ; } ) ; } return object ; } ; } export default ObjectDef ;