/ hybris

hybris - impex translator

El Translator es un componente que ayuda a entender la información que se va a importar en un impex durante el procesamiento de cada línea, encuentra aquí ejemplos básicos para que puedas comenzar a sacarles provecho

Primero, revisaremos la clase AbstractValueTranslator, la cual ese el componente más básico para utilizar un translator, básicamente permite interceptar la interpretación de la línea que se está procesando del impex sobre el campo que se marca para utilizar dicho translator:

public abstract class AbstractValueTranslator {
  public abstract Object importValue(String var1, Item var2) throws JaloInvalidParameterException;

  public abstract String exportValue(Object var1) throws JaloInvalidParameterException;
}

En realidad, la implementación cuenta con varios métodos más, estos, sin embargo, son los más importantes:

  • importValue - Llamado cuando el elemento está siendo importado
  • exportValue - Raramente utilizado, es sólo para agregar un formato de salida al objeto que se va a exportar

En nuestro ejemplo, utilizaremos únicamente el método importValue

Haremos un ejemplo muy sencillo, en el cual actualizaremos la información de un cliente, en este caso, dado que el campo groups es una colección, realmente el impex cuenta con sólo dos mecanismos de carga:

  • mode=append - Agrega los elementos, puede generar elementos repetidos en caso de que algún elemento ya exista
  • (vacío) - hace default a sobreescribir todos los elementos de la colección

Crearemos entonces nuestro translator, como mencionamos, sólo utilizaremos el método de importación por ahora:

public class NopalCustomerGroupAssignmentTranslator extends AbstractValueTranslator
{
    /**
    * Loads the information from the impex file and merges the elements into the existing ones.
    */
    @Override
    public Object importValue(final String cellValue, final Item item) throws JaloInvalidParameterException
    {
        // obtener el id del cliente de la columna uid
        final String customerId = item.getAttribute("uid").toString();
        // sabemos que los campos vienen en un formato separado por comas
        final String[] groups = cellValue.split(",");
        
        // obtener el usuario directamente
        final UserModel user = userService.getUserForUID(customerId);
      
        // obtenere la lista modificada (es TOTALMENTE NECESARIO usar Jalo objects)
        final Collection<PrincipalGroup> newGroups = mergeGroups(user, groups);
      
        return newGroups;
    }
    
    private Collection<PrincipalGroupModel> mergeGroups(final UserModel user, final String[] previousGroups)
    {
        // TODO: implementar aquí la lógica para hacer el merge
    }
    
    
    @Override
    public String exportValue(final Object item) throws JaloInvalidParameterException
    {
        // TODO: log an error?
        return null;
    }
    
}

Como pueden darse cuenta, en realidad no estamos retornando ya un String o una colección de String, y esto ese porque, en realidad, debemos retornar los modelos esperados por el modelo que estamos alterando, en este caso, estamos agregando grupos y el componente más básico de un grupo ese un PrincipalGroupModel, finalmente este Model debe ser transformado a un objeto de Jalo ya que es la representación en la que se necesita, esto puede realizarse muy fácilmente utilizando modelService#getSource el cual retorna una versión de Jalo de un Modelo, por ejemplo:

private Collection<PrincipalGroupModel> mergeGroups(final UserModel user, final String[] previousGroups)
{
  // TODO: implement
  return modelGroups.stream()
      .map(ug -> (PrincipalGroup) getModelService.getSource(ug))
      .collect(Collectors.toList());
}

En caso de necesitar una dependencia de Spring, basta con sobreescribir el método init, el cual será llamado al iniciar la carga del elemento inidicado con el header para el translator:

    @Override
    public void init(StandardColumnDescriptor columnDescriptor)
    {
        // inject the dependency in runtime
        if (modelService == null)
        {
            modelService = (ModelService) Registry.getApplicationContext().getBean("modelService")
        }
    }

Finalmente, la implementación con validaciones se vería algo así:

public class NopalCustomerGroupAssignmentTranslator extends AbstractValueTranslator
{
 private static final Logger LOG = LoggerFactory.getLogger(NopalCustomerGroupAssignmentTranslator.class);

 private static final String SEPARATOR_TOKEN = ",";
 private static final String CUSTOMER_UID = "uid";

 private NopalCustomerGroupMergeStrategy nopalCustomerGroupMergeStrategy;


 /**
  * Loads the information from the impex file and merges the elements into the existing ones.
  */
 @Override
 public Object importValue(final String cellValue, final Item item) throws JaloInvalidParameterException
 {
  // unresolved item
  if (item == null)
  {
   // indicate that an error happened internally
   setError();
   return null;
  }

  final String groupsStr;
  final String customerId;

  try
  {
   groupsStr = cellValue;
   customerId = item.getAttribute(CUSTOMER_UID).toString();
  }
  catch (final JaloSecurityException ex)
  {
   LOG.warn("Error while trying to get the group for the import");
   setError();
   return null;
  }

  // get all the groups that are going to be added
  final String[] groupsArray = groupsStr.split(SEPARATOR_TOKEN);
  LOG.info("Adding groups {} to customer {}", groupsArray, customerId);

  final Collection < PrincipalGroup > nGroups = nopalCustomerGroupMergeStrategy
   .mergeGroupsForCustomer(customerId, Arrays.asList(groupsArray));

  if (LOG.isDebugEnabled())
  {
   LOG.debug("Switched groups are {}",
    nGroups.stream()
    .map(PrincipalGroup::getUid)
    .collect(Collectors.joining(","));
   }

   // use the set to be returned boxed into a collection, set is actually the typed required for the attribute "groups"
   return nGroups;
  }

  @Override
  public void init(StandardColumnDescriptor columnDescriptor)
  {
   // inject the dependency in runtime
   if (nopalCustomerGroupMergeStrategy == null)
   {
    nopalCustomerGroupMergeStrategy = (NopalCustomerGroupMergeStrategy) Registry.getApplicationContext()
     .getBean("nopalCustomerGroupMergeStrategy");
   }
  }

  @Override
  public String exportValue(final Object item) throws JaloInvalidParameterException
  {
   return null;
  }
 }

Como se puede observar, es posible implementar un elemento limpio y claro para un translator, y estos nos ayudan a solventar modificaciones a los modelos programáticamente sin tener que llegar a un interceptor o un atributo dinámico