[Gvsig_desarrolladores] "Undefined Reference" cuando intento usar PluginServices

Joaquin del Cerro jjdelcerro.gvsig en gmail.com
Mar Oct 9 23:28:10 CEST 2012


El 04/10/12 11:00, Alexandre P.M. escribió:
> Hola Joaquin,
>
> Muchas gracias por la explicacion, ya que estoy seguro que es la enesima vez
> que comentas la arquitectura de desarrollo de plugins en gvSIG.
>
> Me gustaria comentarte un poco mi situacion: estoy intentando realizar una
> extension para exportar datos de gvSIG a JASPA como parte de un proyecto
> final de carrera. Soy completamente primerizo en gvSIG (2 semanas con el) y
> con poco experiencia en desarrollos en Java. No quiero usar esto como
> disculpa, pero si para establecer el contexto en el que trabajo.
>
> Mas o menos tengo clara la estructura del proyecto, ya no solo por la
> documentacion que habia leido en la web sino como parte de la arquitectura
> en 3 capas en las que se separa la logica de la IU. Aun asi, todavia estoy
> acostumbrandome a ella, ya que no suelo trabajar con este tipo de proyectos
> (trabajo en el area de BI y es un mundo un tanto diferente del desarrollo de
> aplicaciones).
>
> Debido a la naturaleza del trabajo, no me interesa en ningun momento
> realizar el desarrollo de un modo diferente al que el equipo de gvSIG
> propone, especialmente porque necesito dejarlo preparado para ser ampliado
> por otros desarrolladores (lo que estoy intentando obtener es la fase 1 de
> un proyecto de mas envergadura).
>
> Lo que si me estoy encontrando es un poco la dificultad para saber de donde
> obtener las cosas y donde aplicar dicha logica, ya que no lo he encontrado
> en la documentacion . Como ejemplo: necesito saber las capas que se han
> cargado en la vista y añadirlas a un JListBox en mi extension. Mediante
> pruebas para obtener dichas capas, pense que tenia que obtenerlas a traves
> de PluginServices.getMDIManager() (creo que era asi el metodo) a traves de
> la logica (lib-api, lib-impl) pero me estaba saltando un paso para saber si
> se podian obtener de forma rapida (la dependencia con IWindow es otra prueba
> que habia hecho y que realmente no necesito). Otros ejemplos de
> funcionalidad que necesito alcanzar y que todavia no veo como hacerlo:
>
> - obtener la lista de conexiones creadas por el usuario
> - habilitar / deshabilitar mi herramienta en base a las capas cargadas.
>

Hola Alex,
soy consciente de la complejidad que puedes encontrarte en gvSIG 2.
Por un lado intentamos mantener la separacion de responsabilidades, y por
otro arrastramos mucho codigo de la version 1, en el que no se hacia
tanto incapie en ello. Esto puede liar bastante. Lo primero que deberia
calarnos es que desde una libreria no debemos invocar o depender de
codigo que esta en un plugin. Asi, por ejemplo, si desde nuestra libreria
con la logica tenemos que manipular las capas de una vista tendremos
que hacerle llegar a esta la instancia del mapcontext de la vista, y si
desde nuestra libreria de presentacion queremos hacer algo con la visualizacion
del mapa en la vista le pasaremos la instancia del mapcontrol de esta;
pero nunca intentaremos acceder al objeto vista desde un punto de fuera
de nuestro plugin. A ver... te comento sobre alguna de las cosas que
preguntabas...

