Comunidad de diseño web y desarrollo en internet online

Objetos anidados

Citar            
MensajeEscrito el 03 Sep 2008 01:07 pm
Hola gente, se me ha presentado un problema en un proyecto y no se como encararlo... estoy utilizando la clase DataConvert (by Dano) que publicaron aquí hace un tiempo, y me topé con ciertas limitaciones que no sé como solucionar.

El asunto es que estamos trabajando con ValueObject, osea, una capa de modelo de objetos donde defino solamente sus propiedades (sería una réplica de las clases que manejo en .Net con los WS), aqui dejo un ejemplo:

Código :

package Entities
{
   public class Oportunidad
   {
      [Bindable]
      public var Id:int;
        public var Titulo:String;
        public var IdCliente:int;
        public var IdClienteOld:int;
        public var ObjCliente:Cliente;
        public var IdEmpleado:int;
        public var IdEmpleadoOld:int;
        public var ObjEmpleado:Empleado;
        public var Categoria:String;
        public var Valoracion:String;       
        public var ComoSeEncontro:String;
        public var FechaApertura:Date;
        public var FechaEstimadaCierre:Date;
        public var Probabilidad:int;
        public var IngresosEstimados:Number;
        public var Cerrado:Boolean;
        public var Descripcion:String;
        public var Comentarios:String;
        
      public function Oportunidad()
      {
      
      }

   }
}


Como se vé, en la 5ta propiedad ya tenemos como tipo de dato un Objeto de la clase Cliente, entonces cuando utilizamos la clase DataConvert, no da un lindo error.

Conocen alguna solución para ésto? Cómo se puede orientar una solución al problema?

Saludos, espero puedan ayudarme :)

Jonathan Griguol

Por jgriguol

35 de clabLevel



Genero:Masculino  

Argentina

msie7
Citar            
MensajeEscrito el 03 Sep 2008 01:47 pm
Agrega

import Client (con la ruta del paquete si es que lo tienes dentro de algún directorio)

Eso hará que reconozca el tipo de dato

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 03 Sep 2008 01:51 pm
¿Qué error? :?
¿En qué código da ese error? :?
¿Has importado la clase?

Por Zah

BOFH

4290 de clabLevel

27 tutoriales
5 articulos

  Bastard Operators From Hell Editores

Zaragoza, España

firefox
Citar            
MensajeEscrito el 03 Sep 2008 01:52 pm
Estaba leyendo el tip de Dano (tendría que haberlo hecho antes de contestar :) , y veo que dice que no se puede pasar un VO desde PHP. Sin embargo usando amfphp si se puede pasar VO's (hay una larga discusión en la lista de correo de amfphp), aquí doy un ejemplo con una clase muy básica (sí, el clásico Person, jeje) http://flash-db.com/Tutorials/helloAS3/

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 03 Sep 2008 01:53 pm
De hecho, con weborb sí se puede, pero no cuando escribí el artículo.

Por Zah

BOFH

4290 de clabLevel

27 tutoriales
5 articulos

  Bastard Operators From Hell Editores

Zaragoza, España

firefox
Citar            
MensajeEscrito el 03 Sep 2008 02:05 pm
Corrección: by Zah (no dano)
El tuto de de helloAS3 es del 12.07.2007, la discusión sobre VO's venía desde hacía un par de meses, aunque claro, no estaba casi difundido. Desconozco weborb.
Muy interesante lo de Reflections, no sabía que había un método que te sacaba la instrospección como XML

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 03 Sep 2008 02:47 pm
Si ya se puede con WebOrb tanto para .NET como para PHP. Con fluorine para .NET también se puede y no recuerdo si ya se puede con las últimas versiones de AMFPHP.

Respecto a la clase, como dicen solisarg y Zah, importando la clase, no debería dar error.

saludos

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 03 Sep 2008 02:52 pm
Mmmm.. creo que me expliqué mal.. aunque por ahi viene la cosa. Las clases están importadas, ese no es el problema.

Este es el bloque de código de DataConvert.as donde cacha el error

Código :

