import Schema from './schema' ; import ASTParser from '../parser/ast-parser' ; import DataParser from '../data/index' ; import ErrorCodes from '../errors/io-error-codes' ; import { SCHEMA } from '../parser/constants' ; import { ASTParserTree } from '../parser' ; import { InternetObjectError } from '../errors/io-error' ; import { isKeyVal , isParserTree , isString , isToken } from '../utils/is' ; export default class KeyValueCollection { private _keys : any = [ ] ; private _map : any = { } ; public length ( ) { return this . _keys . length ; } public get keys ( ) : string [ ] { return [ ... this . _keys ] ; } param key { any } returns public getV ( key ) { if ( isString ( key ) && key . startsWith ( '$' ) && key . length > 1 ) { return this . get ( key . substr ( 1 ) ) ; } } param key { string } returns public get ( key ) { return this . _map [ key ] ; } param key { string } param val { any } public set ( key , val ) { if ( key in this . _map === false ) { this . _keys . push ( key ) ; } this . _map [ key ] = val ; return this ; } param key { string } public remove ( key ) { if ( key in this . _map === false ) return this ; const index = this . _keys . indexOf ( key ) ; this . _keys . splice ( index ) ; delete this . _map [ key ] ; return this ; } /**
     * Gets schema
     */ public get schema ( ) : Schema { return this . _map [ SCHEMA ] || null ; } /**
     * Sets schema
     */ public set schema ( schema ) { if ( ! this . schema ) { this . _keys . push ( SCHEMA ) ; } this . _map [ SCHEMA ] = schema ; } param collection param schema public static compile ( collection , schema ? ) { let tree ; const newCollection = new KeyValueCollection ( ) ; if ( isString ( collection ) ) { const parser = new ASTParser ( collection , true ) ; parser . parse ( ) ; tree = parser . header ; } else if ( isParserTree ( collection ) ) { tree = collection ; } else { throw new Error ( 'invlid-collection' ) ; } if ( tree . type === 'object' ) { const compiledSchema = Schema . compile ( tree ) ; newCollection . set ( SCHEMA , compiledSchema ) ; } else if ( tree . type === 'collection' ) { _parseCollection ( tree , newCollection , ( key , val ) => { newCollection . _keys . push ( key ) ; newCollection . _map [ key ] = val ; } ) ; } else { throw new InternetObjectError ( ErrorCodes . invlidHeader , 'Invalid value found in header' ) ; } if ( schema ) { let compiledSchema = schema ; if ( isString ( schema ) ) { compiledSchema = Schema . compile ( tree ) ; } newCollection . set ( SCHEMA , compiledSchema ) ; } return newCollection ; } } function _parseCollection ( tree , collection , callback ) { const map = { } ; const keys = [ ] ; for ( let index = 0 ; index < tree . values . length ; index += 1 ) { const item = tree . values [ index ] ; if ( ! isParserTree ( item ) ) { console . warn ( '>>' , tree ) ; throw new InternetObjectError ( ErrorCodes . invalidHeaderItem ) ; } if ( item . type !== 'object' ) { throw new InternetObjectError ( ErrorCodes . invalidHeaderItem ) ; } if ( item . values . length !== 1 ) { console . log ( '***' , item , item . values ) ; throw new InternetObjectError ( ErrorCodes . invalidHeaderItem ) ; } const keyVal = item . values [ 0 ] ; if ( ! isKeyVal ( keyVal ) ) { throw new InternetObjectError ( ErrorCodes . invalidHeaderItem ) ; } const key = keyVal . key ; let value = keyVal . value ; if ( key . startsWith ( '$' ) ) { const val = Schema . compile ( value , collection ) ; callback ( key , val ) ; } else if ( isParserTree ( value ) ) { const val = DataParser . parse ( value , collection ) ; callback ( key , val ) ; } else if ( isToken ( value ) ) { let val = value . value ; if ( value . type === 'string' && val . length > 2 && val [ 0 ] === '$' ) { const varVal = collection . get ( value . value . substr ( 1 ) ) ; if ( varVal !== undefined ) { val = varVal ; } } callback ( key , val ) ; } else { throw new InternetObjectError ( ErrorCodes . invalidHeaderItem ) ; } } }