Details for a model-to-model transformation that specifies a URI as a target

You can modify the source code that is generated for a model-to-model transformation to enable users to specify a Uniform Resource Identifier (URI) as the target model file.

Running a model-to-model transformation generates an in-memory model. By default, as part of transformation post-processing, the transformation framework writes the contents of the generated in-memory model to a file in the workspace. When a user creates a transformation configuration for the model-to-model transformation, the user can specify the file as the target container of the transformation, or create a new target container. In a transformation configuration, a configuration property named "target container" contains the file name of the target model. This file must exist in the workspace before the transformation runs.

This sample transformation project shows how to provide an alternate way for users to configure the target container by customizing the generated transformation source code. As a transformation author, after you generate the source code for a model-to-model transformation, you can customize the code so that a transformation user can specify a URI, instead of a model file, as the transformation target container. The file that the URI identifies does not need to exist before the transformation runs; the transformation creates the file if it does not exist.

This sample contains a simple transformation mapping model that defines only one mapping from a UML model to a UML model; the mapping assigns a name to the generated target model, and this name is derived from the name of the source model.
Note: The internal name of a model does not have to match the name of the file that contains the model in the file system.
Because the mapping model in this sample is simple, the generated transformation demonstrates only the required customization to support using a URI to specify a target container. The transformation does not copy elements from the source model to the target model.
This sample shows how to customize the following items in the generated transformation:

Customization of the plugin.xml file

After you generate transformation source code, in the plugin.xml file, in the transformation extension point, the property named targetModelType lists the type of models that a transformation user can specify as the target container. By default, this property is set to resource, which means that in the transformation configuration, the user must specify a file that exists in the workspace. In the customized plugin.xml file, the targetModelType property is set to none.

In the plugin.xml file, the generated transformation extension element contains a new transformation property named Target Model URI. In this sample, in the Transformation Configuration wizard and editor, on the Properties tab, in the Target Model URI field, the user specifies a string value for the property.

Customization of the transformation validator class

The transformation configuration wizard and editor use the generated custom transformation validator class named Uri4targetTransformationValidator to validate the settings in the transformation configuration. By default, the implementation of the method named isTargetElementValid returns true only if the configured target container is a file. In this sample, the default implementation is overridden and it returns true whether a value is specified as the target container. A more robust implementation might perform a transformation-specific or project-specific validation on the URI that the user specifies.

The following code fragment shows the default implementation of the method named isTargetElementValid that the transformation generates:
    /**
     * <!-- 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);
    }
The following code fragment shows the customized implementation that the sample contains, which, for the purposes of this sample, always returns 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;
    }

Customization of the transformation provider

In the generated custom class named Uri4targetTransformationProvider, the default implementation of the method named createRootTransformation instantiates the class named RootTransformation, which in turn instantiates the class named ResourceTransform. The default implementation of the class named ResourceTransform uses an implementation named ResourceTargetRule that opens the file that represents the configured target container. In this sample, the configured target container is a URI instead of a file; therefore, a custom ResourceTransform implementation named ResourceFromUriTransform, and a custom ResourceTargetRule rule named ResourceFromUriTargetRule, are added to the Uri4targetTransformationProvider class.

The custom implementation named ResourceFromUriTargetRule completes the following steps:
  • Creates the file specified by the URI, if it does not exist
  • Opens the file specified by the URI
  • Associates an in-memory model resource with the file, and stores the file object in the root transformation context so that other transformation rules can retrieve it
The following code fragment shows the default implementation of the createRootTransformation method that the transformation generates:
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform());
    }
The following code fragment shows the custom implementation of the method named createRootTransformation that the sample contains:
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- 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)));
             }};
    }
    
The following code fragment shows the custom implementations named ResourceFromUriTransform and ResourceFromUriTargetRule that the class named 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;
        }        
    }

Feedback