import { WidgetModel , PropertyModel , ExtraDataModel , VariableModel } from "../models/models" ; import * as parseXml from '../parser/types' ; import { PipeValueResolver } from "./pipe-value-resolver" ; import { PropertyHandlerProvider } from "../providers/property-handler-provider" ; import { ValueTransformersProvider , ValueTransformResult } from "../providers/value-transformers-provider" ; import { Config } from "../models/config" ; export class PropertyResolver { constructor ( private readonly config , private readonly propertyHandlerProvider , public readonly pipeValueResolver ) { } resolveProperties ( element , widget ) { if ( ! element . attributes ) { return null ; } let wrapperWidget = null ; let propertiesNames = Object . keys ( element . attributes ) ; const propertiesToIgnore = this . getRelatedProperties ( element , propertiesNames , widget ) ; propertiesNames = propertiesNames . filter ( a => propertiesToIgnore . indexOf ( a ) === - 1 ) ; const priorities = this . getPropertiesPriorities ( element , propertiesNames , widget ) ; propertiesNames = propertiesNames . sort ( ( a , b ) => typeof element . attributes [ a ] === 'object' ? - 1 : ( typeof element . attributes [ b ] === 'object' ? 1 : ( priorities [ a ] > priorities [ b ] ? 1 : - 1 ) ) ) . filter ( a => a !== ':use' ) ; const usePropertyValue = element . attributes [ ':use' ] ; if ( usePropertyValue ) { widget . type += '.' + usePropertyValue ; } for ( const propertyName of propertiesNames ) { const propertyValue = element . attributes [ propertyName ] as any ; const propertyResult = this . resolveProperty ( element , propertyName , propertyValue , wrapperWidget || widget , widget ) ; if ( propertyResult . wrapperWidget ) { wrapperWidget = propertyResult . wrapperWidget ; } if ( ! propertyResult . handled ) { widget . properties . push ( propertyResult . property ) ; } } return wrapperWidget ; } private getRelatedProperties ( element , propertiesNames , widget ) { const propertiesToIgnore = [ ] ; for ( const propertyName of propertiesNames ) { if ( propertiesToIgnore . indexOf ( propertyName ) > - 1 ) { continue ; } const propertyHandler = this . propertyHandlerProvider . get ( propertyName ) ; if ( propertyHandler && propertyHandler . canResolve ( element , propertyName , widget ) ) { const related = propertyHandler . getRelatedProperties ( element , propertyName , widget ) . filter ( a => a !== propertyName ) ; propertiesToIgnore . push ( ... related ) ; } } return propertiesToIgnore ; } private getPropertiesPriorities ( element , propertiesNames , widget ) { const priorities = { } ; for ( const propertyName of propertiesNames ) { let priority = 100 ; const propertyHandler = this . propertyHandlerProvider . get ( propertyName ) ; if ( propertyHandler && propertyHandler . canResolve ( element , propertyName , widget ) ) { priority = propertyHandler . priority ; } priorities [ propertyName ] = priority ; } return priorities ; } resolveProperty ( element , propertyName , propertyValue , widget , ownerWidget ) { let wrapperWidget = null ; let extraData = null ; let value = propertyValue ; let dataType = typeof value === 'object' ? ( 'propertyElement' ) : 'object' ; let handled = false ; const propertyHandler = this . propertyHandlerProvider . get ( propertyName ) ; if ( propertyHandler && propertyHandler . canResolve ( element , propertyName , widget ) ) { const attr = { name : propertyName , value } ; const customPropertyResolveResult = propertyHandler . resolve ( element , attr , widget ) ; extraData = customPropertyResolveResult . extraData ; wrapperWidget = customPropertyResolveResult . wrapperWidget ; value = customPropertyResolveResult . value ; handled = customPropertyResolveResult . handled ; } if ( ! widget . isPropertyElement && ! propertyHandler && typeof value === 'string' ) { const boundResult = this . pipeValueResolver . resolve ( element , propertyName , value , widget ) ; extraData = boundResult . extraData ; wrapperWidget = boundResult . wrapperWidget ; value = boundResult . value ; } if ( dataType !== 'propertyElement' ) { value = ValueTransformersProvider . transform ( value , propertyName , widget . type ) ; } if ( this . isUnNamedParameter ( propertyName , ownerWidget . type ) ) { propertyName = '' ; } const property = { dataType , extraData , name : propertyName , value } ; if ( propertyName === 'controller' ) { property . controller = this . createController ( propertyValue ) ; property . value = ( property . controller . name . indexOf ( '.' ) > - 1 ? '' : 'ctrl.' ) + property . controller . name ; } return { property , wrapperWidget , handled } ; } private createController ( propertyValue ) { let skipGenerate = false ; const eqSegments = propertyValue . split ( '=' ) ; let name = eqSegments [ 0 ] . split ( ' ' ) [ 1 ] ; let type = eqSegments [ 0 ] . split ( ' ' ) [ 0 ] ; let value ; if ( ! name ) { name = type ; type = '' ; if ( name . indexOf ( '.' ) > - 1 ) { skipGenerate = true ; } } if ( eqSegments . length === 2 ) { value = eqSegments [ 1 ] ; if ( ! type ) { type = value . substring ( 0 , value . indexOf ( '(' ) ) ; } } if ( type ) { type = type . trim ( ) ; } if ( name ) { name = name . trim ( ) ; } if ( value ) { value = value . trim ( ) ; } return { type , name , value , skipGenerate : ! type && ! value || skipGenerate } ; } isUnNamedParameter ( name , widgetType ) { let result = this . getUnNamedParameter ( widgetType ) === name ; return result ; } getUnNamedParameter ( widgetType ) { widgetType = widgetType . split ( '.' ) [ 0 ] ; let unnamed = { Text : 'text' , Icon : 'icon' , Image : 'source' } ; if ( this . config . unnamedProperties ) { unnamed = Object . assign ( unnamed , this . config . unnamedProperties ) ; } return unnamed [ widgetType ] ; } getConfig ( ) { return this . config ; } }