catch(err:Error){                    
               //Si estamos tratando de parsear una propiedad con un tipo de                    
               //datos distinto, mostramos un error.                  
               throw new Error("Error setting " + i + " to the new class. Incompatible datatypes. \n" + err.message);               
               }  


Esto sucede porque estoy mandando como parámetro, la propiedad ObjCliente de tipo Cliente, al no ser un tipo ordinario de datos ni ser del tipo "Oportunidades" no puede convertirlo en un objeto Cliente, la clase no está preparada para esa funcionalidad.

Por cierto, estoy trabajando con WebServices en .Net, acá les copio un resultado (XML) del método sobre el cual estoy trabajando:
Como van a ver, el webservice me trae todas las propiedades de la "oportunidad" que a la vez pertenece a un Cliente, del cual tambien ya traigo sus datos, en el XML se ve anidado...

Código :

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfOportunidad xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://XlineProjectTools.org/">
  <Oportunidad>
    <Id>7</Id>
    <Titulo>ASDt asdsdadsaadsasdsadasssssssssss ssssssssssssssssss </Titulo>
    <IdCliente>26</IdCliente>
    <ObjCliente>
      <Id>26</Id>
      <Codigo>1</Codigo>
      <Organizacion>dulcito</Organizacion>
      <Apellido>perez</Apellido>
      <Nombre>raul</Nombre>
      <Email1 />
      <Email2 />
      <Msn />
      <Cargo />
      <TelefonoTrabajo />
      <TelefonoParticular />
      <TelefonoMovil />
      <NumeroFax />
      <Direccion />
      <Ciudad />
      <CodigoPostal />
      <IdProvincia>0</IdProvincia>
      <OldIdProvincia>0</OldIdProvincia>
      <IdPais>0</IdPais>
      <OldIdPais>0</OldIdPais>
      <Web1 />
      <Web2 />
      <Notas />
      <IdRubro>0</IdRubro>
      <OldIdRubro>0</OldIdRubro>
      <FacturacionAnual>0</FacturacionAnual>
      <Cuit />
      <IIBB />
      <Municipalidad />
      <IdTipoCliente>0</IdTipoCliente>
      <OldIdTipoCliente>0</OldIdTipoCliente>
      <FechaAperturaCTaCTe>0001-01-01T00:00:00</FechaAperturaCTaCTe>
      <SaldoInicial>0</SaldoInicial>
      <SaldoActual>0</SaldoActual>
      <DeudaTope>0</DeudaTope>
    </ObjCliente>
    <IdEmpleado>9</IdEmpleado>
    <ObjEmpleado>
      <Id>9</Id>
      <Nombre>Jeronimo</Nombre>
      <Apellido>Visñovezky</Apellido>
      <Organizacion>x.Line</Organizacion>
      <Cargo>Relaciones Exteriores</Cargo>
      <TelefonoTrabajo />
      <TelefonoParticular>0351 422 8218</TelefonoParticular>
      <TelefonoMovil>351 3 181474</TelefonoMovil>
      <NumeroFax />
      <Direccion>9 de Julio 832 3º D</Direccion>
      <Ciudad>Cordoba</Ciudad>
      <CodigoPostal>5000</CodigoPostal>
      <Barrio>Alberdi</Barrio>
      <IdProvincia>2</IdProvincia>
      <OldIdProvincia>2</OldIdProvincia>
      <ObjProvincia>
        <IdProvincia>0</IdProvincia>
        <NombreProvincia />
        <IdPais>0</IdPais>
        <IdPaisOld>0</IdPaisOld>
      </ObjProvincia>
      <ObjPais>
        <Id>1</Id>
        <Nombre>ARGENTINA</Nombre>
      </ObjPais>
      <IdPais>1</IdPais>
      <OldIdPais>1</OldIdPais>
      <Email1>[email protected]</Email1>
      <Email2>[email protected]</Email2>
      <Web1>www.jeronimov.com.ar#http://www.jeronimov.com.ar#</Web1>
      <EstadoCivil>Casado(a)</EstadoCivil>
      <DNI>26.433.134</DNI>
      <FechaIngreso>2007-01-15T00:00:00</FechaIngreso>
      <Nacionalidad>Argentino</Nacionalidad>
      <CantidadHijos>0</CantidadHijos>
      <CantidadHermanos>2</CantidadHermanos>
      <Notas />
      <NombrePadre>Carmelo Horacio Visnovezky (Fallecido)</NombrePadre>
      <NombreMadre>Maria Blanca Garcia</NombreMadre>
      <IdProfesionPadre>19</IdProfesionPadre>
      <OldIdProfesionPadre>19</OldIdProfesionPadre>
      <IdProfesionMadre>20</IdProfesionMadre>
      <OldIdProfesionMadre>20</OldIdProfesionMadre>
      <Activo>0</Activo>
      <Primario>1</Primario>
      <Secundario>1</Secundario>
      <Terciario>0</Terciario>
      <Universitario>1</Universitario>
      <PosGrado>0</PosGrado>
      <IdTipoRelacion>4</IdTipoRelacion>
      <OldIdTipoRelacion>0</OldIdTipoRelacion>
      <CajaAhorro />
      <IdBanco>0</IdBanco>
      <OldIdBanco>0</OldIdBanco>
      <PrecioHora>14</PrecioHora>
    </ObjEmpleado>
    <Categoria>dfg</Categoria>
    <Valoracion>Templada</Valoracion>
    <ComoSeEncontro />
    <FechaApertura>0001-01-01T00:00:00</FechaApertura>
    <FechaEstimadaCierre>2008-02-02T00:00:00</FechaEstimadaCierre>
    <Probabilidad>20</Probabilidad>
    <IngresosEstimados>0</IngresosEstimados>
    <Cerrado>false</Cerrado>
    <Descripcion>tre</Descripcion>
    <Comentarios>[Versión:  26/06/2008 16:20:16] tyhjjhhjg