-.  Capas que hay cargadas en una vista.

    Voy s suponer que tenemos una herramienta de exportacion de datos
    que se alimenta de los datos de las capas de una vista y los exporta
    a una BBDD postgreSQL. Lo que necesitaria seria un componente que me
    mostrase las capas cargadas en la vista, le permitiese al usuario seleccionar
    las que desee y me devuelba esa lista.

    Si queremos que sea un componente reutilizable, no deberia hacerlo depender
    de la vista, ya que esta esta en un plugin y no en una libreria... pero
    puedo hacerlo depender del MapContext asociado a la vista, que si que es
    un componente de libreria. Podria tener un contructor algo como :

      JLayerSelector createLayerSelector(MapContext mapContext)

    Y o bien podria hacer que mi componente JLayerSelector extendiese de un JList
    si no me importa fijar una dependencia en el API con el componente Jlist, o
    hacer que el API dependiese de JComponent exponiendo solo los metodos que
    me interese y en la implementacion, DefaultJLayerSelector, que ya extienda
    al JList si me interesa o que sea cualquier otra cosa, como por ejemplo
    un JPanel con los componentes que crea oportuno.

    Lo que si que suelo hacer incapie es que ese componente selector de capas,
    no debe tener un boton aceptar o cancelar, ni una etiqueta que diga algo
    asi como "seleccione las capas que desea exportar", se debe limitar
    a seleccionar las capas, para luego usarlo en la ventana/panel que
    creamos oportuno, normalmente desde el nuestro plugin.

    Para acceder a las capas tienes un metodo:

      FLayers layers = mapContext.getLayers();

    Y luego ya puedes ver de recorrer las capas tu mismo o usar el metodo

      accept(LayersVisitor visitor)

    del FLasyers para otener las capas. Yo te recomiendo que uses el metodo
    accept, ya que este se encarga de recorrer las capas de entre los
    distintos grupos de capas que puedan haber en la lista de capas.

    Y la otra cosa que creo que te puede ser util es... ¿ de donde saco
    el MapControl que paso a la creacion de mi componente ?
    Pues en principio, el construir nuestro JLayerSelector se le invocaria
    desde nuestro plugin, en la parte que crea el panel para seleccionar las
    capas. Desde alli podriamos hacer algo como:

      ApplicationManager application = ApplicationLocator.getManager();

      ViewDocument view = (ViewDocument) application.getActiveDocument(ViewDocument.class);
      if( view == null ) {
        return; // No hay vista activa
      }
      JLayerSelector layerSelector = myuimanager.createLayerSelector(view.getMapContext());
      ...

-.  Sobre habilitar / deshabilitar mi herramienta en base a las capas cargadas.

    Bueno, la parte de habilitar o no herramientas en base a capas cargadas, pues
    en principio deberia ser bastante sencillo, luego se puede complicar mas...

    Normalmente las herramientas, en menus y botones de la aplicacion, van
    ligadas a una instancia de clase Extension. Esta tiene un metodo isEnabled,
    que es invocado por el IU cada vez que se precisa actualizar el estado de las
    herramientas y menus. Asi, una primera aproximacion podria ser comprobar
    lo que necesites en ese metodo y devolber si debe o no estar activa tu herramienta.

    Dos o tres consideraciones antes de ver algo de esto...

    - No deberas asumir nunca que la aplicacion se encuentra en un estado
      concreto cuando se invoque a este metodo. No debes nunca hacer asumciones
      del tipo, "pues habra una vista activa", o la vista tiene capas o no cargadas,
      o cosas similares, ya que nunca sabras cuando el sistema invoca a ese metodo
      para ver si ha de activar tu herramienta.

    - No deberas guardar mantener "estado" entre dos invocaciones a este metodo o
      pensar que primero se invocara a este metodo y luego al execute, por ejemplpo,
      asi que me guardo cosas en el isEnabled que luego usare en el execute, ya que
      las condiciones pueden haber cambiado desde que se ejecuto el isEnabled hasta
      que se invoca al execute.

    - El coste de esta operacion debe ser pequeño. Esto es importante ya que se llega
      a invocar muchas veces a este metodo para actualizar el interface de usuario.
      Normalmente, esta consideracion, se lleva bastante mal con lo de no mantener estado,
      asi que hay que ingeniarselas en cada caso para ver como se puede hacer.

    Con esto en mente, veamos como podria ser algo que habilitase nuestra herramienta solo
    si hay capas de BBDD en el TOC.

      public boolean isEnabled() {
        final List<VectorLayer> jdbclayers = new ArrayList<VectorLayer>();
        ApplicationManager application = ApplicationLocator.getManager();
        // Obtenemos la vista activa
        ViewDocument viewDocument = (ViewDocument) application.getActiveDocument(ViewDocument.class);
        if( viewDocument == null ) {
          return false; // Si no hay una vista activa, deshabilitamos la herramienta
        }
        // Obtenemos las capas de la vista
        FLayers layers = viewDocument.getMapContext().getLayers();
        try {
          // Nos recorremos todas las capas de la vista
          layers.accept(new LayersVisitor() {
            public void visit(Object obj) throws VisitCanceledException, BaseException {
              // Do nothing
            }
            public void visit(FLayer layer) throws BaseException {
              if( layer instanceof VectorLayer ) {
                // En el caso de que sea una capa vectorial, le pedimos la fuente de
                // datos y preguntamos por el nombre del proveedor de datos.
                DataStore store = ((VectorLayer) layer).getDataStore();
                if( "JDBC".equalsIgnoreCase(store.getProviderName()) ) {
                  // Si es el proveedor de datos de JDBC, nos guardamos la capa
                  jdbclayers.add((VectorLayer) layer);
                }
              }
            }
          });
        } catch (BaseException e) {
          // Si se produce algun error, informaremos en el log y no activamos la herramienta
          return false;
        }
        if( jdbclayers.isEmpty() ) {
          // Si no habia ninguna capa de BBDD no activamos la herramienta
          return false;
        }
        return true;
      }

    Con algo como esto podemos hacer que nuestra herramienta se active solo cuando hay
    capas vectoriales que son de BBDD. Bueno, si no se entienden cosas preguntais ;)

    Supongo que la parte que te interesara personalizar sera el metodo visit, donde
    comprueba si es una capa vectorial y de que proveedor se trata. Ya me cuentas
    como lo vas resolviendo.

    Escribiendo este codigo de ejemplo he visto un error en el proveedor de postgreSQL, que
    extiende al de JDBC y no sobreescribe el metodo getProviderName, asi que esto no funcionaria
    ahora mismo para detectar capas de postgreSQL, lo corregiremos para el proximo build.

