Cómo crear una clase que ofrezca el interfaz DynObject

En el post anterior referente a los DynObjects, se hizo una pequeña explicación y motivación de su uso en distintos ámbitos de gvSIG. Este HowTo se presenta como un ejemplo en el que se pretende describir el proceso de definición y su uso.

Para apoyar la explicación, se tomará un ejemplo real sobre el que se citarán los pasos a seguir para que quede más ilustrado.

El modelo de objetos del ejemplo es bastante básico: partimos de un interfaz, que es implementado por una clase abstracta. Ésta última, a su vez, es extendida por más clases (se describirá sólo una, ya que el resto sería identíco para la definición de DynObjects), tal y como muestra la figura siguiente:

Definición de los DynObjects

Vamos a cumplimentar la definición básica de un DynObject:

  • Lo primero es que la clase que va a albergar los DynObjects debe extender la clase de mismo nombre.
    public interface ChartProperties extends DynObject
  • Esto nos genera una cantidad de métodos a implementar (en nuestro ejemplo, en la clase abstracta AbstractChartProperties).
    DynClass getDynClass();
    
    void implement(DynClass dynClass);
    
    void delegate(DynObject dynObject);
    
    Object getDynValue(String name)  throws DynFieldNotFoundException ;
    
    void setDynValue(String name, Object value)  throws DynFieldNotFoundException ;
    
    boolean hasDynValue(String name); 
    
    Object invokeDynMethod(String name, DynObject context) throws DynMethodException;
    
    Object invokeDynMethod(int code, DynObject context) throws DynMethodException;
    
    void clear();

    En nuestro caso, delegaremos en la implementación genérica, rellenando los métodos de la siguiente forma:

    • Definimos un DynObjectpor defecto que se creará en el constructor del objeto:
      protected DelegatedDynObject data;
      
      protected AbstractChartProperties(String definitionName){
        this.data = (DelegatedDynObject) 
          ToolsLocator.getDynObjectManager().createDynObject(definitionName, "Chart");
      }
    • Completamos la definición de los métodos delegando en su implementación genérica:
      public DynClass getDynClass() {
          return data.getDynClass();
      }
      
      public void implement(DynClass dynClass) {
          data.implement(dynClass);
      }
      
      public void delegate(DynObject dynObject) {
          data.delegate(dynObject);
      }
      
      public Object getDynValue(String name) throws DynFieldNotFoundException {
          return data.getDynValue(name);
      }
      
      public void setDynValue(String name, Object value)
              throws DynFieldNotFoundException {
          data.setDynValue(name, value);
      }
      
      public boolean hasDynValue(String name) {
          return data.hasDynValue(name);
      }
      
      public Object invokeDynMethod(String name, DynObject context)
              throws DynMethodException {
          return data.invokeDynMethod(name, context);
      }
      
      public Object invokeDynMethod(int code, DynObject context)
              throws DynMethodException {
          return data.invokeDynMethod(code, context);
      }
      
      public void clear() {
          data.clear();
      }
  • Ahora definimos la DynClass:
    public static void registerDefinition(){
      DynObjectManager manager = ToolsLocator.getDynObjectManager();
      DynClass definition = manager.get("Chart","ChartProperties");
      if(definition == null){
        definition = manager.createDynClass("Chart", "ChartProperties", "aquí va la descripción");
        definition.addDynFieldString("name").setMandatory(false);
        definition.addDynFieldString("title").setMandatory(true);
        definition.addDynFieldString("type").setMandatory(true);
        definition.addDynFieldObject("service").setClassOfValue(ChartService.class);
        manager.add(definition);
      }
    }

    Analizamos por partes los elementos más destacados de esta definición:

    • Como se puede ver, el método es estático:
      public static void registerDefinition(){
      ...

      el registro de la DynClass se debe hacer una única vez, cuando se carga la librería, por lo que se llamará a este método en el momento se haga el doInitialize() de la librería correspondiente.

      @Override
      protected void doInitialize() throws LibraryException {
        ...
        AbstractChartProperties.registerDefinition();
      }
    • Tras obtener el manager de los DynObjects, intentamos recuperar la definición de la DynClass (del namespace“Chart”, la DynClass de identificador “ChartProperties”). Si no existe, la creamos:
      DynObjectManager manager = ToolsLocator.getDynObjectManager();
      DynClass definition = manager.get("Chart","ChartProperties");
      if(definition == null){
        definition = manager.createDynClass("Chart", "ChartProperties", "aquí va la descripción");
           ...
        }
      ...
    • Por último, añadimos a la definición los atributos que compondrán la DynClass. La definición contiene los métodos para trabajar con los tipos básicos (String, Integer, Float, …):
      ...
      definition.addDynFieldString("name").setMandatory(false);
      definition.addDynFieldString("title").setMandatory(true);
      definition.addDynFieldString("type").setMandatory(true);
      ...

      en el caso de que se trabaje con otra clase más compleja, ésta deberá implementar la clase DynObject también, delegando su definición en ella misma.

      ...
      definition.addDynFieldObject("service").setClassOfValue(ChartService.class);
      ...
    • Una vez completa la definición, la añadimos al mánager:
      ... 
        manager.add(definition);
      }
  • Además, y esto ya más por comodidad, definiremos métodos de acceso get y seta los atributos:
    public void setChartType(String type) {
      data.setDynValue("type", type);
    }
    
    public String getChartType() {
      return (String) data.getDynValue("type");
    }

En el caso de querer ampliar esta definición a alguna de las clases que extienden a AbstractChartProperties para ampliar la definición del DynObject, los pasos a seguir serían:

  • Dado que se puede delegar en los métodos de la clase abstracta, la definición de los métodos típicos de DynObject no sería necesario volver a implementarlos.
  • Lo único necesario, sería aumentar la definición de la DynClass, en función de nuestras necesidades:
    public static void registerDefinition(){
      DynObjectManager manager = ToolsLocator.getDynObjectManager();
      DynClass definition = manager.get("Chart","BarsChart");
      if(definition == null){
          definition = manager.createDynClass("Chart", "BarsChart", "aquí va la descripción");
          definition.addDynFieldString("xValuesTitle").setMandatory(true);
          definition.addDynFieldString("yValuesTitle").setMandatory(true);
          definition.extend("Chart", "ChartProperties");
          manager.add(definition);
      }
    }

    El proceso es muy similar, salvo que se definen úncamente en la DynClass los parámetros añadidos respecto a la clase extendida, indicando que recoja el resto de la definición del padre a través de la instrucción:

    ...
      definition.extend("Chart", "ChartProperties");
    ...

    Este método también es estático y se carga una única vez cuando se carga la librería correspondiente.
    Nota: debido a que utiliza la definición de la clase AbstractChartProperties, hay que asegurarse que se carga después utilizando cualquiera de los métodos disponibles para la carga de librerías (poniendo el registro de la clase padre en el doInitilize() y las que dependen de él en el postInitialize(), o a través de fijar dependencias en el método doRegistration())

En el siguiente post, comentaremos cómo crear una clase que implementa el mecanismo de persistencia de gvSIG 2.0 basado en DynClasses.

This entry was posted in development, gvSIG Desktop, spanish. Bookmark the permalink.

One Response to Cómo crear una clase que ofrezca el interfaz DynObject

  1. Pingback: DynObjects en gvSIG 2.0 | gvSIG blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s