[Versión:  25/06/2008 15:29:58] rt
[Versión:  25/06/2008 15:29:14] uio
</Comentarios>
  </Oportunidad>
</ArrayOfOportunidad>



Luego donde llamamos al webservice, utilizo el método objectToClass, pero puedo mandar unicamente la clase Oportunidad como parametro, entonces, como obtengo el objeto Cliente que tengo anidado?, me explico? Ahi me da error en esa conversión

Código :

for each (var item : Object in event.result){
            var oportunidad : Oportunidad = DataConvert.objectToClass(item,Oportunidad) as Oportunidad;
            result.addItem(oportunidad);
            }


La clase Oportunidades está en el primer post, les dejo la clase de acceso a datos Oportunidades completa:

Código :

// ActionScript file
package Data
{
   import Entities.Oportunidad;
   import Entities.Cliente;
   import Util.DataConvert;
   
   import mx.collections.ArrayCollection;
   import mx.rpc.Fault;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   import mx.rpc.soap.LoadEvent;
   import mx.rpc.soap.WebService;
    
    public  class OportunidadesWS
    {
      
      
      [Bindable] private var result:ArrayCollection = new ArrayCollection();
      private var objOportunidades : WebService = new WebService();
      [Bindable] private var arrOportunidades:ArrayCollection;      


      public function  get Oportunidades():ArrayCollection
      {
         getOportunidades();
         return result;
         
      }
      
      private function getOportunidades():void
      {
         objOportunidades.wsdl = "http://192.168.1.101/XlineProjectTools/WebServices/Oportunidades.asmx?WSDL";
         objOportunidades.addEventListener(LoadEvent.LOAD, onOportunidadWSL);
         objOportunidades.addEventListener(FaultEvent.FAULT, onWebServiceFault);
         objOportunidades.loadWSDL();
       }
   
      //listener que avisa cuando el WSDL se ha cargado
      private function onOportunidadWSL (event:LoadEvent):void
      { 
         objOportunidades.ObtenerOportunidades.addEventListener(ResultEvent.RESULT, onGetOportunidad); //cuando llame al ws se va a ejecutar onGetOportunidad 
         objOportunidades.ObtenerOportunidades(); //metodo de ws
      }
      
   
      private function onGetOportunidad (event:ResultEvent):ArrayCollection
      {         
         arrOportunidades=event.result as ArrayCollection;
         var datos:ArrayCollection = new ArrayCollection();
         
         
         for each (var item : Object in event.result){
            var oportunidad : Oportunidad = DataConvert.objectToClass(item,Oportunidad) as Oportunidad;
            result.addItem(oportunidad);
            }
         
         /*         
         for each (var item : Object in event.result){
               var oportunidad:Oportunidad = new Oportunidad();
               oportunidad.Id = item.Id;
               oportunidad.Titulo = item.Titulo;
               oportunidad.IdCliente = item.IdCliente;
               oportunidad.IdClienteOld = item.IdClienteOld;
               
               result.addItem(oportunidad);
            }
         */
         
         return result;         
      }
      
      
      // En caso de que el WebService no puede ser cargado.
      public function onWebServiceFault(event:FaultEvent):void 
      {
         var fault: Fault = event.fault;
         var message :String = "An error occurred. The details are as follows\ncode: " + fault.faultCode;
         message += "\ndetail: " + fault.faultDetail;
         trace("Web Service Error :" + message);
      }
            

    }
}

