将项目指定为源的模型到模型变换的详细信息

可以修改已为模型到模型变换生成的源代码,以使用户可以将包含多个模型的项目指定为变换源。
通常,变换用户将一个模型指定为模型到模型变换的源,因为模型到模型变换在缺省情况下接受将一个模型作为输入。此样本说明如何定制已生成的变换代码,以使变换用户可以将 Eclipse 项目而不是模型文件指定为变换源,并且定制代码确定要变换此项目中的哪些模型。在所指定的项目中,将 .emx 作为文件扩展名的 UML 模型是在变换运行时收集的,而不是在用户配置变换时收集的,并且这些 UML 模型用作变换的输入。
注: 在此样本中,变换在处理源模型时采用的顺序无关紧要。要按特定顺序处理这些模型,请将相应的代码添加至 ProjectContentsExtractor 类的实现中。

此样本包含一个变换映射模型,用于为 UML 模型、包和类定义基本映射。生成的变换将创建一个与源项目同名的 UML 模型,并且在该模型中,将为该源项目中包含的每个 UML 模型创建一个包。对于相应 UML 源模型中的每个类,此变换还会在每个包中创建一个类。尽管此映射模型比较简单,但是所生成的变换说明了您必须如何定制代码以支持通过指定源项目来指定源模型。

此样本说明如何定制已生成的变换中的下列各项:
  • 已生成的 plugin.xml 文件中的变换扩展点
  • 已生成的变换验证器中的 isSourceElementValid 方法
  • 已生成的变换提供者中的 createRootTransformation 方法

定制已生成的 plugin.xml 文件

在 plugin.xml 文件包含的变换扩展点中,名为 sourceModelType 的属性指定变换用户可以指定为变换源的对象的类型。当创建模型到模型变换项目时,此属性值在缺省情况下设置为 resource,这意味着在变换配置向导和编辑器中,变换用户必须将工作空间中的现有文件指定为变换源。将 sourceModelType 属性的值设置为 project 时,变换用户可以将 Eclipse 项目而不是文件指定为变换源。

定制变换验证器类

变换配置向导和编辑器使用变换验证器类来验证是否可以使用用户指定的设置来正确运行变换。在变换验证器类中,仅当所指定的变换源是一个文件时,名为 isSourceElementValid 的方法的缺省实现才将返回 true。

在此样本中,名为 Project4sourceTransformationValidator 的变换验证器类将验证是否可以使用用户指定的设置来正确运行变换。对于此样本,此类中的代码将覆盖 isSourceElementValid 方法的缺省实现,并且仅当变换源是一个项目时,此方法才将返回 true。一种更强大的实现可以检查用户是否选择了 UML 项目。

以下代码段显示了变换生成的 isSourceElementValid 方法的缺省版本:

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isSourceElementValid(java.lang.Object)
     * @generated
     */
    protected boolean isSourceElementValid(Object source) {
    	//Remove @generated tag to add more source validation checks
    	return super.isSourceElementValid(source);
    }
以下代码段显示了此方法的定制版本,对于此样本,此方法始终将返回 true:
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isSourceElementValid(java.lang.Object)
     * @generated NOT
     */
    protected boolean isSourceElementValid(Object source) {
    	return source instanceof IProject;
    }

定制变换提供者类

在名为 Project4sourceTransformationProvider 的变换提供者类中,createRootTransformation 方法的缺省实现将实例化名为 RootTransformation 的对象,而此对象将实例化 ResourceTransform 类的缺省实现。ResourceTransform 类的缺省实现包含下列各项:
  • 将打开模型文件并将其内容装入内存中的 ResourceContentsExtractor 方法的实现
  • 将实例化由变换生成的目标模型的名为 ResourceTargetRule 的规则
    注: 此规则取决于变换上下文中的 sourceModelType 属性:如果您更改 sourceModelType 属性的缺省值,那么您还应该定制名为 ResourceTargetRule 的规则以及 ResourceContentsExtractor 方法的实现。
此样本将定义一个 ResourcesFromProjectTransform 类,此类是 ResourceTransform 类的定制版本。此定制类将实例化下列类:
  • 名为 ProjectContentsExtractor 的类,此类是 ResourceContentsExtractor 类的定制版本
  • 名为 Project4sourceTargetRule 的类,此类是 ResourceTargetRule 类的定制版本

以下代码段显示了变换生成的 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 ResourcesFromProjectTransform(mainTransform)));
             }};
    }

以下代码段显示了名为 ResourcesFromProjectTransform 的变换的源代码,其中包含一个名为 ProjectContentsExtractor 的抽取器和一项名为 Project4sourceTargetRule 的规则。

    protected class ResourcesFromProjectTransform extends ResourceTransform {
        public ResourcesFromProjectTransform(Transform mainTransform) {
            super(Project4sourceMessages.ResourcesFromProjectTransform_id);
            setName(Project4sourceMessages.ResourcesFromProjectTransform_name);
            add(new Project4sourceTargetRule());
            add(new ProjectContentsExtractor(mainTransform));
        }
    }
    
    protected class ProjectContentsExtractor extends ResourceContentsExtractor {
        
        public static final String UML_MODEL_FILE_TYPE = "emx"; //$NON-NLS-1$
        
        public ProjectContentsExtractor(AbstractTransform transform) {
            super(transform);
            setName(Project4sourceMessages.ProjectContentsExtractor_name);
        }

        @Override
        public Collection<Model> execute(ITransformContext context) {
            final ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.SOURCE_EDITING_DOMAIN)).getResourceSet();
            final Collection<Model> models = new BasicEList();
            Object source = context.getSource();
            if (source instanceof IProject) {
                IProject project = (IProject)source;
                IResourceVisitor visitor = new IResourceVisitor() {
                    @Override
                    public boolean visit(IResource resource) throws CoreException {
                        if (resource instanceof IProject || resource instanceof IFolder)
                            return true;
                        if (resource instanceof IFile) {
                            IFile file = (IFile)resource;
                            if (UML_MODEL_FILE_TYPE.equals(file.getFileExtension())) {
                                Resource modelResource = resourceSet.getResource(getPlatformURI(file), true);
                                for (Iterator<EObject> i = modelResource.getContents().iterator(); i.hasNext();) {
                                    EObject content = i.next();
                                    if (content instanceof Model)
                                        models.add((Model)content);
                                }
                            }
                        }
                        return false;
                    }                    
                };
                try {
                    project.accept(visitor);
                } catch (CoreException ce) {
                    Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
Project4sourceMessages.ProjectContentsExtractor_name, ce));
                }                   
            }
            return models;
        }

    }
    
    protected class Project4sourceTargetRule extends ResourceTargetRule {

        @Override
        protected Object createTarget(ITransformContext context) {
            if (context.getSource() instanceof IProject) {        
                Object targetContainer = context.getTargetContainer();        
                if (targetContainer instanceof Resource) {
                    return targetContainer;
                } else if (targetContainer instanceof IFile){
                    IFile targetFile = (IFile)targetContainer;
                    ValidateEditRule.addAffectedFile(context, targetFile);
                    ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.TARGET_EDITING_DOMAIN)).getResourceSet();
                    return resourceSet.createResource(getPlatformURI(targetFile));
                }
            }
            return super.createTarget(context);
        }
        
    }

反馈