Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Como resolver este problema?

Iniciado por Diferencial, 08 de Enero de 2007, 09:31:21 PM

« anterior - próximo »

Diferencial

Tengo un archivo xml que guarda en su interior una interfaz de java.
Entonces yo leo todo el archivo usando DOM sin ningun problema, ahora bien
el problema radica cuando debo crear los componentes y darle las propiedades que he ido leyendo. Estoy usando ifs para las propiedades y para crear los componentes, pero esta forma es tediosa y ademas creo que no es la mas adecuada. Como puedo crear y asignar a mis componentes las propiedades sin tener que evaluarlo todo??
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

zupervaca

Como no se muy bien lo que quieres hacer, lo unico que te puede decir es que vayas memorizando los valores en una tabla hash por ejemplo, usando el nombre del valor como indice, luego pasale la tabla hash con los valores al objeto y que el se organice como quiera, no obstante para crear los controles no te queda mas remedio que hacerlo con ifs o mediante una tabla hash (otra vez por ejemplo) con punteros a funciones, si todos los objetos derivan de la misma clase puedes hacer una funcion que retorne el objeto creado ya que puedes tener en la clase base una funcion virtual que tenga como parametro la tabla hash entre otras cosas claro, algo asi:

class Base
{
public:
   virtual bool Inicializar( TablaHash* valores ) = 0;
}
class Boton : public Base
{
public:
   bool Inicializar( TablaHash* valores )
   {
       this->padre = valores.getctrlbase("padre");
       this->colorBoton = valores.getint("colorboton");
       this->coordenadas = valores.getcaja("coordenadas");
       ...
       return true;
   }
}

// Funcion que crea el control
Base* CrearControl( const char* tipo, TablaHash* valores )
{
       if( tipo == "boton" )
       {
           return (Base*)new Boton( valores );
       }
       return NULL;
}

Como en XML puede que no se especifiquen todos los valores puedes hacer que la funcion de la tablahash getint por ejemplo permita especificar un valor por defecto, algo asi:

colorpordefecto = 0xFF
this->colorBoton = valores.getint("colorboton", colorpordefecto);

Asi te ahorras tener que mirar si el valor existe o no, ya que lo hace la propia funcion dentro.

Editado: Queda dado de si que la tablahash no es una tablahash normal y corriente, puedes tener una clase tablahash y luego deriva otra para hacer las funciones especiales de obtener valores. Tambien deberias hacer una clase base para memorizar dentro de esta tablahash todos los tipos de valores que existan, date cuenta que solo el control sabe como manejarlos, es decir, el "colorboton" siempre va a ser un int, el "padre va a ser un control "base", etc.

class Item
{
public:
}
class ItemInt : public Item
{
public:
   int valor;
}
class ItemBase : public Item
{
public:
   Base* base;
}
class HashTableXML : public HashTable<Item*>
{
public:
   ...
   int getint( const char* id )
   {
       // obtener el puntero al elemento
       Item* item = ...
       // Retornarlo
       return ((ItemInt*)item)->valor;
   }
   ...
}

Otra forma es usar una tabla hash normal y corriente y que retorne siempre strings o el puntero al valor directamente y luego hacer una conversion a "int" para la getint, para el caso del control "base" (funcion getctrlbase) puedes hacer que retorne su nombre o su direccion en memoria en formato string (si siempre retornas un string) y luego hacer la conversion, pero esto ya es cuestion de gustos :wink:
Puede que el sistema de Item sea mas lioso al principio, pero al final si algun dia tienes que meter alguna funcionalidad extra por cada valor no tendrias que cambiar nada, por ejemplo, que mire en el registro de windows si ya existe un valor para el control.

class Item
{
public:
   bool verRegWin;
};

Asi agregarias la funcionalidad sin tener que tocar apenas codigo, exceptuando claro en las funciones de obtener los valores para ver si es true o false este valor.

Editado 2: Releyendo todo me he dado cuenta que lo mejor es que la tablahash memorize un objeto como este:

class Item
{
public:
   const char* valor;
   bool verRegWin; // Este bool es un ejemplo por poner algo
};
class HashTableXML : public HashTable<Item*>
{
public:
   int getint( const char* id )
   {
       // Obtener item
       Item *item = ...
       // Retornarlo
       return atoi(item->valor);
};

El motivo es sencillo, si quieres automatizar la lectura del xml tiene que ser todo strings ya que si no tendrias que andar creando otra estructura para automatizar el tipo de dato por su nombre.
PD: No borro el sistema anterior por si a alguien le ayuda en algo.

Editado 3: Para casos en el que un control puede tener elementos con nombres de valores iguales, haz que si existe el valor ya en la tablahash le agrega un numero correlativo, algo asi:

<ctrl tipo="lista">
   <item nombre="pepe">
   <item nombre"=luis">
</ctrl>

En la tabla hash quedaria algo asi:

lista0.nombre0 = pepe
lista0.nombre1 = luis

Ademas asi te aseguras que el control cuando se inicializa no coja valores erroneos si esta mal hecho el xml.
Despues para obtener esos valores lo puedes hacer con un simple while:

class Boton : public Base
{
public:
   bool Inicializar( TablaHash* valores )
   {
       this->padre = valores.getctrlbase("boton0.padre0");
       this->colorBoton = valores.getint("boton0.colorboton0");
       this->coordenadas = valores.getcaja("boton0.coordenadas0");
       char sz[256] = "boton0.nombre0";
       int n = 0;
       while( valores.tiene(sz) )
       {
           this->agregarElemento( valores.getstr(sz) );
           n++;
           sprintf( sz, "boton0.nombre%i", n );
       }
       ...
       return true;
   }
}

El while es un ejemplo, pero podria optimizarse por ejemplo que la funcion valores.getstr retornara true o false si el valor existe y que devolviera el valor en un puntero a string que le pasaras a la funcion, pero eso ya es cuestion de gustos.
Si quieres para optimizar al agregar valores a la tabla hash le puedes pasar una clave, por ejemplo, para el "nombre", su clave seria "nombre" y la propia tablahash va incrementando el valor en 1 cada vez que se use esa clave, el motivo de esto es que si no te tocaria mirar si existe "nombre0", "nombre1", "nombre2", etc. hasta encontrar el que no existe.

Editado 4: Tios me piro pa la piltra :shock:

Editado 5: Como veo que al final si metes el problema de la lista te recomiendo usar el sistema clasico, una jerarquia de nodos, algo asi:

class Nodo
{
public:
   const char* indice;
   const char* valor;
   Nodo* siguiente;
   Nodo* primerHijo;
   Nodo* padre;

   const char* obtenervalor( Nodo* buscarDesde, const char* indice )
   {
       // Buscar nodo
       Nodo* nodo = ...
       // Retornar valor
       return nodo->valor;
   }
}

Ahora si que me voy pa la pilta que ya estoy desvariando demasiado :?

Diferencial

Muchisimas gracias por tu respuesta, con tu explicación me ha quedado claro. Lo unico malo es que en java no existen punteros. Pero la idea de usar una tabla hash no se me habia ocurrido, ayer se me ocurrio una forma sin tener que evaluar el objeto, si se crea un identificador ahora usando una tabla hash tendria por un lado el identificador y por el otro el nombre de la clase algo asi como ejemplo b03f5f7f11d50a30, javax.swing.JFrame en el fichero xml vendria a ser algo asi como <object key="b03f5f7f11d50a30"/>

Aunque creo que es uno de los casos que me has expuesto.

La idea es reusar mas facilmente las interfaces de los usuarios es decir yo creo una interfaz en xml y despues haciendo este pequeño añadido puedes usarlo en cualquier proyecto hecho en java.
Ejemplo.
<object key="b03f5f7f11d50a30" title="Test">
  <Layout key="jd32mn3243mn">
     ....
  </object>
</object>
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.