Por jgriguol

35 de clabLevel



Genero:Masculino  

Argentina

msie7
Citar            
MensajeEscrito el 03 Sep 2008 02:57 pm
Got it. La clase así como esta, no te va a ayudar para eso, tendrás que modificarla.

En esta línea:

Código :

tClass(newClass)[i] = value[i];


Antes de asignar el valor, obten el tipo de datos, si es un tipo primitivo(string, number, etc) pues dejas la línea como esta, sino tendrías que invocar de manera recuersiva DataConvert.objectToClass.

Saludos

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 03 Sep 2008 03:21 pm
Asi como con hasOwnProperty puedo saber si la propiedad existe, hay forma de "capturar" el tipo de dato? para cuando no sea primitivo ejecutar recursivamente el método.

Por ej, preguntar if tipoDato != tipoDatoPrimitivo {DataConvert}

De lo contrario tendria que agregar una propiedad más a cada clase de tipo String indicando el nombre de la clase... para luego decidir cuando ejecutar de nuevo objectToClass, pero de ésa forma tendria que estar hard coded.

Por jgriguol

35 de clabLevel



Genero:Masculino  

Argentina

msie7
Citar            
MensajeEscrito el 03 Sep 2008 03:35 pm

jgriguol escribió:

Asi como con hasOwnProperty puedo saber si la propiedad existe, hay forma de "capturar" el tipo de dato? para cuando no sea primitivo ejecutar recursivamente el método.

Por ej, preguntar if tipoDato != tipoDatoPrimitivo {DataConvert}

De lo contrario tendria que agregar una propiedad más a cada clase de tipo String indicando el nombre de la clase... para luego decidir cuando ejecutar de nuevo objectToClass, pero de ésa forma tendria que estar hard coded.


Si hay una forma, hace mucho que ya no muevo actionscript, pero recuerdo que para saber los tipos puedes hacer:

trace(typeof Variable);

No recuerdo si algo como getClassName, o algo así. Pero de que hay forma, la hay, no recuerdo exactamente como.

saludos

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 03 Sep 2008 03:41 pm
En AS3 puedes hacer

if(SomeVar is SomeClass)

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 03 Sep 2008 04:41 pm
Bueno, solucionado a la ligera... méritos de mi compañero de trabajo que hace desde el lunes que está con flex 3. Así quedo la clase, hay que intentar hacerla lo más genérica posible

Código :

