Casos de Uso - Tipos de DAtos Estructurados

Caso 1. Clientes

1-     Definir el SDT:Se define de la misma forma que cualquier otro objeto GeneXus, desde el menú Object/New Object :

 

Edición del SDT

La edición cuenta con dos secciones. Una que almacena la estructura del objeto (Estructura), y otra donde se almacena la documentación del objeto (documentación)

            a – Estructura

          La estructura de un SDT puede tener elementos simples o compuestos:

 

 

Con el campo collection se indica si el elemento es o no una lista de elementos, es decir una colección.

 

El Editor de SDT es similar a los editores de objetos GeneXus ya conocidos. Entre sus propiedades, además de definir los elementos, permite importar la estructura de una transacción al SDT.

Por lo tanto podría crear otra estructura de clientes

 

a partir de la transacción:

y el resultado sería un SDT con la siguiente estructura

 

 

            b -  Documentación del SDT
Permite escribir un texto descriptivo del objeto. 

 

Uso del SDT – carga

  Una vez creado el SDT, se definen variables basadas en él desde cualquier objeto GeneXus.

Esta variable la podemos cargar recorriendo la Base de datos con el código:

For Each

    Where CliID = &CliId

    &Cliente.Nombre = Clinom

    &Cliente.Identidad = CliDoc

    &CLiente.Direccion.Empresa = Clidir

    &Cliente.Telefonos.Add(CliTel)

Endfor

 

Uso del SDT – carga vía XML

También podemos cargar la información desde un XML, simplemente con el código

 

       &Cliente.FromXml(&ClienteXml)

 

Una vez cargado el xml se obtiene los datos del cliente, accediendo a los ítems del SDT, de una forma mas clara  que tradicionalmente con el tipo de datos Xmlreader.

 

Similarmente se puede salvar el contenido de un SDT en un xml con:

 

       &ClienteXML = &Cliente.ToXml()

 

El contenido del string &CLienteXml será:

<Cliente xmlns = “name_Kb”>

   <Nombre>CliNom</Nombre>

   <Identidad>... </Identidad>

   <Nacionalidad>... </Nacionalidad>

   <Direccion>

        <Empresa>CliDir</Empresa>

        <Personal>CliDir2</Personal>

   </Direccion>

   <Telefonos>

        <item> CliTel1 </item>

        <item> CliTel2 </item>

  </Telefonos>

 

el mismo string puede ser generado con los tipos de datos XML, pero es bastante mas complejo, se precisan las siguientes líneas de código:

 

      &FileXml.opentoString()

      &filexml.WriteNSStartElement('Cliente', , "name_kb")            &filexml.WriteElement('Nombre', CliNom  )

  &filexml.WriteElement('Identidad', … )

  &filexml.WriteElement('Nacionalidad', … )

&filexml.WriteStartElement('Dirección’)

            &filexml.WriteElement('Empresa', CliDir )

            &filexml.WriteElement('Personal', CliDir2 )

&filexml.WriteEndElement()  

&filexml.WriteStartElement('Telefonos’)

            &filexml.WriteElement('Item', CliTel1  )

            &filexml.WriteElement('Item', CliTel2  )

    &filexml.WriteEndElement()  

&filexml.WriteEndElement() 

&ClienteXML = filexml.resultingString()

&filexml.Close()

 

Uso del SDT – Proveer/consumir

Ahora estamos en condiciones de proveer/consumir en un Webservice los datos del cliente. Para proveer simplemente se debe definir un procedimiento con call protocol SOAP y retornar por parámetro una variable de tipo Cliente. Para consumir simplemente utilizar el WSDL inspector y el mismo se encarga de crear los SDT necesarios para poder consumirlo

 

También se podría pasar o recibir el cliente en cualquier otro objeto GeneXus,  sin necesidad de acceder a la base de datos. En el pasado esto implicaba pasar n parámetros, algo como:

 

     Call(‘WtrabCliente’, &CliNom, &CLiDoc, &Clidir, &Clitel1, &CLitel2)

 

Ahora se traduce en:

 

     Call(‘WtrabCliente’, &cliente)

 

Colecciones

Si bien ya definimos una lista de teléfonos del cliente, una colección de un tipo simple (numérico), se podría definir un nuevo SDT, o el mismo, como una lista de clientes

 

En este caso son creados dos tipos de datos, uno Clientes y otro Clientes.Cliente.

 

 

Cargar una colección

Al definir una variable de tipo Clientes esta se cargaría de una forma similar al Cliente, pero es necesario utilizar el comando new, ya que los SDT por defecto se asignan por referencia. Con el siguiente código podríamos cargar la lista de clientes.

 

For Each

    &Cliente.Nombre = Clinom

    &Cliente.Identidad = CliDoc

    &Cliente.Nacionalidad= &Nacionalidad

    &CLiente.Direccion.Empresa = Clidir

    &Cliente.Telefonos.Add(CliTel)

   &Clientes.add(&Cliente)

   &Cliente = new Clientes.Cliente ()

Endfor

 

Al definir una variable se hace un new implicito, la primera vez. Por esto en el caso de la carga el new es el ultimo comando del for each, luego de cargar el primer cliente.

 

Recorrer una colección

Luego de cargada la estructura de clientes es posible recorrerla con el comando For IN Array, con las siguientes líneas de código:

 

   For &Cliente in Clientes

     &Clinom = &cliente.Nombre

     ...

   EndFor

 

Proveer/consumir servicios con colecciones.

Ahora podemos proveer/consumir en un Webservice la lista de clientes. Al igual que en el caso de los datos del cliente, para proveer simplemente se debe definir un procedimiento con call protocol SOAP y retornar por parámetro una variable de tipo Clientes.

Para consumir utilizar el WSDL inspector.

 

Muchos de los webservices disponibles proveen datos estructurados, es fundamental esta feature para su uso, por ejemplo en:  http://www.swanandmokashi.com/HomePage/WebServices/Horoscope.asmx?WSDL , se provee, diariamente, la lista de los signos del horóscopo, con su respectivo pronóstico. En su portal podría tener:

 

Para ello debería

1)     incluir la definición del webservices desde diseño:

2)     Definir en un objeto Web Panel dos variables, “array” e “item”, con los nuevos tipos de datos y una variable, “ws” con el servicio:

3)     Codificar la carga de un subfile recorriendo el array resultado de la invocación:

 

Event Load

&array = &ws.GetHoroscope()

For &item in &array

    &SodiacSign = &item.ZodiacSign

    &ForeDailiy = &item.DailyForecast

    load

endfor

EndEvent  // Enter

 

Caso 2. Listas

También cabe destacar que existen muchas formas de representar una realidad, por ejemplo una Lista de largo variable de numéricos es posible definirlo como:

 

Caso 2.1

Una estructura que es una lista de estructurados LstNumItem que contiene un elemento numérico. Para referenciar un valor: LstNum.Item(X).Num

Carga:

&LstnumItem.Num = 1

&Lstnum.Add(&LstnumItem)

 

&LstnumItem = new LSTNUM.LSTNUMItem()

&LstnumItem.Num = 2

&Lstnum.Add(&LstnumItem)

Recorrida:

For & LstnumItem In &lstNum

    &item = & LstnumItem.Num

Endfor

siendo &LstnumItem à S(LSTNUM.LSTNUMItem)

          &lstNum à S(LSTNUM)

 

Caso 2.2

Es una estructura que tiene un elemento numérico que es una lista. Para referenciar un elemento sería: LstNum2.Num.Item(x).

Carga:

  &LstNum2.Num.Add(1)

  &LstNum2.Num.Add(2)

Recorrida:

  &tope = &LstNum2.Num.Count

  Do while &i = &tope

   &item = &LstNum2.Num.Item(&i)

   &i = &i +1

  enddo

En este caso no es posible utilizar la propiedad Item name.

 

Caso 2.3

Es una estructura que es una lista de numéricos. Para referenciar un elemento sería LstNum3.Item( X).

 

Carga:

  &LstNum3.Add(1)

  &LstNum3.Add(2)

Recorrida:

&tope = &LstNum3.Count

  &i = 1

  Do while &i = &tope

   &item = &LstNum3.Item(&i)

   &i = &i +1

   enddo

En este caso no es posible definir elementos simples dentro de la estructura.

Caso 2.4

Muy similar al caso 2.1, pero el item esta definido en otra estructura.

 

Una estructura que es una lista de estructurados Item4, este contiene un único  elemento numérico. Para referenciar un valor: LstNum4.Item(X).Num

Carga:

&LstNum4Item.Num = 1

&Lstnum4.Add(&LstNum4Item)

 

&LstNum4Item = new Item4()

&LstNum4Item.Num = 2

&Lstnum4.Add(&LstNum4Item)

Recorrida:

For &LstNum4Item In &lstNum4

  &item = &LstNum4Item.Num

Endfor

siendo &Lstnum4Item à S(Item4)

          &lstNum4 à S(LSTNum4)

 

Caso 3. Listas anidadas

Es posible definir matrices, o sea listas de listas

 

Caso 3.1

 

 

Es una lista de estructurados, con tres elementos un numérico, un char y otra lista de estructurados

Para referenciar un elemento del cabezal:

          &Levels.LV1ID con &levels de tipo S(Levels)

Para referenciar un elemento de las líneas: &Levels.level2.LV2ID

 

Carga:

 

for &i = 1 to 4                                                   //carga las columnas

  &levels1.Lv1ID = &i

  &levels1.LV1sec = ‘Column:  ' + str(&i,2) 

 

  For &j = 1 to 5                                                // carga las líneas

    &levels2.LV2ID = &j

    &levels2.LV2sec = 'Row: ' + str(&j,2) 

    &levels1.Level2.Add(&levels2)                       // agrega a la lista de líneas

    &levels2 = new Levels.Level1.Level2()          // crea una instancia para la proxima línea

  endfor

 

  &levels.Add(&levels1)                          // agrega a la lista de columnas

  &levels1 = new Levels.Level1()           // crea una instancia para la proxima columna

endfor

 

Recorrida:

 

  for &levels1 in &levels

    msg(&levels1.LV1sec)

    for &levels2 in &levels1.Level2

       msg(&levels2.LV2sec)

    endfor

  endfor

 

Ejemplo

Es posible bajar un ejemplo desde:  http://www.gxopen.com/main/hproject.aspx?313