plantillas ftl + metadatos customizados

cancel
Showing results for 
Search instead for 
Did you mean: 
txakin
Member II

plantillas ftl + metadatos customizados

Hola a todos,

Tengo unas dudas que no sé resolver respecto al tema de los ftl, y espero que me podáis echar un cable.

Me he creado un aspecto "miAspecto" que tiene varias propiedades para poder trabajar con mis propios metadatos, por ejemplo comunidad autónoma, etc…

A la hora de modificar el node_summary_panel.ftl la cosa me funciona bien con mis nuevos metadatos, pero encuentro un problema o una gran duda.

Cuando accedo al metadato de comunidad autónoma, el dato que me muestra siempre es el código, pero yo quiero mostrar la descripción de esa comunidad autónoma….

Para el tema de BBDD me he creado un servicio, con varios métodos, uno de los cuales me devuelve el objeto comunidad autónoma (id, descripcion), a partir del id que se recibe….

Puedo acceder desde ftl a ese método para poder obtener la propiedad "miAspecto.comunidadautonoma.descripcion" o algo así, o debería guardar otra propiedad en mi modelo que fuera la descripción de la comunidad autonoma?

un saludo y espero me ayuden.
9 Replies
venzia
Senior Member

Re: plantillas ftl + metadatos customizados

Hola txakin, a ver si te podemos ayudar. Primero necesito que me aclares ciertos aspectos :
Cuando accedo al metadato de comunidad autónoma, el dato que me muestra siempre es el código, pero yo quiero mostrar la descripción de esa comunidad autónoma….
¿Como insertas ese metadato? .. ¿de forma manual metes el codigo? .. ¿o traes los registros de la bd y luego solo guardar el codigo en la propiedad del aspecto?

Para el tema de BBDD me he creado un servicio, con varios métodos, uno de los cuales me devuelve el objeto comunidad autónoma (id, descripcion), a partir del id que se recibe….
¿A que tipo de servicio te refieres? .. ¿lo tienes integrado con Alfresco? ..

Puedo acceder desde ftl a ese método para poder obtener la propiedad "miAspecto.comunidadautonoma.descripcion" o algo así
Esto me temo que es técnicamente bastante complicado ya que deberías implementar toda la lógica necesaria. Si esos metodos estuvieran accesibles desde el API Javascript de Alfresco si que podrías pero me temo que no es así. No se tu nivel en java pero a mi me esta dando dolor de cabeza solo de pensarlo jeje :?
o debería guardar otra propiedad en mi modelo que fuera la descripción de la comunidad autonoma?
Esto es una opción, aunque de cara al cliente web no se como afectaría a los usuarios el que tengan que introducir manualmente tanto el id como el nombre de la comunidad.
Por ultimo una pregunta :
¿Por que no guardas unicamente la descripción de la comunidad autónoma? .. incluso te puedes crear un "Constraint" que recoja todas las comunidades y lo asignas a la propiedad del aspecto http://wiki.alfresco.com/wiki/Constraints.
No se, tal vez cuando me expliques lo anterior entienda mejor tu problema.
Saludos,
pjcaracuel_2349
Active Member II

Re: plantillas ftl + metadatos customizados

Buenas Javier,

¿Por que no guardas unicamente la descripción de la comunidad autónoma? .. incluso te puedes crear un "Constraint" que recoja todas las comunidades y lo asignas a la propiedad del aspecto http://wiki.alfresco.com/wiki/Constraints.
No se, tal vez cuando me expliques lo anterior entienda mejor tu problema.

Entiendo que el uso de codigos lo hace para mantener la integridad con los datos guardados en bbdd, esto es si tienes n documentos con un valor ya dado en el campo Comunidad Autonoma, si se modifica la descripcion (caso poco probable para este tipo de dato, pero no imposible  :lol: ) en bbdd, habría que renombrar el valor de ese metadato en  todos los documentos que tengan dicho valor. Por ello si trabajas con codigos (clave primaria), nunca tendras ese problema. A modo de ejemplo, Documentum si gestiona asi los valores leidos en bbdd.

Saludos
venzia
Senior Member

Re: plantillas ftl + metadatos customizados

Hola Pedro, lo que comentas es correcto (y lógico). Ahora bien, no tengo muy claro el caso concreto de txakin.
Entiendo que lo que necesita es llamar desde javascript a una función que devuelve la descripcion de la comunidad según un id. Para esto he encontrado un post que al parecer explica como hacerlo http://forums.alfresco.com/en/viewtopic.php?f=36&t=12336
A ver si es esto lo que busca.
Saludos
ajv
Member II

Re: plantillas ftl + metadatos customizados

Hola amigos!!