package Util{
/**Esta clase contiene funciones para la conversión de distintos tips de datos.*/   

   import Entities.Cliente;
   import Entities.Banco;
   import Entities.Empleado;
   import Entities.Oportunidad;
   import Entities.Pais;
   import Entities.Provincia;
   import Entities.RubroEmpresa;
   import Entities.TipoCliente;   

   public class DataConvert{           
      /**Esta función sirve para convertir un objeto cualquiera      
      * en una instancia de una clase.      
       * * @param value El objeto que queremos parsear.      
       * * @param tClass  El nombre de la clase en la que queremos transformar el objeto.      
       * * @return Una instancia de la clase que hemos pedido */        
      
      public static function objectToClass(value:Object, tClass:Class):Object {                  
         //Creamos una instancia de la clase         
         var newClass:Object;         
         newClass = new tClass();            
         //Usamos el bucle "for in", que nos permitirá recorrer tanto      
         // las propiedades del objeto, como sus valores.         
         for(var i:String in value){            
            //Usamos la función de la clase Object hasOwnProperty para            
            //saber si hemos definido esa propiedad en la clase.
            switch (i) {
            case "ObjCliente" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],Cliente) as Cliente;
               break;
            case "ObjEmpleado" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],Empleado) as Empleado;
               break;
            case "ObjBanco" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],Banco) as Banco;
               break;
            case "ObjPais" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],Pais) as Pais;
               break;
            case "ObjProvincia" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],Provincia) as Provincia;
               break;         
            case "ObjRubro" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],RubroEmpresa) as RubroEmpresa;
               break;   
            case "ObjTipoCliente" :
               tClass(newClass)[i]= DataConvert.objectToClass(value[i],TipoCliente) as TipoCliente;
               break;                                                                     
            default:
               if( newClass.hasOwnProperty(i) )
               {               
                  try 
                  {   
                     //Le asignamos las propiedades del objeto                      
                     //a la nueva instancia de la clase.                  
                     tClass(newClass)[i] = value[i];
                     
                  }               
                  catch(err:Error){                    
                  //Si estamos tratando de parsear una propiedad con un tipo de                    
                  //datos distinto, mostramos un error.                  
                  throw new Error("Error setting " + i + " to the new class. Incompatible datatypes. \n" + err.message);               
                  }            
               }
               break;
         }      
            }                  
      return newClass;      
      }
      
      
   }
}


Acá se llama al webservice:

Código :

// ActionScript file
package Data
{
   import Entities.Oportunidad;
   
   import Util.DataConvert;
   
   import mx.collections.ArrayCollection;
   import mx.rpc.Fault;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   import mx.rpc.soap.LoadEvent;
   import mx.rpc.soap.WebService;
    
    public  class OportunidadesWS
    {
      
      
      [Bindable] private var result:ArrayCollection = new ArrayCollection();
      private var objOportunidades : WebService = new WebService();
      [Bindable] private var arrOportunidades:ArrayCollection;      


      public function  get Oportunidades():ArrayCollection
      {
         getOportunidades();
         return result;
      }
      
      private function getOportunidades():void
      {
         objOportunidades.wsdl = "http://localhost/XlineProjectTools/WebServices/Oportunidades.asmx?WSDL";
         objOportunidades.addEventListener(LoadEvent.LOAD, onOportunidadWSL);
         objOportunidades.addEventListener(FaultEvent.FAULT, onWebServiceFault);
         objOportunidades.loadWSDL();
       }
   
      //listener que avisa cuando el WSDL se ha cargado
      private function onOportunidadWSL (event:LoadEvent):void
      { 
         objOportunidades.ObtenerOportunidades.addEventListener(ResultEvent.RESULT, onGetOportunidad); //cuando llame al ws se va a ejecutar onGetOportunidad 
         objOportunidades.ObtenerOportunidades(); //metodo de ws
      }
      
   
      private function onGetOportunidad (event:ResultEvent):ArrayCollection
      {         
         arrOportunidades=event.result as ArrayCollection;
         var datos:ArrayCollection = new ArrayCollection();

         for each (var item : Object in event.result){
         var oportunidad : Oportunidad = DataConvert.objectToClass(item,Oportunidad) as Oportunidad;
         result.addItem(oportunidad);   
         }
      
         
         return result;         
      }
      
      
      // En caso de que el WebService no puede ser cargado.
      public function onWebServiceFault(event:FaultEvent):void 
      {
         var fault: Fault = event.fault;
         var message :String = "An error occurred. The details are as follows\ncode: " + fault.faultCode;
         message += "\ndetail: " + fault.faultDetail;
         trace("Web Service Error :" + message);
      }
            

    }
}



Gracias!

Por jgriguol

35 de clabLevel



Genero:Masculino  

Argentina

msie7

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.