Detalles para una transformación de modelo a modelo con un URI como destino

Es posible modificar el código fuente que se genera en una transformación de modelo a modelo para que los usuarios puedan definir un identificador universal de recursos (URI) como archivo de modelo de destino.

Ejecutar una transformación de modelo a modelo genera un modelo en memoria. De forma predeterminada, como parte del postproceso de transformación, la infraestructura de transformación escribe el contenido del modelo en memoria generado en un archivo del espacio de trabajo. Cuando un usuario crea una configuración para una transformación de modelo a modelo, puede definir el archivo como contenedor de destino de la transformación, o bien crear un contenedor nuevo. En la configuración de transformación hay una propiedad llamada "contenedor de destino" que contiene el nombre de archivo del modelo de destino. Es necesario que este archivo se encuentre en el espacio de trabajo antes de ejecutar la transformación.

En este proyecto de transformación de ejemplo se muestra cómo proporcionar una forma alternativa para que los usuarios configuren el contenedor de destino personalizando el código fuente de la transformación. Como autor de una transformación, tras generar el código fuente de una transformación de modelo a modelo, puede personalizar el código para que el usuario de la transformación pueda especificar un URI, en vez de un archivo de modelos, como contenedor de destino de la transformación. No es necesario que el archivo que identifica el URI exista antes de ejecutar la transformación. Este proceso lo creará si no existe.

Este ejemplo contiene un modelo de correlación de transformaciones que define sólo una correlación de un modelo UML a otro; la correlación asigna un nombre al modelo de destino generado. Este nombre deriva del nombre del modelo de origen.
Nota: El nombre interno del modelo no tiene porqué coincidir con el nombre del archivo que contiene el modelo en el sistema de archivos.
Como el modelo de correlación de este ejemplo es sencillo, la transformación generada muestra sólo la personalización necesaria para darle soporte utilizando un URI que defina un contenedor de destino. La transformación no copia los elementos del modelo de origen al modelo de destino.
En este ejemplo se muestra cómo personalizar los elementos siguientes en la transformación generada:
  • El punto de ampliación de la transformación en el archivo plugin.xml
  • El método isTargetElementValid en la clase de validador de la transformación generada
  • El método createRootTransformation en la clase de proveedor de transformación denominado Uri4targetTransformationProvider

Personalización del archivo plugin.xml

Después de generar el código fuente de la transformación, dentro del archivo plugin.xml, en el punto de ampliación de la transformación, la propiedad denominada targetModelType enumera el tipo de modelos que puede definir el usuario de la transformación como contenedor de destino. De forma predeterminada, la propiedad está establecida en resource, que significa que en la configuración de transformación, el usuario debe especificar un archivo que se encuentre en el área de trabajo. En el archivo personalizado plugin.xml, la propiedad targetModelType está establecida en none.

En el archivo plugin.xml, el elemento de ampliación de la transformación tiene una propiedad llamada Target Model URI. En este ejemplo, dentro del editor y asistente de configuración de transformación, en el separador Propiedades, el usuario define un valor de serie para esta propiedad en el campo URI de modelo de destino.

Personalización de la clase de validador de la transformación

El asistente y editor de configuración de transformación utiliza la clase de validador de transformación personalizada que se llama Uri4targetTransformationValidator para validar los valores de la configuración de transformación. De forma predeterminada, la implementación del método isTargetElementValid devuelve true sólo si el contenedor de destino configurado es un archivo. En este ejemplo, se sustituye la implementación predeterminada y esta devuelve true independientemente del valor especificado, si existe, como contenedor de destino. Una implementación más completa puede realizar una validación específica de proyecto o de transformación en el URI que especifique el usuario.

En el siguiente fragmento de código se muestra la implementación predeterminada del método denominado isTargetElementValid que genera la transformación:
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isTargetElementValid(java.lang.Object)
     * @generated
     */
    protected boolean isTargetElementValid(Object target) {
    	//Remove @generated tag to add more target validation checks
    	return super.isTargetElementValid(target);
    }
En el siguiente fragmento de código se muestra la implementación personalizada que contiene el ejemplo, el cual en este ejemplo siempre devuelve true:
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isTargetElementValid(java.lang.Object)
     * @generated NOT
     */
    protected boolean isTargetElementValid(Object target) {
        return true;
    }

Personalización del proveedor de transformación

En la clase personalizada que se genera con nombre Uri4targetTransformationProvider, la implementación predeterminada del método denominado createRootTransformation crea instancias de la clase llamada RootTransformation, que a su vez crea instancias de la clase ResourceTransform. La implementación predeterminada de la clase ResourceTransform utiliza una implementación denominada ResourceTargetRule que abre el archivo que funciona como contenedor de destino configurado. En este ejemplo, el contenedor de destino configurado es un URI en vez de un archivo. Por tanto, se añaden a la clase Uri4targetTransformationProvider una implementación ResourceTransform personalizada denominada ResourceFromUriTransform y una regla ResourceTargetRule personalizada denominada ResourceFromUriTargetRule.

La implementación personalizada denominada ResourceFromUriTargetRule lleva a cabo los pasos siguientes:
  • Crea el archivo especificado por el URI, si no existe
  • Abre el archivo especificado por el URI
  • Asocia un recurso de modelo en memoria con el archivo y almacena el objeto de archivo en el contexto de transformación raíz para que otras reglas de transformación puedan recuperarlo.
En el fragmento de código siguiente se muestra la implementación predeterminada del método createRootTransformation que genera la transformaciones:
    /**
     * Crea una transformación raíz. Aquí se pueden añadir más reglas de la transformación
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform());
    }
En el siguiente fragmento de código se muestra la implementación personalizada del método denominado createRootTransformation que contiene el ejemplo:
    /**
     * Crea una transformación raíz. Aquí se pueden añadir más reglas de la transformación
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated NOT
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform()) {
            @Override
             protected void addInitialExtractor(Transform mainTransform) {
                add(new ResourceListExtractor(new ResourceFromUriTransform(mainTransform)));
             }};
    }
    
En el siguiente fragmento de código se muestran las implementaciones personalizadas denominadas ResourceFromUriTransform y ResourceFromUriTargetRule que contiene la clase Uri4targetTransformationProvider contains:
    protected class ResourceFromUriTransform extends ResourceTransform {
        public ResourceFromUriTransform(Transform mainTransform) {
            super(Uri4targetMessages.ResourceFromUriTransform_id);
            setName(Uri4targetMessages.ResourceFromUriTransform_name);
            add(new ResourceFromUriTargetRule());
            add(new ResourceContentsExtractor(mainTransform));
        }
    }

    protected class ResourceFromUriTargetRule extends ResourceTargetRule {
        @Override
        protected Object createTarget(ITransformContext context) {
            ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.TARGET_EDITING_DOMAIN))
.getResourceSet();
            Resource resource = null;
            Object targetModelURIString = context.getPropertyValue("TargetModelURI"); //$NON-NLS-1$
            if (targetModelURIString instanceof String) {
                URI targetModelURI = URI.createURI((String)targetModelURIString);
                IPath targetModelPath = new Path(targetModelURI.path());                
                IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
                IFile targetModelFile = wsRoot.getFile(targetModelPath);
                ValidateEditRule.addAffectedFile(context, targetModelFile);
                resource = resourceSet.createResource(getPlatformURI(targetModelFile));
                ITransformContext rootContext = context;
                while (rootContext.getParentContext() != null)
                    rootContext = rootContext.getParentContext();
                rootContext.setPropertyValue(ITransformContext.TARGET_CONTAINER, targetModelFile);
            }
            return resource;
        }        
    }

Comentarios