プロジェクトをソースとして指定するモデルからモデルへの変換の詳細

モデルからモデルへの変換用に生成されたソース・コードを変更して、ユーザーが変換のソース として複数のモデルを含むプロジェクトを指定できるようにすることができます。
通常、変換ユーザーは、モデルからモデルへの変換のソースとして 1 つのモデルを指定します。 これは、モデルからモデルへの変換では、デフォルトで 1 つのモデルを入力として受け入れるためです。このサンプルでは、生成された変換コードをカスタマイズして、 変換ユーザーが変換のソースとしてモデル・ファイルではなく Eclipse プロジェクトを指定できるようにし、 カスタム・コードでプロジェクト内のどのモデルを変換するかを判別するようにする方法を示します。指定プロジェクト内でファイル名拡張子が .emx である 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);
        }
        
    }

フィードバック