Sobre lo de las conexiones a BBDD, ahora mismo creo que esa parte se heredo de la 1, y no
hay API para acceder a ello. Dejame que le de unas vueltas y ya te cuento algo.

> No busco encontrar una solucion completa, tengo que ponerme a mirar ejemplos
> en el codigo e intentar entender donde aplicar dichas funcionalidades, pero
> si destacar un poco la dificultad para una persona no familiarizada con el
> desarrollo y arquitectura de gvSIG. Si existe dicha documentacion,
> agradeceria si alguien pudiese indicar el link al documento o web.
>

Que yo sepa no hay un documento sobre que cosas tienes disponibles desde que sitios.
En teoria siempre podrias acceder a todo desde cualquierpate, solo que no siempre
es aconsejable hacerlo. Tomo nota y a ver si saco tiempo y escribo algunas lineas
contando un poco al respecto de esto.

> Tambien me gustaria pedir disculpas por los sucesivos posts que he puesto en
> los ultimos dias, entiendo que pueda molestar a la comunidad que recibe los
> emails, especialmente si el problema no es de la aplicacion sino del
> desarrollador.
>

Nadie deberia molestarse por que preguntes en la lista, esta para eso.
De las preguntas de unos siempre hay algo que aprendemos los demas ;)

Espero que te sirba lo que he contado.
Un saludo

Joaquin


> Un saludo y un millon de gracias por la ayuda, nos seguimos leyendo por
> aqui!
>
> Alex
>
> PD: perdona las faltas de ortografia pero es que trabajo con un teclado
> ingles.
>
>
>
>
>
> --
> View this message in context: http://osgeo-org.1560.n6.nabble.com/Undefined-Reference-cuando-intento-usar-PluginServices-tp5006122p5006332.html
> Sent from the gvSIG desarrolladores mailing list archive at Nabble.com.
> _______________________________________________
> gvSIG_desarrolladores mailing list
> gvSIG_desarrolladores en listserv.gva.es
> Para ver histórico de mensajes, editar sus preferencias de usuario o darse de baja en esta lista, acuda a la siguiente dirección: http://listserv.gva.es/cgi-bin/mailman/listinfo/gvsig_desarrolladores
>



Más información sobre la lista de distribución gvSIG_desarrolladores