A ver, leyendo unas cuantas veces el post de txakin yo entiendo lo siguiente:
- Se ha creado un aspecto personalizado en el que incluirá los códigos de las comunidades autónomas.
- La información de las comunidades autónomas residen en una tabla, que mediante código java la hace accesible a la aplicación (alguna vez se ha explicado cómo alimentar listas de valores desde tablas de base de datos).
- Interesa disponer de algún método en FreeMarker para llamarlo desde sus plantillas pero, lógicamente, el API que proporciona Alfresco no incluye dicho método.

Bueno, pues esto creo que tiene una solución…y no muy complicada.
En su día tuve que hacer algo similar y conseguí llamar a un método mío propio desde plantillas ftl  :mrgreen:
Ahora os explico cómo:

1.- Definir el método que queremos ejecutar en la plantilla.
Para ello, tenemos que crear una clase java, pero que ha de cumplir una serie de condiciones:
- Heredar de la clase org.alfresco.repo.template.BaseTemplateProcessorExtension
- Implementar la interfaz freemarker.template.TemplateMethodModelEx
- El método que queremos que se ejecute en la plantilla, debe tener esta apariencia:
public Object exec(List args) throws TemplateModelException { … }
Como veis, admite una lista de parámetros por si interesase pasarle y hacer cosas en función de ellos.
También retorna un objeto, que es lo que "imprimirá" la plantilla.
Básicamente, tu método debería acceder a la BD y consultar la comunidad autonoma del codigo X, código pasado por parámetro en la plantilla.

2.- Registrar un bean con la clase anteriormente implementada.
El bean tiene que tener una apariencia similar a esta:
<!– Nuevo método para emplear en las plantillas –>
    <bean id="miTemplateExtension" parent="baseTemplateImplementation" class="miPaquete.miClase">
        <property name="extensionName">
            <value>misComunidades</value>
        </property>
    </bean>
Es importante definir el atributo parent con el valor baseTemplateImplementation para que alfresco lo adquiera como una extensión al APIs de plantillas.
La propiedad extensionName es el nombre a través del cual podrás acceder al método de la clase (al exec) a través de la plantilla.

3.- Utilizar el nuevo método en una plantilla FreeMarker.
Una vez hecho todo lo anteior, podremos emplear el metodo en nuestras plantillas:
${misComunidades('IB')}
Esto, por ejemplo, consultaría en la Base de datos qué Comunidad Autónoma es la que tiene por código IB y devolvería "Illes Balears" (por ejemplo).


Bueno, pues básicamente eso es todo.
Espero que efectivamente responda a la duda de txakin  Smiley Very Happy
Si no, pues bueno, quizás a alguien le interese…

Saludos!!
venzia
Senior Member

Re: plantillas ftl + metadatos customizados

oleee Adri!! .. tomo nota  :wink: .. y supongo que txakin también .. que a gusto se te ve tocando temas java!!
Saludos
txakin
Member II

Re: plantillas ftl + metadatos customizados

Perdonar por no haber respondido antes…es que he andado super liado tocando otras cosas….

Voy a contar como he solucionado mi problema y explicar un poco mi caso…que a más de uno le podrá servir en un futuro.

                                PROCESO DE PREVIEW DE ESPACIOS Y DOCUMENTOS

Pequeña descripción:

En mi aplicación, me he creado 2 aspectos propios, uno para los espacios (Carpeta) y otro para los documentos(Documentos), todo esto para poder guardar metadatos propios que tendrá mi aplicación.
La idea de usar los ftl, viene porque quiero que cuando el usuario clickee en el icono "i", tanto de los espacios como de los documentos, se ejecute mi nuevo ftl, con mis nuevos cambios.

  • Si el usuario clickea en un espacio…le mostrará los metadatos especificos del espacio, como podrán ser comunidad autónoma, año, etc….Como funciona ahora, pero sólo mostrando mis nuevos metadatos, siempre y cuando el espacio en cuestión tenga el aspecto Carpeta

  • Si el usuario clickea en un documento…se le mostrará, además de los metadatos del documento, un pantallazo de primera página del documento, siempre y cuando el documento en cuestión tenga el aspecto Documento.
Como bien habéis imaginado, muchos metadatos sólo guardan el valor del id, como por ejemplo comunidad autónoma, y para ellos tengo una tabla de comunidades autónomas…a la cual debemos acceder a través de una clase java, que nos devuelva o bien una lista o bien el objeto comunidad autónoma a partir de un id pasado como parámetro….Así con todas nuestras tablas y nuestro id.

Para acceder a la base de datos y generar los métodos que obtienen listas u objetos a partir de un id….es puro java…y eso supongo que mucha gente sabrá hacerlo….o bien por jdbc, o con hibernate, o con ibatis….lo que decida cada uno.

Pasos a seguir:

