#include "hbclass.ch" CREATE CLASS TConectorDatosReg FROM TConectorDatos DATA hDatos INIT { => } DATA cGrupoVarDefecto INIT "DATOS" DATA cGrupoLineDefecto INIT "LINEAS" DATA cGrupoLineActual INIT "LINEAS" DATA nIndiceLineActual INIT 0 DATA hVariablesCache INIT NIL DATA aRegistrosDetalleCache INIT NIL METHOD New( cRuta ) CONSTRUCTOR METHOD Init( cRuta ) METHOD Create() METHOD End() METHOD SendDataVar( aStruct, aReg ) METHOD SendDataLine( aStruct, aReg ) METHOD GetVariables() METHOD GetData() INLINE ::hDatos METHOD GetRegistrosDetalle() METHOD ResetLine() METHOD NextLine() METHOD EofLine() METHOD GetTotalLine() METHOD GetCurrentLine() METHOD GetLineValue( cCampo, uDefault ) METHOD GetVarValue( cCampo, uDefault ) HIDDEN: METHOD EmptyData() METHOD NormalizarStruct( aStruct, cGrupoDefecto ) METHOD DefinicionCampo( hCampo, cGrupoDefecto ) METHOD NormalizarTipo( uTipo ) METHOD VariablesDataVar() METHOD PrimerRegistroDetalleVar() METHOD ValorDefinicion( uDefinicion ) METHOD RegistroDesdeArray( aCampos, aRegistro ) METHOD SplitCampo( cCampo, cGrupoDefecto ) METHOD HashKeys( hHash ) INLINE iif( HB_ISHASH( hHash ), hb_HKeys( hHash ), {} ) METHOD HGet( hHash, cKey, uDefault ) METHOD ValueString( uValue ) METHOD NormalizeHashKeyName( uKey ) ENDCLASS METHOD New( cRuta ) CLASS TConectorDatosReg ::Init( cRuta ) RETURN Self METHOD Init( cRuta ) CLASS TConectorDatosReg HB_SYMBOL_UNUSED( cRuta ) ::hDatos := ::EmptyData() ::cGrupoVarDefecto := "DATOS" ::cGrupoLineDefecto := "LINEAS" ::cGrupoLineActual := ::cGrupoLineDefecto ::nIndiceLineActual := 0 ::hVariablesCache := NIL ::aRegistrosDetalleCache := NIL RETURN Self METHOD Create() CLASS TConectorDatosReg RETURN Self METHOD End() CLASS TConectorDatosReg ::hDatos := ::EmptyData() ::cGrupoLineActual := ::cGrupoLineDefecto ::nIndiceLineActual := 0 ::hVariablesCache := NIL ::aRegistrosDetalleCache := NIL RETURN NIL METHOD SendDataVar( aStruct, aReg ) CLASS TConectorDatosReg LOCAL aCampos := ::NormalizarStruct( aStruct, ::cGrupoVarDefecto ) LOCAL aRegistro := iif( HB_ISARRAY( aReg ) .AND. Len( aReg ) > 0 .AND. HB_ISARRAY( aReg[ 1 ] ), aReg[ 1 ], {} ) LOCAL hDataVar := { => } LOCAL hGrupo LOCAL hCampo LOCAL nIndex LOCAL cGrupo LOCAL cNombre LOCAL uValor LOCAL nCamposLen hb_HAutoAdd( hDataVar, .T. ) nCamposLen := Len( aCampos ) FOR nIndex := 1 TO nCamposLen hCampo := aCampos[ nIndex ] cGrupo := hCampo[ "grupo" ] cNombre := hCampo[ "nombre" ] uValor := iif( nIndex <= Len( aRegistro ), aRegistro[ nIndex ], NIL ) IF Len( cGrupo ) == 0 .OR. Len( cNombre ) == 0 LOOP ENDIF IF ! hb_HHasKey( hDataVar, cGrupo ) hDataVar[ cGrupo ] := { => } hb_HAutoAdd( hDataVar[ cGrupo ], .T. ) ENDIF hGrupo := hDataVar[ cGrupo ] hGrupo[ cNombre ] := { "tipo" => hCampo[ "tipo" ], "valor" => uValor } NEXT ::hDatos[ "DataVar" ] := hDataVar ::hDatos := ::NormalizarDatosRuntime( ::hDatos ) ::hDatos[ "_StructVar" ] := aCampos ::hDatos[ "_RegVar" ] := iif( HB_ISARRAY( aReg ), aReg, {} ) ::hVariablesCache := NIL RETURN Self METHOD SendDataLine( aStruct, aReg ) CLASS TConectorDatosReg LOCAL aCampos := ::NormalizarStruct( aStruct, ::cGrupoLineDefecto ) LOCAL hDetalleVar := { => } LOCAL hRegistro LOCAL hCampo LOCAL aGrupoRegistros LOCAL nReg LOCAL nCampo LOCAL cGrupo LOCAL cNombre LOCAL uValor LOCAL nRegLen LOCAL nCamposLen hb_HAutoAdd( hDetalleVar, .T. ) ::cGrupoLineActual := iif( Len( aCampos ) > 0 .AND. Len( aCampos[ 1 ][ "grupo" ] ) > 0, aCampos[ 1 ][ "grupo" ], ::cGrupoLineDefecto ) IF HB_ISARRAY( aReg ) nRegLen := Len( aReg ) nCamposLen := Len( aCampos ) FOR nReg := 1 TO nRegLen IF ! HB_ISARRAY( aReg[ nReg ] ) LOOP ENDIF FOR nCampo := 1 TO nCamposLen hCampo := aCampos[ nCampo ] cGrupo := hCampo[ "grupo" ] cNombre := hCampo[ "nombre" ] uValor := iif( nCampo <= Len( aReg[ nReg ] ), aReg[ nReg ][ nCampo ], NIL ) IF Len( cGrupo ) == 0 .OR. Len( cNombre ) == 0 LOOP ENDIF IF ! hb_HHasKey( hDetalleVar, cGrupo ) hDetalleVar[ cGrupo ] := {} ENDIF aGrupoRegistros := hDetalleVar[ cGrupo ] DO WHILE Len( aGrupoRegistros ) < nReg AAdd( aGrupoRegistros, { => } ) hb_HAutoAdd( aGrupoRegistros[ Len( aGrupoRegistros ) ], .T. ) ENDDO hRegistro := aGrupoRegistros[ nReg ] hRegistro[ cNombre ] := { "tipo" => hCampo[ "tipo" ], "valor" => uValor } hDetalleVar[ cGrupo ] := aGrupoRegistros NEXT NEXT ENDIF ::hDatos[ "DetalleVar" ] := hDetalleVar ::hDatos[ "_StructLine" ] := aCampos ::hDatos[ "_RegLine" ] := iif( HB_ISARRAY( aReg ), aReg, {} ) ::hVariablesCache := NIL ::aRegistrosDetalleCache := NIL ::ResetLine() RETURN Self METHOD GetVariables() CLASS TConectorDatosReg LOCAL hVariables LOCAL hDetalle LOCAL aKeys LOCAL nIndex LOCAL cKey LOCAL nKeysLen IF HB_ISHASH( ::hVariablesCache ) RETURN ::hVariablesCache ENDIF hVariables := ::VariablesDataVar() hDetalle := ::PrimerRegistroDetalleVar() aKeys := ::HashKeys( hDetalle ) hb_HAutoAdd( hVariables, .T. ) nKeysLen := Len( aKeys ) FOR nIndex := 1 TO nKeysLen cKey := aKeys[ nIndex ] hVariables[ cKey ] := hDetalle[ cKey ] NEXT ::hVariablesCache := hVariables RETURN ::hVariablesCache METHOD GetRegistrosDetalle() CLASS TConectorDatosReg LOCAL hDetalleVar := ::HGet( ::hDatos, "DetalleVar", { => } ) LOCAL aRegistros := {} LOCAL aGrupos := ::HashKeys( hDetalleVar ) LOCAL aGrupoRegistros LOCAL hRegistro LOCAL aCampos LOCAL nGrupo LOCAL nReg LOCAL nCampo LOCAL cGrupo LOCAL cCampo LOCAL nGruposLen LOCAL nGrupoRegistrosLen LOCAL nCamposLen IF HB_ISARRAY( ::aRegistrosDetalleCache ) RETURN ::aRegistrosDetalleCache ENDIF nGruposLen := Len( aGrupos ) FOR nGrupo := 1 TO nGruposLen cGrupo := aGrupos[ nGrupo ] aGrupoRegistros := ::HGet( hDetalleVar, cGrupo, {} ) IF ! HB_ISARRAY( aGrupoRegistros ) LOOP ENDIF nGrupoRegistrosLen := Len( aGrupoRegistros ) FOR nReg := 1 TO nGrupoRegistrosLen IF ! HB_ISHASH( aGrupoRegistros[ nReg ] ) LOOP ENDIF hRegistro := { => } hb_HAutoAdd( hRegistro, .T. ) aCampos := ::HashKeys( aGrupoRegistros[ nReg ] ) nCamposLen := Len( aCampos ) FOR nCampo := 1 TO nCamposLen cCampo := aCampos[ nCampo ] hRegistro[ cGrupo + "." + cCampo ] := ::ValorDefinicion( aGrupoRegistros[ nReg ][ cCampo ] ) NEXT AAdd( aRegistros, hRegistro ) NEXT NEXT ::aRegistrosDetalleCache := aRegistros RETURN ::aRegistrosDetalleCache METHOD ResetLine() CLASS TConectorDatosReg ::nIndiceLineActual := 0 RETURN Self METHOD NextLine() CLASS TConectorDatosReg ::nIndiceLineActual++ RETURN Self METHOD EofLine() CLASS TConectorDatosReg RETURN ::nIndiceLineActual >= ::GetTotalLine() METHOD GetTotalLine() CLASS TConectorDatosReg LOCAL aRegLine := ::HGet( ::hDatos, "_RegLine", {} ) RETURN iif( HB_ISARRAY( aRegLine ), Len( aRegLine ), 0 ) METHOD GetCurrentLine() CLASS TConectorDatosReg LOCAL aRegistros := ::GetRegistrosDetalle() IF ::nIndiceLineActual < 0 .OR. ::nIndiceLineActual >= Len( aRegistros ) RETURN { => } ENDIF RETURN aRegistros[ ::nIndiceLineActual + 1 ] METHOD GetLineValue( cCampo, uDefault ) CLASS TConectorDatosReg LOCAL hRegistro := ::GetCurrentLine() LOCAL cClave := ::ValueString( cCampo ) IF At( ".", cClave ) == 0 cClave := ::cGrupoLineActual + "." + cClave ENDIF IF HB_ISHASH( hRegistro ) .AND. hb_HHasKey( hRegistro, cClave ) RETURN hRegistro[ cClave ] ENDIF RETURN uDefault METHOD GetVarValue( cCampo, uDefault ) CLASS TConectorDatosReg LOCAL hVariables := ::VariablesDataVar() LOCAL cClave := ::ValueString( cCampo ) IF HB_ISHASH( hVariables ) .AND. hb_HHasKey( hVariables, cClave ) RETURN hVariables[ cClave ] ENDIF IF At( ".", cClave ) == 0 cClave := ::cGrupoVarDefecto + "." + cClave IF hb_HHasKey( hVariables, cClave ) RETURN hVariables[ cClave ] ENDIF ENDIF RETURN uDefault METHOD EmptyData() CLASS TConectorDatosReg LOCAL hData := { => } hb_HAutoAdd( hData, .T. ) hData[ "DataVar" ] := { => } hData[ "DetalleVar" ] := { => } hData[ "_StructVar" ] := {} hData[ "_RegVar" ] := {} hData[ "_StructLine" ] := {} hData[ "_RegLine" ] := {} hb_HAutoAdd( hData[ "DataVar" ], .T. ) hb_HAutoAdd( hData[ "DetalleVar" ], .T. ) RETURN hData METHOD NormalizarStruct( aStruct, cGrupoDefecto ) CLASS TConectorDatosReg LOCAL aCampos := {} LOCAL nIndex LOCAL hCampo LOCAL nStructLen IF ! HB_ISARRAY( aStruct ) RETURN aCampos ENDIF nStructLen := Len( aStruct ) FOR nIndex := 1 TO nStructLen IF HB_ISHASH( aStruct[ nIndex ] ) hCampo := ::DefinicionCampo( aStruct[ nIndex ], cGrupoDefecto ) IF Len( hCampo[ "nombre" ] ) > 0 AAdd( aCampos, hCampo ) ENDIF ENDIF NEXT RETURN aCampos METHOD DefinicionCampo( hCampo, cGrupoDefecto ) CLASS TConectorDatosReg LOCAL cNombre := ::ValueString( ::HGet( hCampo, "nombre", ::HGet( hCampo, "name", ::HGet( hCampo, "campo", ::HGet( hCampo, "cName", "" ) ) ) ) ) LOCAL cGrupo := ::ValueString( ::HGet( hCampo, "grupo", ::HGet( hCampo, "group", ::HGet( hCampo, "tabla", ::HGet( hCampo, "alias", cGrupoDefecto ) ) ) ) ) LOCAL aPartes cNombre := AllTrim( cNombre ) cGrupo := AllTrim( iif( Len( cGrupo ) > 0, cGrupo, cGrupoDefecto ) ) IF At( ".", cNombre ) > 0 aPartes := ::SplitCampo( cNombre, cGrupoDefecto ) cGrupo := aPartes[ 1 ] cNombre := aPartes[ 2 ] ENDIF RETURN { ; "nombre" => cNombre, ; "grupo" => cGrupo, ; "tipo" => ::NormalizarTipo( ::HGet( hCampo, "tipo", ::HGet( hCampo, "type", ::HGet( hCampo, "cType", "texto" ) ) ) ), ; "longitud" => ::HGet( hCampo, "longitud", ::HGet( hCampo, "length", ::HGet( hCampo, "nLength", NIL ) ) ), ; "decimales" => ::HGet( hCampo, "decimales", ::HGet( hCampo, "decimals", ::HGet( hCampo, "nDecimals", NIL ) ) ) } METHOD NormalizarTipo( uTipo ) CLASS TConectorDatosReg LOCAL cTipo := Lower( AllTrim( ::ValueString( uTipo ) ) ) IF At( "," + cTipo + ",", ",c,char,character,string,texto," ) > 0 RETURN "texto" ENDIF IF At( "," + cTipo + ",", ",n,num,number,numeric,numerico,decimal," ) > 0 RETURN "numerico" ENDIF IF At( "," + cTipo + ",", ",d,date,fecha," ) > 0 RETURN "fecha" ENDIF IF At( "," + cTipo + ",", ",l,logical,bool,boolean,logico," ) > 0 RETURN "logico" ENDIF IF cTipo == "m" .OR. cTipo == "memo" RETURN "memo" ENDIF IF At( "," + cTipo + ",", ",i,image,imagen," ) > 0 RETURN "imagen" ENDIF RETURN iif( Len( cTipo ) > 0, cTipo, "texto" ) METHOD VariablesDataVar() CLASS TConectorDatosReg LOCAL hVariables := { => } LOCAL hDataVar := ::HGet( ::hDatos, "DataVar", { => } ) LOCAL aGrupos := ::HashKeys( hDataVar ) LOCAL aCampos LOCAL nGrupo LOCAL nCampo LOCAL cGrupo LOCAL cCampo LOCAL nGruposLen LOCAL nCamposLen hb_HAutoAdd( hVariables, .T. ) nGruposLen := Len( aGrupos ) FOR nGrupo := 1 TO nGruposLen cGrupo := aGrupos[ nGrupo ] aCampos := ::HashKeys( hDataVar[ cGrupo ] ) nCamposLen := Len( aCampos ) FOR nCampo := 1 TO nCamposLen cCampo := aCampos[ nCampo ] hVariables[ cGrupo + "." + cCampo ] := ::ValorDefinicion( hDataVar[ cGrupo ][ cCampo ] ) NEXT NEXT RETURN hVariables METHOD PrimerRegistroDetalleVar() CLASS TConectorDatosReg LOCAL aRegistros := ::GetRegistrosDetalle() RETURN iif( Len( aRegistros ) > 0, aRegistros[ 1 ], { => } ) METHOD ValorDefinicion( uDefinicion ) CLASS TConectorDatosReg IF HB_ISHASH( uDefinicion ) .AND. hb_HHasKey( uDefinicion, "valor" ) RETURN uDefinicion[ "valor" ] ENDIF RETURN uDefinicion METHOD RegistroDesdeArray( aCampos, aRegistro ) CLASS TConectorDatosReg LOCAL hRegistro := { => } LOCAL nIndex LOCAL cClave LOCAL nCamposLen hb_HAutoAdd( hRegistro, .T. ) nCamposLen := Len( aCampos ) FOR nIndex := 1 TO nCamposLen cClave := aCampos[ nIndex ][ "grupo" ] + "." + aCampos[ nIndex ][ "nombre" ] hRegistro[ cClave ] := iif( nIndex <= Len( aRegistro ), aRegistro[ nIndex ], NIL ) NEXT RETURN hRegistro METHOD SplitCampo( cCampo, cGrupoDefecto ) CLASS TConectorDatosReg LOCAL nPos := At( ".", cCampo ) IF nPos > 0 RETURN { Left( cCampo, nPos - 1 ), SubStr( cCampo, nPos + 1 ) } ENDIF RETURN { cGrupoDefecto, cCampo } METHOD HGet( hHash, cKey, uDefault ) CLASS TConectorDatosReg IF HB_ISHASH( hHash ) .AND. hb_HHasKey( hHash, cKey ) RETURN hHash[ cKey ] ENDIF RETURN uDefault METHOD ValueString( uValue ) CLASS TConectorDatosReg IF uValue == NIL RETURN "" ENDIF IF HB_ISSTRING( uValue ) RETURN uValue ENDIF IF HB_ISNUMERIC( uValue ) RETURN AllTrim( Str( uValue ) ) ENDIF IF HB_ISLOGICAL( uValue ) RETURN iif( uValue, "1", "" ) ENDIF RETURN AllTrim( hb_ValToStr( uValue ) ) METHOD NormalizeHashKeyName( uKey ) CLASS TConectorDatosReg LOCAL cKey IF HB_ISSTRING( uKey ) RETURN uKey ENDIF cKey := AllTrim( hb_ValToExp( uKey ) ) IF cKey == "NIL" RETURN "" ENDIF IF Len( cKey ) >= 2 .AND. Left( cKey, 1 ) == Chr( 34 ) .AND. Right( cKey, 1 ) == Chr( 34 ) cKey := SubStr( cKey, 2, Len( cKey ) - 2 ) ENDIF RETURN cKey