Creando y gestionando de manera dinámica propiedades de tipo constraint en Alfresco

 

Basándonos en este artículo del blog de Alfresco relativo a propiedades dinámicas en tipos de contenido, hemos desarrollado un sencillo componente para utilizar y gestionar listas dinámicas en uno de nuestros modelos de contenido utilizados en zylk.net.

 

En nuestro caso, tenemos un modelo de contenido para gestionar incidencias o tickets, con un tipo base bug:incidencia, del cual tenemos el siguiente extracto:

 

<type name="bug:incidencia"> 

      <title>Incidencia</title> 
      <parent>cm:folder</parent>
      <properties>
<property name="bug:incidencia_asignar"> 
               <title>Asignar a</title> 
               <type>d:text</type>               
        <constraints>
                 <constraint ref="bug:AsignarIssue" />
               </constraints> 
            </property>
  <property name="bug:incidencia_estado"> 
               <title>Estado</title> 
               <type>d:text</type>             
      <constraints>
                 <constraint ref="bug:EstadosIssue" />
               </constraints> 
            </property>
  <property name="bug:incidencia_prioridad"> 
               <title>Prioridad</title> 
               <type>d:text</type> 
      <constraints>
                 <constraint ref="bug:PrioridadesIssue" />
               </constraints>           
            </property> 
</type>
 

Para las tres propiedades anteriores se utilizan un conjunto de constrains que se definen de manera dinamica a continuación, a partir de una query de lucene sobre el repositorio. Es decir, gestionamos las propiedades en el repositorio (y no en un archivo xml del modelo), y las consumimos mediante querys de lucene.

 

Para asignar incidencia a usuario (person):

 

 <constraint name="bug:AsignarIssue" 
       type="zylk.net.constraints.SearchBasedListConstraint" > 
       <parameter name="query"> 
       <value>TYPE:"{http://www.alfresco.org/model/content/1.0}person"</value> 
       </parameter> 
 </constraint>
 

Para definir los estados de la incidencia (categorías):

 

<constraint name="bug:EstadosIssue" 

 

       type="zylk.net.constraints.SearchBasedListConstraint" > 
      <parameter name="query"> 
      <value>PATH:"/cm:generalclassifiable/cm:Aplicaciones/cm:Bugtracker/cm:Estados//."</value> 
      </parameter> 
 </constraint>
 

Para establecer la prioridad de la incidencia (folders):

 

<constraint name="bug:PrioridadesIssue" 
       type="zylk.net.constraints.SearchBasedListConstraint" > 
       <parameter name="query"> 
       <value>PATH:"/app:company_home/app:dictionary/cm:Aplicaciones/cm:Bugtracker/cm:Prioridades//."</value> 
       </parameter> 
</constraint> 
 

El caso de uso es el siguiente:

 

  • Tenemos un tipo de contenido con una propiedad definida que es variable bug:EstadosIssue y necesita de una administración propia, porque el administrador requiere añadir nuevos valores a esa constraint con cierta frecuencia. Esta problemática se puede gestionar con categorias en Alfresco (pero solo el administrador puede acceder a través de las interfaces de Alfresco Explorer y Share).

  • Tenemos un tipo de contenido con una propiedad definida que es variable bug:PrioridadesIssue y necesita de una administración propia y donde no sólo por los administradores sino un grupo de usuarios va a añadir valores con cierta frecuencia. Esta problemática se puede gestionar con una estructura de carpetas virtual creada por ejemplo en Data Dictionary (con permisos de edicion para el conjunto de usuarios editores)

 

 

La clase que implementará la carga de valores extiende de ListOfValuesConstraint (ver wiki )

 

public class SearchBasedListConstraint extends ListOfValuesConstraint implements Serializable

 

haremos uso del ServiceRegistry para poder llamar a los servicios que necesitamos (SearchService, NodeService...)

 

private static ServiceRegistry registry;
public ServiceRegistry getServiceRegistry()
{
return registry;
}
public void setServiceRegistry(ServiceRegistry registry)
{
SearchBasedListConstraint.registry = registry;
}

tendremos un método que realizará una búsqueda Lucene con una query que pasaremos como parámetro desde el modelo de contenido.

 

protected List<String> getResults()
{
   getServiceRegistry().getAuthenticationService().authenticate("admin", "admin".toCharArray());

   List<String> allowedValues = new ArrayList<String>();
   for (ResultSetRow row : resultSet)
   {
     if(nodeSvc.getType(row.getNodeRef()).equals(ContentModel.TYPE_PERSON)){
     allowedValues.add((String)nodeSvc.getProperty(row.getNodeRef(), ContentModel.PROP_FIRSTNAME) + " "
      + (String)nodeSvc.getProperty(row.getNodeRef(), ContentModel.PROP_LASTNAME));
      }else{
     allowedValues.add((String)nodeSvc.getProperty(row.getNodeRef(), ContentModel.PROP_NAME));
    }
   } 
   if (allowedValues.size() == 0)
    allowedValues.add("");
return allowedValues;
}

 

también es necesario sobreescribir el método getAllowedValues para que cargue los valores obtenidos en la búsqueda:

 

@Override
public List<String> getAllowedValues()
{
List<String> allowedValues = getResults();
super.setAllowedValues(allowedValues);
return allowedValues;
}

y por último, tendremos que tener definido el bean en el contexto:

 

(bug-model-context.xml)
<bean id="SearchBasedListConstraintInitializer" 
class="zylk.net.constraints.SearchBasedListConstraint"> 
<property name="serviceRegistry"> 
<ref bean="ServiceRegistry"/> 
</property> 
</bean>

 

PS: Para desplegar la clase java hemos creado un jar y lo hemos copiado en $ALF_HOME$/tomcat/webapps/alfresco/WEB-INF/lib.

 

 

Ejemplos:

Constraint para usuarios:

 

 

Constraint de categorías:

 

 

Constraint de carpetas:

 

 

00

Más entradas de blog

Añadir comentarios