import { InternalMapping } from "./internalMapping" ; import { MappingBase } from "./mappingBase" ; import { MappingModel } from "./mappingModel" ; import { Reference } from "../reference" ; import { InternalSession } from "../session" ; import { ResultCallback } from "../core/callback" ; import { ResolveContext } from "./resolveContext" ; import { ReadContext } from "./readContext" ; import { Observer } from "../observer" ; import { WriteContext } from "./writeContext" ; import { PersistenceError } from "../persistenceError" ; hidden export class TupleMapping extends MappingBase { constructor ( public elementMappings ) { super ( MappingModel . MappingFlags . Tuple ) ; } read ( context , value ) { if ( value == null ) return null ; if ( ! Array . isArray ( value ) ) { context . addError ( "Expected tuple." ) ; return ; } var mappings = this . elementMappings ; if ( value . length != mappings . length ) { context . addError ( "Expected " + mappings . length + " elements in tuple but source had " + value . length + "." ) ; return ; } var result = new Array ( value . length ) ; for ( var i = 0 , l = mappings . length ; i < l ; i ++ ) { var savedPath = context . path ; context . path += "." + i ; result [ i ] = mappings [ i ] . read ( context , value [ i ] ) ; context . path = savedPath ; } if ( context . observer ) { context . observer . watch ( result ) ; } return result ; } write ( context , value ) { if ( value == null ) return null ; if ( ! Array . isArray ( value ) ) { context . addError ( "Expected tuple." ) ; return ; } var mappings = this . elementMappings ; if ( value . length != mappings . length ) { context . addError ( `Expected ${ mappings . length } elements in tuple but source had ${ value . length }.` ) ; return ; } var result = new Array ( value . length ) ; for ( var i = 0 , l = mappings . length ; i < l ; i ++ ) { var savedPath = context . path ; context . path += "." + i ; result [ i ] = mappings [ i ] . write ( context , value [ i ] ) ; context . path = savedPath ; } return result ; } watch ( value , observer , visited ) { if ( ! value || ! Array . isArray ( value ) ) return ; observer . watch ( value ) ; for ( var i = 0 , l = Math . min ( value . length , this . elementMappings . length ) ; i < l ; i ++ ) { this . elementMappings [ i ] . watch ( value [ i ] , observer , visited ) ; } } areEqual ( documentValue1 , documentValue2 ) { if ( documentValue1 === documentValue2 ) return true ; if ( documentValue1 == null || documentValue2 == null ) return false ; if ( ! Array . isArray ( documentValue1 ) || ! Array . isArray ( documentValue2 ) || documentValue1 . length != documentValue2 . length ) { return false ; } var mappings = this . elementMappings ; if ( documentValue1 . length != mappings . length ) { return false ; } for ( var i = 0 , l = mappings . length ; i < l ; i ++ ) { var fieldValue1 = documentValue1 [ i ] ; var fieldValue2 = documentValue2 [ i ] ; if ( fieldValue1 !== fieldValue2 && ! mappings [ i ] . areEqual ( fieldValue1 , fieldValue2 ) ) { return false ; } } return true ; } walk ( session , value , flags , entities , embedded , references ) { if ( ! Array . isArray ( value ) ) { return ; } var mappings = this . elementMappings ; for ( var i = 0 , l = Math . min ( value . length , mappings . length ) ; i < l ; i ++ ) { mappings [ i ] . walk ( session , value [ i ] , flags , entities , embedded , references ) ; } } fetch ( session , parentEntity , value , path , depth , callback ) { if ( ! Array . isArray ( value ) || depth == path . length ) { process . nextTick ( ( ) => callback ( null , value ) ) ; return ; } var index = parseInt ( path [ depth ] ) ; if ( index !== index || index < 0 || index >= this . elementMappings . length ) { return callback ( new PersistenceError ( "Undefined tuple index '" + path [ depth ] + "' in path '" + path . join ( "." ) + "'." ) ) ; } var item = value [ index ] ; this . elementMappings [ index ] . fetch ( session , parentEntity , item , path , depth + 1 , ( err , result ) => { if ( err ) return callback ( err ) ; if ( item !== result ) { value [ index ] = item ; } callback ( null , value ) ; } ) ; } protected resolveCore ( context ) { var property = context . currentProperty ; if ( property == "$" ) { context . setError ( "Cannot resolve positional operator for Tuple." ) ; return ; } var index ; if ( ( index = parseInt ( property ) ) === index ) { if ( index < 0 || index >= this . elementMappings . length ) { context . setError ( "Index out of range for Tuple." ) ; return ; } var elementMapping = this . elementMappings [ index ] ; if ( context . resolveProperty ( elementMapping , property ) ) { return ; } elementMapping . resolve ( context ) ; } else { context . setError ( "Expected index for Tuple." ) ; } } }