将 URI 指定为目标的模型到模型变换的详细信息

可以修改为模型到模型变换生成的源代码,以使用户可以将统一资源标识(URI)指定为目标模型文件。

运行模型到模型变换将生成一个 in-memory 模型。缺省情况下,作为变换后处理的一部分,变换框架会将已生成的 in-memory 模型的内容写入工作空间中的一个文件。当用户为模型到模型变换创建变换配置时,可以将此文件指定为变换的目标容器,也可以创建新的目标容器。在变换配置中,名为“目标容器”的配置属性包含目标模型的文件名。工作空间中必须存在此文件才能运行变换。

此样本变换项目说明了如何提供另一种方法,以使用户可以通过定制已生成的变换源代码来配置目标容器。您作为变换的编写者,在生成模型到模型变换的源代码之后,可以定制代码,以使变换用户可以将 URI 而不是模型文件指定为变换目标容器。在运行变换之前,不需要 URI 所标识的文件;如果此文件不存在,变换时会创建它。

此样本包含一个简单的变换映射模型,它仅定义了从一个 UML 模型到另一个 UML 模型的单个映射;此映射将为已生成的目标模型指定名称,并且此名称是根据源模型的名称派生而来。
注: 一个模型的内部名称并不需要与文件系统中包含此模型的文件名相匹配。
由于此样本中的映射模型比较简单,因此已生成的变换仅说明了支持使用 URI 来指定目标容器时必须进行的定制。变换时不会将源模型中的元素复制至目标模型。
此样本说明如何定制已生成的变换中的下列各项:
  • plugin.xml 文件中的变换扩展点
  • 已生成的变换验证器类中的 isTargetElementValid 方法
  • 已生成的名为 Uri4targetTransformationProvider 的变换提供者类中的 createRootTransformation 方法

定制 plugin.xml 文件

生成变换源代码之后,在 plugin.xml 文件包含的变换扩展点中,名为 targetModelType 的属性将列示变换用户可以指定为目标容器的模型的类型。缺省情况下,此属性设置为 resource,这意味着在变换配置中,用户必须指定工作空间中已存在的文件。在定制的 plugin.xml 文件中,targetModelType 属性被设置为 none。

在 plugin.xml 文件中,已生成的变换扩展元素包含一个名为“目标模型 URI”的新变换属性。在此样本中,在“变换配置”向导和编辑器的属性选项卡上的目标模型 URI 字段中,用户将为此属性指定字符串值。

定制变换验证器类

变换配置向导和编辑器使用已生成的名为 Uri4targetTransformationValidator 的定制变换验证器类来验证变换配置中的设置。缺省情况下,仅当已配置的目标容器是一个文件时,isTargetElementValid 方法的实现才将返回 true。在此样本中,缺省实现已被覆盖,并且无论是否将一个值指定为目标容器,它都将返回 true。更强大的实现可能会对用户指定的 URI 执行特定于变换或特定于项目的验证。

以下代码段显示了变换生成的 isTargetElementValid 方法的缺省实现:
    /**
     * <!-- 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);
    }
以下代码段显示了样本包含的定制实现,对于此样本,始终将返回 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;
    }

定制变换提供者

在已生成的名为 Uri4targetTransformationProvider 的定制类中,createRootTransformation 方法的缺省实现将实例化 RootTransformation 类,而此类会依次实例化 ResourceTransform 类。ResourceTransform 类的缺省实现使用名为 ResourceTargetRule 的实现,此实现将打开用于表示已配置的目标容器的文件。在此样本中,以配置的目标容器是一个 URI 而不是一个文件;因此,已将一个名为 ResourceFromUriTransform 的定制 ResourceTransform 实现和一项名为 ResourceFromUriTargetRule 的定制 ResourceTargetRule 规则添加至 Uri4targetTransformationProvider 类。

名为 ResourceFromUriTargetRule 的定制实现将完成下列步骤:
  • 如果不存在由此 URI 指定的文件,那么将创建此文件
  • 打开由此 URI 指定的文件
  • 使 in-memory 模型资源与此文件相关联,并将文件对象存储在根变换上下文中,以便其他变换规则可以检索此文件对象
以下代码段显示了变换生成的 createRootTransformation 方法的缺省实现:
    /**
     * 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());
    }
以下代码段显示了样本包含的 createRootTransformation 方法的定制实现:
    /**
     * 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)));
             }};
    }
    
以下代码段显示了 Uri4targetTransformationProvider 类包含的名为 ResourceFromUriTransform 和 ResourceFromUriTargetRule 的定制实现:
    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;
        }        
    }

反馈