Comento los cambios que se han hecho…para poder generar todo esto.
!!!!!ATENCION!!!!!! En todos los cambios, siempre se intenta no tocar el código fuente original de Alfresco.

  • 1.- Se crean 2 aspectos. (sobre esto ya existe un manual redactado por ajv, si no me equivoco)
  •          Aspecto Carpeta : aqui se albergarán los nuevos espacios que se generen
             Aspecto Documento : aqui se albergarán los nuevos documentos.

             Para ello se ha creado un BilbomaticaModel.xml :
    <?xml version="1.0" encoding="UTF-8"?>

    <model name="bilbomatica:bilbomaticaModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

       <!– Optional meta-data about the model –>  
       <description>Prueba Bilbomática</description>
       <author>Jon Santos - Bilbomática S.A.</author>
       <version>1.0</version>

       <imports>
          <!– Import Alfresco Dictionary Definitions –>
          <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
          <!– Import Alfresco Content Domain Model Definitions –>
          <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
       </imports>

       <!– Introduction of new namespaces defined by this model –>
       <!– NOTE: The following namespace custom.model should be changed to reflect your own namespace –>
       <namespaces>
          <namespace uri="www.bilbomatica.es" prefix="bilbomatica"/>
       </namespaces>
       
       <aspects>
           <aspect name="bilbomatica:Carpeta">
                <title>Carpetas de Bilbomática</title>
                <parent>cm:folder</parent>         
                <properties>

                    <property name="bilbomatica:anio">
                        <title>Año de Creación</title>
                        <type>d:text</type>
       </property>
                
       <!– Hay tabla en BBDD –>
       <property name="bilbomatica:comautonoma">
           <title>Comunidad Autónoma</title>
           <type>d:text</type>               
       </property>
                   
                    <!– Hay tabla en BBDD –>            
                    <property name="bilbomatica:tipodocu">
           <title>Tipo de Documentación</title>
           <type>d:text</type>
       </property>
                
       <!– Materia –>
       <property name="bilbomatica:materia">
           <title>Materia</title>
           <type>d:text</type>
       </property>
          
                    <!– Otras propiedades que se deseen –>
          
               </properties>
          </aspect>

          <aspect name="bilbomaticaSmiley Very Happyocumento">
              <title>Documentos de Bilbomática</title>
              <parent>cm:folder</parent>         
              <properties>
                  <property name="bilbomaticaSmiley Surprisedrden">
                      <title>Orden de Documento</title>
         <type>d:text</type>
                  </property>
       
                  <!– Hay tabla en BBDD –>
                  <property name="bilbomaticaSmiley Surprisedrigendocumento">
                      <title>Origen del documento</title>
                      <type>d:text</type>
                  </property>
             
                  <property name="bilbomatica:fecha">
                      <title>Fecha</title>
         <type>d:text</type>
                  </property>         
                 
                  <!– Otras propiedades que se deseen –>
                      
              </properties>
          </aspect>
      </aspects>
    </model>

    Para poder acceder a todos las propiedades de los aspectos nuevos, se ha generado una clase java, para albergar todos los QName necesarios (supongo que existen otros manuales explicando lo que es un QName)

    package bilbomatica.modelos;

    import org.alfresco.service.namespace.QName;

    public interface BilbomaticaModel {
       
         //Carpetas de Bilbomática
         QName aspectCarpeta =
       QName.createQName("{www.bilbomatica.es}Carpeta");
          
         QName propCarpetaAnio =
                    QName.createQName("{www.bilbomatica.es}anio");
          
         QName propCarpetaComunidadAutonoma =
                    QName.createQName("{www.bilbomatica.es}comautonoma");

         QName propCarpetaTipoDocu =
                    QName.createQName("{www.bilbomatica.es}tipodocu");
          
         QName propTraspMateria =
       QName.createQName("{www.bilbomatica.es}materia");
          
         //Documentos de Bilbomática
         QName aspectDocTraspaso =
       QName.createQName("{www.bilbomatica.es}Documento");
          
         QName propDocumentoOrden =
       QName.createQName("{www.bilbomatica.es}orden");
          
         QName propDocumentoOrigen =
       QName.createQName("{www.bilbomatica.es}origendocumento");
          
         QName propDocumentoFecha =
       QName.createQName("{www.bilbomatica.es}fecha");
    }
        
  • 2.- Cuando el usuario clickea el icono "i", esto ha provocado tener que modificar el browse.jsp…..
  •          Como una de las políticas de Alfresco es no modificar el código fuente orginal se ha decido sobreescribir la navegación
             de dicho  browse….desde el web-client-config-custom.xml

    <config>
             <navigation>
                 <override from-view-id="/jsp/browse/browse.jsp" to-view-id="/jsp/extension/browse.jsp" />
                 <override from-outcome="browse" to-view-id="/jsp/extension/browse.jsp" />
                 <override from-outcome="cancel" to-view-id="/jsp/extension/browse.jsp"/>
                 <override from-outcome="finish" to-view-id="/jsp/extension/browse.jsp"/>
                 <override from-outcome="success" to-view-id="/jsp/extension/browse.jsp"/>
             </navigation>
         </config>

    Lo que se ha hecho…es una copia exacta del browse.jsp….y se han modifcado algunas cosas para que se ejecute el preview que he desarrollado.

    En el browse.jsp original…aparece unas cuantas veces la siguiente instrucción que si no recuerdo mal, llama a una clase llamada NodeInfoBean.java, que obtiene esa previsualización orginal.

    <r:nodeInfo id="col2-info" value="#{r.id}">
        <h:graphicImage id="col2-img" url="/images/icons/popup.gif" styleClass="popupImage" width="16" height="16" />
    </r:nodeInfo>

    En el desarrollo que se ha llevado a cabo, esta parte se ha retocado :

    <r:nodeInfo id="col1-info" value="#{r.id}">
    <f:verbatim>
      <script>
          var AlfNodeInfoMgr = new Alfresco.PanelManager("PopupNodeInfoBean.sendNodeInfo", "noderef");
      </script>
      <span onclick="AlfNodeInfoMgr.toggle('</f:verbatim><hSmiley SurprisedutputText value="#{r.nodeRef}" /><f:verbatim>',this);">
    </f:verbatim>
        <h:graphicImage id="col1-img" url="/images/icons/popup.gif" styleClass="popupImage" width="16" height="16" />
      </span>
    </r:nodeInfo>

    Como podréis observar, estas instrucciones, van a llamar a la clase PopupNodeInfoBean, que ha sido generada para poder redefinir lo original.

    Aquí está la clase nueva :

    package org.alfresco.web.bean.ajax;

    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Serializable;
    import java.net.ConnectException;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;

    import javax.faces.context.FacesContext;
    import javax.faces.context.ResponseWriter;
    import javax.servlet.http.HttpServletRequest;

    import magick.ImageInfo;
    import magick.MagickException;
    import magick.MagickImage;
    import net.sf.jooreports.converter.DocumentFamily;
    import net.sf.jooreports.converter.DocumentFormat;
    import net.sf.jooreports.openoffice.connection.OpenOfficeConnection;
    import net.sf.jooreports.openoffice.connection.SocketOpenOfficeConnection;
    import net.sf.jooreports.openoffice.converter.OpenOfficeDocumentConverter;

    import org.alfresco.model.ContentModel;
    import org.alfresco.repo.content.transform.TransformerInfoException;
    import org.alfresco.repo.template.CropContentMethod;
    import org.alfresco.repo.template.TemplateNode;
    import org.alfresco.service.cmr.repository.ContentIOException;
    import org.alfresco.service.cmr.repository.ContentReader;
    import org.alfresco.service.cmr.repository.ContentService;
    import org.alfresco.service.cmr.repository.NodeRef;
    import org.alfresco.service.cmr.repository.NodeService;
    import org.alfresco.service.cmr.repository.StoreRef;
    import org.alfresco.service.cmr.repository.TemplateException;
    import org.alfresco.service.cmr.repository.TemplateImageResolver;
    import org.alfresco.service.cmr.search.ResultSet;
    import org.alfresco.service.cmr.search.SearchParameters;
    import org.alfresco.service.cmr.search.SearchService;
    import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
    import org.alfresco.web.bean.repository.Repository;
    import org.apache.commons.lang.StringUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    import bilbomatica.beans.ServiceFactoryBeanImpl;
    import bilbomatica.dto.ComunidadAutonoma;
    import bilbomatica.dto.OrigenDocumento;
    import bilbomatica.TipoDocumento;
    import bilbomatica.BilbomaticaModel;

    public class PopupNodeInfoBean extends NodeInfoBean implements Serializable {

       private static final long serialVersionUID = 6270388697125863150L;
       private ContentService contentService;
       private NodeService nodeService;
       private ServiceFactoryBeanImpl serviceFactory;
       private TemplateImageResolver imageResolver;
       
       public static final String MIME_TYPE_PDF = "application/pdf";
       public static final String MIME_TYPE_MSWORD = "application/msword";
       public static final String MIME_TYPE_MSEXCEL = "application/msword";

       private static final Log logger = LogFactory.getLog(PopupNodeInfoBean.class);
       
       public PopupNodeInfoBean() {
          super();
       }
       
       public void sendNodeInfo() throws IOException {
           FacesContext context = FacesContext.getCurrentInstance();
           ResponseWriter out = context.getResponseWriter();

           Map requestMap = context.getExternalContext().getRequestParameterMap();
           String strNodeRef = (String)requestMap.get("noderef");
           String strTemplate = (String)requestMap.get("template");
           if ((strTemplate == null) || (strTemplate.length() == 0))
           {
             strTemplate = "node_summary_panel.ftl";
           }

           NodeRef nodeRef = null;
           if ((strNodeRef != null) && (strNodeRef.length() != 0))
           {
             nodeRef = new NodeRef(strNodeRef);
             if (!(getNodeService().exists(nodeRef)))
             {
               out.write("<span class='errorMessage'>Node could not be found in the repository!</span>");
               return;
             }
           }
           try
           {
             Repository.getServiceRegistry(context).getTemplateService().processTemplate
                                ("/alfresco/templates/client/" + strTemplate, getModel(nodeRef, requestMap), out);
           }

           catch (TemplateException ex)
           {
             logger.error(ex);
             Throwable cause = ex.getCause();
             do { if (cause == null)
                 break; //label240;
               logger.error(cause);
               cause = cause.getCause(); }
             while ((cause == null) || (!(cause instanceof TransformerInfoException)));

             out.write("<tr><td colspan=\"2\"><span class='errorMessage'>" + cause.getMessage() + "</span></td></tr>");
             return;

             //label240: throw ex;
           }
          


    /**
    Esto es lo que se ha modificado para que se genere el pantallazo de la primera página de los documentos.
           
      Este proceso, hace varias cosas :
                 
    • Si el documento es del formato PDF, sólo genera el pantallazo de la primera página (ImageMagick)
    •            
    • Si el documento es del formato XLS o DOC, primero se convierte en formato PDF (OpenOffice) y luego se genera
    •                 el pantallazo de la primera página (ImageMagick)
           
    Para todo esto se ha instaladon :
    • OpenOffice para la conversión de documentos de varios formatos.

    • ImageMagick y GhostScript para la generación de los pantallazos
    **/


    //super.sendNodeInfo();
    ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
    if (contentReader != null) {
       InputStream is = contentReader.getContentInputStream();
             
       HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
       OpenOfficeConnection connection = null;
       ByteArrayOutputStream baos = null;
       FileOutputStream fos = null;
       try {
           // TODO: Crear un servicio que se conecte a OpenOffice al arrancar el Tomcat
           // Connect to an OpenOffice.org instance running on port 8100
           connection = new SocketOpenOfficeConnection(8100);
           connection.connect();
                
           String mimeType = contentReader.getMimetype();
           if (MIME_TYPE_PDF.equals(mimeType)) {
                // No hace falta hacer la conversion a PDF
                baos = new ByteArrayOutputStream();
               // Leer InputStream y pasarlo a ByteArrayOutputStream
               byte[] buf = new byte[1024];
               int numRead = 0;
               while ((numRead = is.read(buf))>=0) {
       baos.write(buf, 0, numRead);
               }
            } else if (MIME_TYPE_MSWORD.equals(mimeType)) {
       // Convert incoming DOC document to outcoming PDF document
       baos = new ByteArrayOutputStream();
       OpenOfficeDocumentConverter converter = new OpenOfficeDocumentConverter(connection);
       final DocumentFormat outputFormat =
                         new DocumentFormat("Portable Document Format", "application/pdf", "pdf");
                    outputFormat.setExportFilter(DocumentFamily.PRESENTATION, "impress_pdf_Export");
       outputFormat.setExportFilter(DocumentFamily.SPREADSHEET, "calc_pdf_Export");
       outputFormat.setExportFilter(DocumentFamily.TEXT, "writer_pdf_Export");
       final DocumentFormat inputFormat =
                        new DocumentFormat("Microsoft Word", DocumentFamily.TEXT, "application/msword", "doc");
       inputFormat.setExportFilter(DocumentFamily.TEXT, "MS Word 97");
       converter.convert(is, inputFormat, baos, outputFormat);
              } else if (MIME_TYPE_MSEXCEL.equals(mimeType)) {
       // Convert incoming XLS document to outcoming PDF document
       baos = new ByteArrayOutputStream();
       OpenOfficeDocumentConverter converter = new OpenOfficeDocumentConverter(connection);
       final DocumentFormat outputFormat =
                            new DocumentFormat("Portable Document Format", "application/pdf", "pdf");
       outputFormat.setExportFilter(DocumentFamily.PRESENTATION, "impress_pdf_Export");
       outputFormat.setExportFilter(DocumentFamily.SPREADSHEET, "calc_pdf_Export");
       outputFormat.setExportFilter(DocumentFamily.TEXT, "writer_pdf_Export");
       final DocumentFormat inputFormat =
                        new DocumentFormat("Microsoft Excel", DocumentFamily.SPREADSHEET, "application/vnd.ms-excel", "xls");
       inputFormat.setExportFilter(DocumentFamily.SPREADSHEET, "MS Excel 97");
       converter.convert(is, inputFormat, baos, outputFormat);
              } else return;
       // Create the temporary image file
       String imgName = "img".concat(""+System.currentTimeMillis()).concat(".jpg");
       String[] ar = StringUtils.split(imgName, ".");
       String pathDir = request.getSession(false).getServletContext().getRealPath("");
       File tempDir = new File(pathDir.concat("/images/temp"));
       if (!tempDir.exists()) tempDir.mkdirs();
       File tempFile = File.createTempFile(ar[0], ".".concat(ar[1]), tempDir);
       fos = new FileOutputStream(tempFile);
                
       // Extract the first page of the PDF document and create a PDF file on the fly
       MagickImage image = new MagickImage(new ImageInfo(), baos.toByteArray());
       MagickImage[] pages = image.breakFrames();
       MagickImage smaller = pages[0].scaleImage(300, 450);
       smaller.setMagick("JPEG");
       fos.write(smaller.imageToBlob(new ImageInfo()));
       fos.flush();
       image.destroyImages();
       smaller.destroyImages();
       
       // Generate HTML code
       StringBuilder html = new StringBuilder("<div class=\"summaryPopupPanel\"><table cellpadding=\"3\" cellspacing=\"0
                                                                             \"><tbody><tr><td class=\"mainSubTitle\">");
                    html.append("<table width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td
                                         class=\"mainSubTitle\">Preview</td></tr></tbody></table>");
       html.append("</td></tr><tr><td>");
       html.append("<img src='");
       html.append(request.getContextPath());
       html.append("/images/temp/");
       html.append(tempFile.getName());
       html.append("'>");
       html.append("</td></tr></tbody></table></div>");
       out.write(html.toString());
       tempFile.deleteOnExit();
       // TODO: crear un servicio que elimine todas las imagenes temporales con una cierta antiguedad
                 } catch (MagickException me) {
       System.out.println("No se ha podido conectar con ImageMagick");
                 } catch (ConnectException ce) {
       System.out.println("No se ha podido conectar con OpenOffice");
                 } finally {
       // close the connection and the streams
       if (connection!=null) connection.disconnect();
       if (baos!=null) baos.close();
       if (fos!=null) fos.close();
                 }
              }
           }




    /**
    Además también se ha redefinido el método getModel, para poder obtener los datos que deseemos mostrar.
    En este método se obtiene el objeto "node", que almacenará todos los metadatos, tanto para Carpetas como para Documentos.
    Para el caso de los metadatos que acceden a BBDD se generan nuevas variables en el objeto model, que es el que se leerá en el ftl.
    **/



    private Map<String, Object> getModel(NodeRef nodeRef, Map<String, String> requestMap) throws ContentIOException
          {
              FacesContext context = FacesContext.getCurrentInstance();
              Map model = new HashMap(8, 1F);
       
              model.put("date", new Date());
              model.put("cropContent", new CropContentMethod());
              model.put("url", new BaseTemplateContentServlet.URLHelper(context.getExternalContext().getRequestContextPath()));
              if (nodeRef != null){
                 model.put("node", new TemplateNode(nodeRef, Repository.getServiceRegistry(context), this.imageResolver));
              }
       
             //Si el nodo a tratar tiene aspecto de Carpeta de Bilbomática
             if (getNodeService().hasAspect(nodeRef, BilbomaticaModel.aspectCarpeta)) {
                //Se obtiene la comunidad autónoma
                String comunidadAutonomaId =
                      (String)getNodeService().getProperty(nodeRef, BilbomaticaModel.propCarpetaComunidadAutonoma);

                //Se accede al método que obtiene datos de BBDD. En este caso se obtiene el objeto
                //ComunidadAutonoma a partir del id
                ComunidadAutonoma comunidadAutonoma = (ComunidadAutonoma)
                    serviceFactory.getDatabaseSectalfService().getComunidadAutonoma(comunidadAutonomaId);

                //Se crea una nueva variable en el objeto model, que es el que se lee en el ftl.
                model.put("comunidadautonoma", comunidadAutonoma);
              }      

             //Si el nodo a tratar tiene aspecto de Documento de Bilbomática
             if (getNodeService().hasAspect(nodeRef, BilbomaticaModel.aspectDocumento)) {

                 //Se obtiene el origen del documento
                 String origenDocTraspId = (String)getNodeService().getProperty(nodeRef, BilbomaticaModel.propTraspOrigenDoc);
                 if (origenDocTraspId != null) {
       OrigenDocTrasp origen =
                        serviceFactory.getDatabaseSectalfService().getOrigenDocTrasp(origenDocTraspId);

                    //Se crea una nueva variable en el objeto model, que es el que se lee en el ftl.
       model.put("origendocumento", origen);
                 }
              }
             
              Map args = new HashMap(4, 1F);
              for (Iterator i$ = requestMap.keySet().iterator(); i$.hasNext(); ) { String name = (String)i$.next();
       args.put(name, requestMap.get(name));
              }
              model.put("args", args);
              return model;
           }

       public ContentService getContentService() {
          return contentService;
       }

       public void setContentService(ContentService contentService) {
          this.contentService = contentService;
       }

       public NodeService getNodeService() {
          if (this.nodeService == null)
           {
             this.nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
           }
           return this.nodeService;
       }

       public void setNodeService(NodeService nodeService) {
          this.nodeService = nodeService;
       }

       public ServiceFactoryBeanImpl getServiceFactory() {
          return serviceFactory;
       }

       public void setServiceFactory(ServiceFactoryBeanImpl serviceFactory) {
          this.serviceFactory = serviceFactory;
       }
    }

  • 3.- Por último se ha modificado el node-summary-panel.ftl para que muestre loa datos deseados en este caso.
  • Este caso es un poco particular, ya que no hemos sobreescrito el ftl, sino que se machaca el original.
    Supongo que modificando parte del código de la clase anterior se puede sobreescribir, y así mantener el original.

    <#assign isImage=node.isDocument && (node.mimetype = "image/gif" || node.mimetype = "image/jpeg" || node.mimetype = "image/png")>
    <#assign isVideo=node.isDocument && node.mimetype?starts_with("video/")>
    <div class="summaryPopupPanel">
       <table cellpadding='3' cellspacing='0'>
          <tr>
             <td colspan='2' class='mainSubTitle'>
               <table cellspacing='0' cellpadding='0' width='100%' style='cursor:move' id='dragable'>
       <tr>
          <td class='mainSubTitle'>${node.name?html}</td>
          <#if node.isDocument || node.isLinkToDocument>
             <#assign navurl="/navigate/showDocDetails/">
          <#else>
              <#assign navurl="/navigate/showSpaceDetails/">
          </#if>
          <#assign navurl=navurl + node.nodeRef.storeRef.protocol + '/' + node.nodeRef.storeRef.identifier + '/' +
                                                node.nodeRef.id>
          <td width=24>
                           <center>
                              <a href='${url.context}${navurl}'><img src='${url.context}/images/icons/View_details.gif'
                                   style='cursorSmiley Tongueointer' width=12 height=16 border=0 title="Details" alt="Details"></a>
                           </center>
                       </td>
          <td width=14 align=right><img src='${url.context}/images/icons/close_panel.gif' onclick="<#if isVideo>if
                           (document.all) document.getElementById('${node.id}_player').controls.stop();</#if>AlfNodeInfoMgr.close
                           ('${node.nodeRef}');" style='cursorSmiley Tongueointer' width=14 height=14 border=0 title="Close" alt="Close"></td>
       </tr>
               </table>
            </td>
          </tr>
          <tr>
              <td valign='middle' align='center'>
              <#if isImage>
                 <a href="${url.context}${node.url}" target="new"><img src="${url.context}${node.url}" width=120 border=0></a>
              <#elseif isVideo>
                  <object width="320" height="240" border="0" id="${node.id}_player"
                             classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6">
           <param name="URL" value="${url.context}${node.url}" />
           <param name="AutoStart" value="true" />
           <param name="AutoSize" value="true" />
           <embed type="application/x-mplayer2"
                              pluginspage="http://microsoft.com/windows/mediaplayer/en/download/" src="${url.context}${node.url}?
                              ticket=${session.ticket}" showcontrols="1" showdisplay="0" showstatusbar="0" autosize="1" autoplay="1"
                              autoStart="1" height="240" width="320"></embed>
                   </object>
                <#else>
                   <table cellspacing=0 cellpadding=0 border=0>
          <tr>
             <td>
                <div style="border: thin solid #cccccc; padding:4px">
          <a href="${url.context}${node.url}" <#if node.isDocument>target="new"</#if>><img src="${url.context}
                                                  ${node.icon32}" width=32 height=32 border=0></a>
                             </div>
              </td>
              <td><img src="${url.context}/images/parts/rightSideShadow42.gif" width=6 height=42></td>
           </tr>
           <tr>
               <td colspan=2><img src="${url.context}/images/parts/bottomShadow42.gif" width=48 height=5></td>
                         </tr>
       </table>
               </#if>
             </td>

             <td valign='top'>
                <table cellpadding='2' cellspacing='0'>

                      
    <#– Esto es lo nuevo que se ha tocado en este ftl,<lo demás es lo que existía originalmente –>
                       <#if hasAspect(node, "bilbomatica:Carpeta")==1>
                           <#–
                 Cuando el nodo tiene el aspecto de Carpeta de Bilbomática, se obtienen los metadatos.
                              Año, Comunidad Autónoma, Tipo de Documentación, y materia.
                           –>

                           <#if node.properties["bilbomatica:anio"]?exists>                                           
                               <tr><td> Año:</td><td>${node.properties["bilbomatica:anio"]?html}</td></tr>
               </#if>

                           <#–
                 La variable comunidadautonoma se ha creado en la clase anterior y su valor es un objeto
                              ComunidadAutonoma (id, name)-
                           –>
                           <#if comunidadautonoma?exists>
                 <tr><td> Comunidad Autónoma:</td><td>${comunidadautonoma.name?html}</td></tr>
              </#if>

                          <#–
                              La variable tipodocu está almacenada en el objeto node                      
                           –>
                           <#if node.properties["bilbomatica:tipodocu"]?exists>                                           
                               <tr><td> Tipo Documentación:</td><td>${node.properties["bilbomaticaSmiley Tongueleno"]?html}</td></tr>
               </#if>               
                              <tr><td> Materia:</td><td>${node.properties["bilbomatica:materia"]?html}</td></tr>
                       <#else>
              <#if hasAspect(node, "bilbomaticaSmiley Very Happyocumento")==1>
                               <#–
                      Cuando el nodo tiene el aspecto de Documento de Bilbomática, se obtienen los metadatos.
                                   Fecha, Origen del Documento y Tamaño
                  –>
                  <#if node.properties["bilbomatica:fecha"]?exists>
                 <tr><td> Fecha:</td><td>${node.properties["bilbomatica:fecha"]?html}</td></tr>
                  </#if>                        
                  <#if origendocumento?exists>
                     <tr><td> Origen del Documento:</td><td>${origendocumento.name?html}</td></tr>
                  <#else>
                     <tr><td> Origen del Documento:</td><td>Sin valor</td></tr>
                  </#if>
                 
    <#if node.isDocument>
          <tr><td> Tamaño:</td><td>${(node.size / 1000)?string("0.##")} KB</td></tr>
                  </#if>
              <#else>


                 <#if node.properties.title?exists>              
          <tr><td> Title:</td><td>${node.properties.title?html}</td></tr>
                 </#if>
                         <#if node.properties.description?exists>
                            <tr><td> Description:</td><td>${node.properties.description?html}</td></tr>
                         </#if>
                         <tr><td> Created:</td><td>${node.properties.created?datetime}</td></tr>
                         <tr><td> Creator:</td><td>${node.properties.creator}</td></tr>
                         <tr><td> Modified:</td><td>${node.properties.modified?datetime}</td></tr>
                         <tr><td> Modifier:</td><td>${node.properties.modifier}</td></tr>
                         <#if node.properties.owner?exists>
                            <tr><td> Owner:</td><td>${node.properties.owner}</td></tr>
                         </#if>
                         <#if node.properties.author?exists>
                            <tr><td> Author:</td><td>${node.properties.author?html}</td></tr>
                         </#if>
                         <#if node.isDocument>
                            <tr><td> Size:</td><td>${(node.size / 1000)?string("0.##")} KB</td></tr>
                         </#if>
                   </#if>
                </#if>              
                </table>
             </td>
          </tr>
       </table>
    </div>
Bueno….espero que os sirva de ayuda todo esto que he posteado…
Espero que no se me haya olvidado nada…y ya sabeis….si hay alguna duda….hacermela llegar.

He obviado algunas clases…porque entiendo que ya existe información suficiente para poder entender todo esto que he redactado.

Un abrazo y gracias por todo.
ajv
Member II

Re: plantillas ftl + metadatos customizados

Hola txakin,

Muchas gracias por compartir con todos nosotros tu avances!
Hay dos cosas que no entiendo muy bien:
- Según el modelo, tus "documentos" heredan de cm:folder por lo que realmente son espacios, no?
- Supongo que la idea de este montaje es sustituir los espacios y contenidos que por defecto proporciona alfresco, para poder personalizarlos a tu gusto…Las acciones de crear espacio, crear contenido, etc. ¿crean espacios de los tuyos o de los genéricos de Alfresco (cm:folder)?

Por cierto, lo de pasar directamente tu objeto ComunidadAutonoma también resuelve perfectamente el problema y con menos complicaciones.
Un saludo y gracias de nuevo.

Hasta pronto!
txakin
Member II

Re: plantillas ftl + metadatos customizados

Perdonar el otro día con el copy paste…se copió algo mal….

El padre del aspecto Documento es de tipo cm:content

En cuanto a las creaciones de Carpetas y Documentos, he desarrollado mis propios wizard para que creen los mios propios.
Para ello siempre uso la instrucción :

getNodeService().addAspect(nodeRef, BilbomaticaModel.QNameAspecto, propiedades);

donde nodeRef : nodo que se está creando.
QNameAspecto : es el QName para el aspecto que esté tratando (Carpeta o Documento)
propiedades : es un Map<QName, Serializable> que contendrá todas las propiedades de mi aspecto.

Espero les sirva de ayuda todo esto…

Se aceptan valoraciones.  Smiley Very Happy
venzia
Senior Member

Re: plantillas ftl + metadatos customizados

Añadir que actualmente existe Alfresco MetaDBConnector (http://addons.alfresco.com/addons/alfresco-metadbconnector-component) un componente, desarrollado y liberado por nuestra empresa, que puede ayudar mucho en tareas de este tipo, sin necesidad de desarrollar nada (todo a través de ficheros de configuración, o mejor dicho, un único fichero ;D). Probadlo y veréis la potencia y simplicidad del mismo.
Espero que sea de utilidad para usuarios que lleguen a este post buscando soluciones similares.

Saludos!