IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  오픈 소스  >

EMF 모델의 콘텐트를 검색하는 Eclipse 플러그인 구현하기 (한글)

Common Navigator Framework과 Eclipse Modeling Framework을 사용하여 EMF 기반 모델의 콘텐트 조작 및 검색하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Javier Torres, Staff Software Engineer, IBM

2007 년 10 월 16 일

EMF.Edit과 Common Navigator Framework (CNF)을 사용하여 트리 뷰어에 기반한 모델 네비게이션 플러그인을 만드는 방법을 배워봅시다. 사용자가 Eclipse Modeling Framework (EMF) 기반 모델의 콘텐트를 조작 및 검색할 수 있도록 하는 Eclipse 플러그인을 구현합니다. 플러그인 개발, EMF 편집 프레임웍을 통해 모델 콘텐트를 추출할 수 있는 구조 구현, CNF 기반 뷰 파트에 콘텐트 디스플레이 하는 방법을 단계별로 설명합니다.

일반적으로, EMF 프로젝트 리소스— 예를 들어, EMF Ecore 모델 —는 뷰어에 단일 객체로서 디스플레이 된다. (그림 1의 왼편). 이것의 한계는 연결된 에디터를 열지 않고는 모델을 검색할 수 없다는 점이다. 개발이 도메인 모델에 의존할 경우에는 손실이 크다. 이것을 해결하는 한 가지 방법은 우리가 원하는 도메인 모델 콘텐트로 액세스를 제공할 커스텀 뷰를 구현하는 것이다. 이 플러그인을 처음부터 구현하거나, 기존 프레임웍을 사용할 수 있다. 이 글에서는 플러그인을 생성하는 절차를 개요 및 상세히 설명할 것이다. 이 글의 끝에 가서는 Ecore 모델(그림 1의 오른편)을 검색하는데 사용될 수 있는 뷰어 플러그인이 생길 것이다.

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot


그림 1. 네비게이터의 유형
네비게이터의 유형

배경

ModelNavigator 플러그인에게서 바라는 것이 무엇인지 알고는 있지만, 개발을 시작하기 전에, 우리가 사용하게 될 Eclipse 컴포넌트를 기본적으로 알고 있어야 한다. 모델의 계층을 디스플레이 하는 트리 뷰어를 구현해야 한다. 트리 뷰어의 상세는 이 글의 범위를 벗어난다. 참고자료 섹션을 참조하라. 한 가지 중요한 측면은 트리 뷰어들은 콘텐트 프로바이더라고 하는 어댑터를 통해서 모델 객체에 액세스 하고, 객체가 레이블 프로바이더를 통해 시각화 되는 방법을 결정한다. 다음 섹션에서는 콘텐트 및 레이블 프로바이더를 위해 데이터에 액세스 할 수 있는 방법과, 모델 네비게이터를 디스플레이 하는 방법을 상세히 설명하겠다.

EMF.Edit 프레임웍

EMF.Edit 프레임웍은 EMF 모델용 에디터를 구현하는데 사용된다. 이 에디터를 구현하려면, 프레임웍은 명령어 코드 생성 기능과 기타 클래스를 제공하여 프로그래밍 방식으로 모델에 액세스 할 수 있도록 해야 한다. 이 프레임웍이 노출하는 다른 기능들이자 가장 중요한 것은 EMF 모델이 뷰어에 디스플레이 되도록 하는 편의 클래스들이다. 이 프레임웍은 특정 유형의 EMF 객체용 어댑터를 사용하여 모델을 디스플레이 하는 기본 콘텐트와 레이블 프로바이더를 통해 액세스를 제공한다. AdapterFactoryContentProviderAdapterFactoryLabelProvider 클래스가 있는데, 이것은 EMF 모델을 검색하는 방법을 알고 있는 아이템 프로바이더 어댑터들에 위임함으로써 객체, 레이블, 이미지를 EMF 객체용 뷰어에 제공한다. 이러한 스킴은 그림 2에 나타나 있다. 이는 모델을 뷰에 적응시키는 방법에 대해 알 필요가 없기 때문에 유용하다. 우리는 그저 이러한 기본 프로바이더에 위임하기만 하면 된다.


그림 2. Eclipse help에서 변환된 EMF.Edit
Eclipse help에서 변환된 EMF.Edit

이 프레임웍에는 다양한 EMF 모델 유형을 위한 아이템 프로바이더가 포함되어 있다. 하지만, 우리 대부분은 각각의 모델 유형 마다 개별 네비게이터를 구현하고 싶지는 않을 것이다. 같은 네비게이터에서 모든 모델 콘텐트에 액세스 하고 싶다. 바로 여기에서 복합 어댑터 팩토리가 등장한다. 다중 모델에서 객체들의 결합체를 적응시킬 수 있는 어댑터 팩토리를 제공함으로써, 한 개 이상의 EMF 모델에서 객체를 디스플레이 할 수 있다.

ComposedAdapterFactory 클래스는 다른 어댑터 팩토리에 대한 공통 인터페이스로서 작동하는 EMF.Edit 클래스들 중 하나이다. 이것의 장점은 복합 어댑터 팩토리의 일부로서 우리가 관심을 갖고 있는 모델 유형에 대한 아이템 프로바이더만 포함시키면 된다는 것이다. 복합 어댑터 팩토리는 구현을 다른 프로바이더에 위임한다. 예를 들어, 네비게이터가 제너레이터 모델, Ecore 모델, UML 모델에 디스플레이를 제공하게끔 할 수 있다. 뷰어가 이러한 모델들을 디스플레이 하려고 할 때, 콘텐트와 레이블 프로바이더는 어댑터 팩토리에 위임하는데, 이는 다시 적절한 아이템 프로바이더로 위임하면서, 개발을 쉽게 하고 ModelNavigator가 확장되어 다중 도메인 모델을 지원할 수 있도록 한다.

Common Navigator Framework

Common Navigator Framework
Navigator Framework (CNF)의 기능과 사용법에 대한 튜토리얼들은 Michael Elder의 블로그에서 참조하기 바란다. (참고자료) CMF에 관심이 있는 개발자들이라면 적극 권장한다.

ModelNavigator의 모델 콘텐트에 액세스 할 수 있는 전체 프레임웍이 갖춰졌으므로, 우리에게 필요한 컴포넌트는 네비게이터를 저장 할 실제 뷰어이다. 뷰 플러그인을 확장하고 트리 뷰에 원하는 콘텐트를 디스플레이 할 고유의 뷰 파트를 구현하는 것이 가능하다. 하지만, 프레임웍은 다양한 도메인에서 온 콘텐트들을 하나의 뷰로 결합하면서, 사용자들이 하나의 뷰어에서 에디터 모델을 조작하고 검색할 수 있도록 해준다. 이 프레임웍은 Eclipse V3.2에 CNF, org.eclipse.ui.navigator로서 도입되었고, 개발자들은 콘텐트, 레이블, 액션, 필터, 기타 기능들을 하나의 네비게이터로 기여할 수 있다. 네비게이션 뷰어를 통합하고 일관된 사용자 경험을 제공할 방법을 제공한다.

CNF는 모든 에디터 모델 통합자를 위한 하나의 뷰어를 지원하고, 비 리소스 중심 모델 콘텐트를 허용하며, 사용자가 자신들의 통합 뷰어에서 원하는 것을 선택할 수 있도록 한다. org.eclipse.ui.navigator.resources 플러그인은 이러한 프레임웍의 한 예이며, Project Explorer 뷰의 형태로 나타나 있다. IResource 모델에 대한 뷰어 확장을 제공한다. 이 프레임웍은 우리의 뷰어를 구현할 수 있는 가장 빠른 방식을 제공하고, 뷰어 구현의 상세를 핸들하며, 우리는 모델에 대한 콘텐트 및 레이블 프로바이더만 구현하면 된다. 또한, 플러그인을 다른 모델 콘텐트로 확장할 여지도 제공하며, 뷰어에서 프레임웍의 고급 기능을 활용할 수 있도록 해준다. (분류기, 필터, 드래그&드롭)

이제 이러한 컴포넌트들을 작동시키고, 모델 네비게이션 플러그인을 구현할 준비가 되었다.




위로


간단한 네비게이터

ModelNavigator를 구현하려면 두 단계를 거쳐야 한다. 먼저, 플러그인의 기본 구조를 설정하고, 작동을 정의해야 한다. 그런 다음, 이러한 간단한 플러그인을 확장하여 EMF 모델 콘텐트를 디스플레이 할 것이다.

ModelNavigator 프로젝트

ModelNavigator를 생성하는 첫 번째 단계는 플러그인 프로젝트를 생성하는 것이다. 새로운 프로젝트 마법사를 사용한다. File > New > Project에서 Plug-in Project를 선택하고 Next를 클릭한다.

플러그인 프로젝트 이름을 ModelNavigator로 하고, 플러그인 ID를 com.ibm.navigator.example.modelnavigator로 설정하고, 액티베이터를 com.ibm.navigator.example.modelnavigator.ModelNavigatorPlugin으로 설정한 다음, Finish를 클릭한다.


그림 3. 플러그인 프로젝트 생성하기
플러그인 프로젝트 생성하기

뷰 만들기

이제 플러그인을 개발할 준비가 되었다. 첫 번째 단계는 네비게이터를 수용할 뷰를 생성하는 단계이다. 플러그인에서 확장을 하여 뷰가 나타날 곳에 뷰 파트와 카테고리를 생성한다. plug-in xml 파일에서, 뷰 확장을 추가한다.

Extensions 탭에서:

  • Add를 클릭한다.
  • Extension points 탭 밑에서, org.eclipse.ui.views를 선택한다.
  • 카테고리 만들기:
    • org.eclipse.ui.views 확장에서 오른쪽 클릭한다.
    • New > Category를 선택한다.
    • 이름을 com.ibm.navigator.example.modelnavigator.mncategory로 한다.
    • 아이디를 Model Navigator로 설정한다.
  • 뷰 파트 만들기:
    • org.eclipse.ui.views 확장을 오른쪽 클릭한다.
    • New > View를 선택한다.
    • 아이디를 com.ibm.navigator.example.modelnavigator.mnview로 설정한다.
    • 이름을 Model Navigator View로 설정한다.
    • 클래스를 org.eclipse.ui.navigator.CommonNavigator로 설정한다.
    • 카테고리를 com.ibm.navigator.example.modelnavigator.mncategory로 설정한다.
  • 변경 사항을 저장한다.

언급한 대로, 구현 부담을 CNF로 옮겼다. 뷰를 설정하는 방식에서 알아두어야 할 점은 뷰를 위해 ViewPart를 확장할 고유의 클래스를 만드는 대신, 뷰가 공통 네비게이터 클래스를 사용할 수 있도록 하였다. 클래스 필드에서 우리가 가리키는 공통 네비게이터 클래스는 우리 플러그인의 클래스 경로에 추가되어야 한다. 계속 진행하여 org.eclipse.ui.navigator를 Dependencies 탭 상의 필수 플러그인에 추가한다.

기본 작동 설정 및 CNF에 추가하기

다음 단계는 플러그인용 CNF 애트리뷰트를 설정하는 단계인데, 네비게이터의 기본 작동을 명시한다.

먼저, 뷰를 공통 네비게이터 뷰어에 연결시킨다. Extensions 탭에서:

  • Add를 클릭한다.
  • Extension points 탭 밑에서, org.eclipse.ui.navigator.viewer를 선택하고 Finish를 클릭한다.
  • 뷰어 생성하기:
    • Right-click on the org.eclipse.ui.navigator.viewer 확장에서 오른쪽 클릭한다.
    • New > viewer를 선택한다.
    • viewerid를 위에서 정의했던 뷰의 아이디로 설정한다.. (com.ibm.navigator.example.modelnavigator.mnview)

네비게이터 플러그인의 작동은 연결된 콘텐트, 액션, CNF를 사용할 때 플러그인에서 설정한 기타 옵션들(필터, 분류기)에 의해 관리된다. 플러그인에서, include 엘리먼트는 어떤 확장들이 뷰어에 보일 것인지를 선택한다. 콘텐트 확장은 프레임웍에게 뷰에 콘텐트를 디스플레이 하는 방법을 알려주고, 액션 확장은 프레임웍에게 어떤 옵션들을 뷰에 사용할 수 있는지(콘텍스트 메뉴 등)를 알려준다. 이러한 기본적인 네비게이터를 설치하여 실행하려면, IResource 모델에서 콘텐트와 액션 바인딩을 추가하면서, 플러그인을 Package Explorer와 유사한 모습으로 만든다. 이를 위해 viewerContentBinding을 생성하여 네비게이터가 리소스 콘텐트 확장을 추가하도록 하고, viewerActionBinding을 생성하여 리소스 액션 확장을 추가한다.

Extensions에서 IResource 콘텐트 확장 추가하기:

  • org.eclipse.ui.navigator.viewer 확장에서 오른쪽 클릭 한다.
  • New > viewerContentBinding을 선택한다.
  • viewerid를 플러그인의 뷰 파트 아이디로 설정한다. (com.ibm.navigator.example.modelnavigator.mnview)
  • 콘텐트 바인딩을 추가한다:
    • viewerContentBinding을 오른쪽 클릭한다.
    • New > includes를 선택한다.
    • includes 엘리먼트를 오른쪽 클릭한다.
    • New > contentExtension을 선택한다.
    • 패턴을 org.eclipse.ui.navigator.resourceContent로 설정한다.

Extensions 탭에서 IResource 액션 확장을 연결하기:

  • org.eclipse.ui.navigator.viewer 확장에서 오른쪽 클릭한다.
  • New > viewerActionBinding을 선택한다.
  • viewerid를 플러그인의 뷰 파트 아이디로 설정한다. (com.ibm.navigator.example.modelnavigator.mnview)
  • 액션 바인딩 추가하기:
    • viewerContentBinding을 오른쪽 클릭한다.
    • New > includes를 선택한다.
    • includes 엘리먼트를 오른쪽 클릭한다.
    • New > actionExtension을 선택한다.
    • 패턴을 org.eclipse.ui.navigator.resources.*로 설정한다.

이제 네비게이터 구조가 설정되었다. 네비게이터 프레임웍에 디스플레이 하고자 하는 콘텐트 유형을 지시하는 방법과, 네비게이터가 작동하게 하는 방법을 배웠다. 이러한 확장들을 반드시 추가해야 할 필요는 없었지만, IResource 모델 콘텐트와 액션을 추가함으로써, 보다 유용한 뷰를 갖게 되었다. 또한, 콘텐트를 뷰어에 연결시키고, 이것을 확장하여 커스텀 또는 사전 정의된 필터를 추가하는 방법도 배웠다. 자세한 내용은 참고자료 섹션을 참조하라. 네비게이터는 아직 우리가 원하는 모습이 아니기 때문에, 뷰어에 EMF 모델을 디스플레이 하는 기능을 추가해야 한다.




위로


EMF 도메인 콘텐트 추가하기

EMF 도메인 모델 콘텐트를 네비게이터에 디스플레이 하려면, 프레임웍에게 어떤 모델에 관심이 있는지, 이 모델의 정보를 획득할 수 있는 방법은 무엇인지, 이를 디스플레이 할 방법과 시기에 대해 알려주어야 한다. 네비게이터 콘텐트 서비스에 의해 사용될 수 있는 콘텐트 확장을 생성하여 EMF 도메인 모델을 디스플레이 해야 한다. org.eclipse.ui.navigator.navigatorContent 플러그인에 대한 확장을 생성해야 한다.

네비게이터 콘텐트 확장은 EMF 모델의 엘리먼트에 자식 및 부모 객체를 제공하는데 사용될 수 있는 콘텐트 프로바이더와 레이블 프로바이더를 정의한다. 또한, triggerPoints로 알려진 자식 객체 또는possibleChildren으로 알려진 부모 객체를 제공하기 위해 이러한 확장이 호출될 수 있는 시기도 정의한다. 액션 프로바이더, 공통 마법사, 필터 같은 플러그인의 작동을 수정하기 위해 우리가 수정할 수 있는 네비게이터 콘텐트의 다른 애트리뷰트들도 있다. 하지만, 이것들은 ModelNavigator 플러그인을 생성하는데 있어 필수적인 것은 아니다.

먼저, 공통 네비게이터에 의해 사용될 콘텐트와 레이블 프로바이더를 지정할 새로운 콘텐트 확장을 만들어야 한다. 그리고 나서, 이러한 클래스들을 구현할 것이다.

Extensions 탭에서 navigatorContent 확장 추가하기:

  • Add를 클릭한다.
  • Extension points 탭 밑에서, org.eclipse.ui.navigator.navigatorContent를 선택하고 Finish를 클릭한다.
  • Navigator Content 생성하기:
    • org.eclipse.ui.navigator.navigatorContent 확장을 오른쪽 클릭한다.
    • New > navigatorContent를 선택한다.
    • 아이디를 com.ibm.navigator.example.modelnavigator.emfModelContent로 설정한다.
    • 이름을 EMF Model Content로 설정한다.
    • Content 프로바이더를 com.ibm.navigator.example.modelnavigator.MNViewContentProvider로 설정한다.
    • Label 프로바이더를 com.ibm.navigator.example.modelnavigator.MNViewLabelProvider로 설정한다.
    • Priority를 normal로 설정한다.
    • ActiveByDefault를 true로 설정한다.

네비게이터 콘텐트용 콘텐트 및 레이블 프로바이더로서 작동할 클래스를 구현한다.

복합 어댑터 팩토리

EMF.Edit 프레임웍을 사용하여 콘텐트와 레이블 프로바이더의 실제 작업을 수행할 것이다. 따라서, 콘텐트 및 레이블 프로바이더 클래스를 EMF 편집 프레임웍에서 어댑터 팩토리들의 하위 클래스로서 생성해야 한다. 이는 각각 AdapterFactoryContentProviderAdapterFactoryLabelProvider로 위임할 콘텐트와 레이블 프로바이더 클래스를 생성하기 전에, 이러한 어댑터 팩토리들이 다른 EMF 모델들용 아이템 프로바이더 리스트를 사용하여 인스턴스화 된다는 것을 기억해야 한다. 다시 말해서, 복합 어댑터 팩토리로서 프로바이더 리스트를 먼저 만들어야 한다. MNComposedAdapterFactory라고 하는 새로운 클래스를 만든다. (File > New > Class)


그림 4. 구현 클래스 생성하기
플러그인 프로젝트 생성하기

org.eclipse.emf.codegen.ecore.ui를 Dependencies 탭 상의 필수 플러그인에 추가해야 한다. 이렇게 하면 다른 EMF 모델 유형을 위한 ComposedAdapterFactory 아이템 프로바이더와, 플러그인에 사용할 수 있는 EMF.Edit 클래스가 만들어진다. MNComposedAdapterFactory 클래스의 구현은 Listing 1과 같다.


Listing 1. ComposedAdapterFactory 클래스
                
...
public class MNComposedAdapterFactory
{
    private static ComposedAdapterFactory mnCompAdapterFactory;

    public final static ComposedAdapterFactory getAdapterFactory()
    {
        if (mnCompAdapterFactory == null)
            mnCompAdapterFactory = new ComposedAdapterFactory(createFactoryList());
        return mnCompAdapterFactory;
    }

    public final static ArrayList<AdapterFactory> createFactoryList()
    {
        ArrayList<AdapterFactory> factories = new ArrayList<AdapterFactory>();
        factories.add(new ResourceItemProviderAdapterFactory());
        factories.add(new EcoreItemProviderAdapterFactory());
        factories.add(new ReflectiveItemProviderAdapterFactory());
        return factories;
    }
}

중요한 것은 아이템 프로바이더의 리스트를 만들 정적 메소드를 만들고 있다는 것이다. 이러한 아이템 프로바이더들 중에, EcoreItemProviderAdapterFactory는 Ecore 모델을 위한 콘텐트와 레이블을 제공하기 위해 어댑터 팩토리가 위임해야 할 것이다.

콘텐트와 레이블 프로바이더

이와 비슷한 방식으로, navigatorContent 확장 상세에 지정했던 콘텐트와 레이블-프로바이더 클래스를 만든다.

콘텐트 프로바이더(MNViewContentProvider)로 시작하여, 확장 상세 패널에 있는 프로바이더 이름 옆에 있는 링크를 클릭하거나, File > New > Class 다이얼로그로 간다. 콘텐트 프로바이더용 ITreeContentProvider 인터페이스를 구현하는 대신, EMF.Edit 클래스를 사용한다. 이를 위해서, MNViewContentProvider 클래스를 수정하여 AdapterFactoryContentProvider 클래스를 확장한다. AdapterFactoryContentProvider 클래스는 ITreeContentProvider 인터페이스의 구현을 핸들하는 방법을 이미 알고 있는데, 이것은 콘텐트를 뷰어에 제공하는 아이템 프로바이더로 위임한다.

AdapterFactoryContentProvider 클래스는 그 구조체에 어댑터 팩토리를 기대하고 있다. 따라서 콘텐트 프로바이더에 모호한 구조체를 사용할 수 없다. 콘텐트 프로바이더 구조체를 명확히 선언하고, 수퍼-클래스 구조체를 예상된 매개변수와 함께 호출해야 한다. 구조체를 선언하면, super(MNComposedAdapterFactory.getAdapterFactory());를 여기에 추가한다. 이 클래스에서 우리가 초점을 맞출 다른 메소드는 getChildren, getParent, hasChildren, getElements이다.

getChildren 메소드는 뷰어가 도메인 객체의 자식 엘리먼트를 디스플레이 해야 할 때 호출된다. 이것은 매개변수 엘리먼트의 자식인 도메인 객체들의 어레이를 리턴한다. 이와 비슷하게, getElements 메소드는 매개변수 엘리먼트의 도메인 객체를 획득하기 위해 호출된다. 이 두 가지는 비슷한 함수로 연산된다. 다른 시간에 호출될 뿐이다. getChildren 메소드를 구현하려면, AdapterFactoryContentProvider가 주어진 부모의 URI의 자식들을 리턴하도록 하면 된다. getChildren 메소드는 Listing 2에 나타나 있다. getElements 메소드의 경우, 호출을 getChildren 메소드로 리턴한다.


Listing 2. getChildren 구현
                
...
public Object[] getChildren(Object parentElement) 
{
    if (parentElement instanceof IFile)
    {
        String path = ((IFile)parentElement).getFullPath().toString();
        URI uri = URI.createPlatformResourceURI(path, true);
        parentElement = resourceSet.getResource(uri, true);
    }
    return super.getChildren(parentElement);
}
...
	

트리 뷰에 콘텐트를 디스플레이 하는 두 가지 중요한 단계는 디스플레이 되어야 할 자식을 뷰에 있는 객체가 언제 갖게 될지를 결정할 수 있도록 하는 것과, 자식들을 하나의 부모 객체로 제휴시키는 것이다. 이것은 뷰어가 도메인 객체들의 상태를 확장할지 또는 수축할지를 제어하게 하는 것이다. 우리 예제에서, 자식 패키지 세트를 갖고 있는 Ecore 모델로 전환할 수 있다. 같은 부모 패키지로 제휴되는 클래스 객체들은 그러한 패키지들 안에 있다. Listing 3에 이를 구현한다.


Listing 3. getParent 구현
                
...
public Object getParent(Object element)
{
    if (element instanceof IFile)
        return ((IResource)element).getParent();
    return super.getParent(element);
}

public boolean hasChildren(Object element) 
{
    if (element instanceof IFile)
        return true;
    return super.hasChildren(element);
}
...

여기에서 우리가 사용하는 리소스를 풀지 못하는 에러를 발견하게 된다. 이를 해결하려면, org.eclipse.core.resources를 Dependencies 탭 상의 필수 플러그인에 추가한다. 또한, 콘텐트 프로바이더가 뷰에 파일 리소스의 URI를 얻을 수 있도록 하려면, 플랫폼에서 리소스 세트를 사용해야 한다. private static ResourceSetImpl resourceSet = new ResourceSetImpl();MNViewContentProvider 클래스에 추가함으로써 이러한 리소스들을 얻기 위해 사용될 수 있는 하나의 정적 리소스 세트 구현을 만든다.

레이블 프로바이더는 작업을 EMF.Edit 프레임웍의 AdapterFactoryLabelProvider 클래스로 위임한다는 점에서 콘텐트 프로바이더와 같은 포맷을 따른다. 콘텐트 프로바이더와 마찬가지로, 레이블 프로바이더는 도메인 객체들을 인자로서 받아들이지만, 뷰어에서 이 객체와 제휴되어야 하는 Image 또는 String을 리턴한다. 뷰어를 커스터마이징 하려면, 이름과 아이콘을 가져오는 태스크를 위임해야 하는 때와 객체용 고유의 아이콘을 제공해야 하는 때를 프로그래밍 방식으로 제어할 수 있다. 여기에서는 커스터마이징을 하지 않기로 한다. 우리는 단지 EMF 모델이 제공하는 이미지와 텍스트만 필요하다. 레이블 프로바이더를 구현하려면, 콘텐트 프로바이더에 가졌던 같은 아이템 프로바이더 리스트로 수퍼 클래스를 호출한 다음, 객체의 이미지 또는 디스크립션에 대한 호출을 AdapterFactoryLabelProvider 수퍼 클래스로 위임한다.


Listing 4. 레이블 프로바이더
                
...
public MNViewLabelProvider() 
{
    super(MNComposedAdapterFactory.getAdapterFactory());
}

public Image getImage(Object element) 
{
    return super.getImage(element);
}

public String getText(Object element) 
{
    return super.getText(element);
}
...

테스트 하기

지금까지, 플러그인에 콘텐트 확장을 구현하는 작업을 완료했다. 뷰가 이 콘텐트 확장을 사용하도록 하려면 두 단계가 더 필요하다. 먼저, 특정 콘텐트 확장에 대한 사용을 신호로 보내는 이벤트를 정의해야 한다. 두 번째, 네비게이터 콘텐트를 뷰에 연결시켜야 한다.

<possibleChildren /><triggerPoints /> 엘리먼트를 네비게이터 콘텐트 확장에 추가함으로써, 도메인 모델을 클래스에 전개할 수 있을 때 CNF에 신호를 보내야 한다. 이 두 개의 엘리먼트들은 plug-in xml 파일에서 Eclipse 코어 확장으로서 정의하는 것만큼 쉽다. 우리 같은 경우, 네비게이터 콘텐트는 뷰어에 EMF 모델의 인스턴스인 객체가 포함될 때 호출된다. 우리는 현재 Ecore 모델만 검색하기 때문에, 리소스의 확장이 Ecore가 되는지를 검사하는 간단한 식을 만들 수 있다. 자식 엘리먼트가 확장이 뷰어에 객체에 대한 부모를 제공할 수 있을 때를 알리는데, 이 경우, EMF 모델 객체나 리소스의 인스턴스인 객체들이 이 역할을 한다.


Listing 5. 트리거 포인트 및 자식 엘리먼트
                
<triggerPoints> 
    <or>
        <and> 
            <instanceof value="org.eclipse.core.resources.IResource"/> 
            <test 
                forcePluginActivation="true" 
                property="org.eclipse.core.resources.extension" 
                value="ecore"/> 
        </and> 
    </or>
</triggerPoints> 
<possibleChildren> 
    <or> 
        <instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
        <instanceof value="org.eclipse.emf.ecore.EObject"/>  
    </or> 
</possibleChildren>
	

마지막으로, 우리가 만들었던 네비게이터를 뷰에 연결하려면, 이전에 했던 같은 방식을 사용하여 IResource 모델 콘텐트 확장을 뷰어 콘텐트 바인딩에 추가한다.

Extensions 탭에서 네비게이터 콘텐트 com.ibm.navigator.example.modelnavigator.emfModelContent를 실제 뷰에 연결하기:

  • org.eclipse.ui.navigator.viewer 엘리먼트를 확장한다.
  • viewerContentBinding 엘리먼트를 확장한다.
  • 새로운 콘텐트 확장을 만든다.
    • includes 엘리먼트를 오른쪽 클릭한다.
    • New > contentExtension을 선택한다.
    • 패턴을 navigatorContent로 설정한다. (com.ibm.navigator.example.modelnavigator.emfModelContent)
  • Save를 클릭한다.

EMF 모델 콘텐트를 공통 네비게이터로 추가하는데 필요한 모든 단계를 마쳤다. IResource 모델과 EMF Ecore 모델에서 객체를 디스플레이 할 수 있는 ModelNavigator 플러그인이 생겼다.




위로


네비게이터 테스트

EMF 프로젝트에서 테스트 하기
테스트를 실행하려면, 기존 EMF 프로젝트를 여러분의 Eclipse 워크스페이스로 가져오거나 새로운 프로젝트를 생성해야 한다. EMF Developers Guide 튜토리얼에서는 UML 모델을 가져오는 새로운 프로젝트를 생성하는 방법을 설명하고 있다. 다운로드 및 설치가 가능하다.

새로운 뷰에서 프로젝트를 실행하고 Ecore 모델을 디스플레이 하여 ModelNavigator가 작동하는지를 확인해야 한다. 테스트를 위해, Model 네비게이터에서 디스플레이 될 EMF 프로젝트를 만들어야 한다. SchoolLibrary UML 파일에 기반한 예제를 사용할 것이다. (Resources).

ModelNavigator 프로젝트를 Eclipse 애플리케이션으로서 실행한다. 그런 다음:

  • 새로운 워크벤치에서 Window > Show View > Other를 클릭하여 ModelNavigator 뷰를 디스플레이 한다.
  • Model Navigator 카테고리를 찾아서 Model Navigator View를 클릭한다.
  • OK를 클릭한다.

런타임 워크스페이스에 EMF 프로젝트 만들기:

  • File > New > Project를 클릭하여 새로운 프로젝트를 만든다.
  • Eclipse Modeling Framework 엘리먼트를 확장한다.
  • EMF project를 클릭하고 Next를 선택한다.
  • 프로젝트 이름을 SchoolLibrary로 하고 Next를 선택한다.
  • 모델 반입자로서 Rose class model을 선택하고 Next를 선택한다.
  • 모델 URI를 위해 schoollibrary.mdl 파일을 다운로드 했던 장소를 검색한다.
  • Next를 클릭한다.
  • librarySchoolLibrary 패키지를 선택한다. (그림 5)
  • Finish를 클릭한다.

그림 5.EMF 테스트 프로젝트 만들기
플러그인 프로젝트 생성하기

모든 것이 계획에 따라 진행되었다면, Model Navigator 뷰에 새로운 SchoolLibrary 프로젝트를 보게 될 것이다. 더 중요한 것은, 네비게이터 콘텐트가 기대한 대로 작동한다면, 프로젝트의 모델 디렉토리를 확장하고 네비게이터 뷰 안에 librarySchoolLibrary Ecore 파일들의 콘텐트를 통해 검색할 수 있다. 네비게이터는 그림 6에 있는 것과 비슷하다.


그림 6. ModelNavigator 테스트하기
ModelNavigator 테스트하기




위로


동기화 업데이트

지금까지 EMF 모델 콘텐트를 뷰어에 디스플레이 하는 과정을 수행했다. 에디터에서 Ecore 파일을 열고 수정을 시작할 때 어떤 일이 발생할까? 어떤 일도 일어나지 않는다. ModelNavigator는 이것이 디스플레이 하고 있는 모델에 가해진 수정 사항을 모르고, 이들을 리프레시 하지 않는다. 뷰어가 수정 사항들을 인식하게 하고 자체적으로 리프레시 하도록 하지 않는 한 리프레시 되지 않는다. 이러한 동기화를 구현하는 한 가지 방법은 리소스 수정 리스너를 콘텐트 프로바이더에 추가하는 것이다. 다음 섹션에서는 필요한 단계들이다.

리소스-수정 리스너

콘텐트 프로바이더가 모델 파일 리소스(Ecore 파일)의 수정 사항을 리스닝 하게 함으로써, 모델에 생긴 수정 사항들에 반응하도록 한다. MNViewContentProvider 클래스에 IResourceChangeListenerIResourceDeltaVisitor 인터페이스를 구현해야 한다.

resourceChanged(IResourceChangeEvent event) 메소드는 리소스가 변경되고 그 변경 사항들을 기술하는 이벤트 세트를 리소스로 전달할 때 호출된다. 이러한 변경 사항들은 리소스 투리 간 차이점을 제공한다. 이것을 사용하여 리소스 트리에서 변경 사항들을 파악할 수 있고, 변경된 리소스 유형에 기반하여 어떤 액션을 취할지를 결정할 수 있다. Listing 6처럼, resourceChanged(IResourceChangeEvent event)를 구현하는데, 이는 변경되었던 리소스 세트를 제공하고 리소스 델타로 방문할 수 있도록 해준다.


Listing 6. Resource-changed 메소드
                
...
try 
{
    IResourceDelta delta = event.getDelta();
    delta.accept(this);
} 
catch (CoreException e) 
{
...

visit(IResourceDelta delta) 메소드는 델타가 방문자를 수락한 후에 호출된다. 우리 플러그인의 경우, 변경된 리소스가 Ecore 확장을 가진 IResource 파일일 경우만 주의하면 된다. 변경된 리소스가 Ecore 모델이라면, ModelNavigator는 리프레시되어 이러한 변경 사항들을 반영해야 한다. 이를 위해서, 수정된 파일과 리소스를 얻어서, 이러한 리소스가 나타내는 모델을 재 로드 한다.


Listing 7. visit 메소드
                
...
IResource changedResource = delta.getResource();
if (changedResource.getType() == IResource.FILE 
   && changedResource.getFileExtension().equals("ecore"))
{
    try
    {
        String path = ((IFile)changedResource).getFullPath().toString();
        URI uri = URI.createPlatformResourceURI(path, true);
        Resource res = resourceSet.getResource(uri, true);
        res.unload();
        res.load(resourceSet.getLoadOptions());
    }
    catch(IOException ie)
    {
        System.out.println("Error reloading resource - " + ie.toString());
    }	
    return false;
}
return true;
...

resource-change 리스너를 사용하려면, 이것을 콘텐트 프로바이더에 추가하고, 필요할 경우 제거해야 한다. MNContentProvider 클래스에서, ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);를 구조체에 삽입함으로써 리스너를 추가한다. 또한, ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);를 클래스의 dispose 메소드에 삽입한다. 이것이 리소스 변경에 생긴 업데이트를 관리하지 않지만, 이것은 변경 사항을 핸들하는 단순한 방식이다. 콘텐트 프로바이더에서 영향을 받는 모델을 업데이트 함으로써, 그러한 엘리먼트들을 업데이트 하기 위해 이러한 모델의 의존성을 경험하지 않아도 된다. 이것은 네비게이터를 업데이트 하는 기본적인 방식이다.

모델 업데이트 테스트

Ecore 모델의 변경 사항들이 뷰어에 반영되고 있는지를 테스트 하기 위해, 애플리케이션을 재실행 하고 수정을 시작한다.

Eclipse 애플리케이션으로서 ModelNavigator 프로젝트를 실행한 다음:

  • 모델 디렉토리 밑에 schoollibrary.ecore를 검색한다.
  • 에디터에서 schoollibrary.ecore 파일을 연다.
  • schoollibrary.ecore 노드를 확장한다.
  • SchoolLibrary 패키지 노드를 오른쪽 클릭한다.
  • New Child > EClass를 선택한다.
  • Properties 탭에서, 새로운 클래스에 이름을 부여한다. (Test)
  • 파일을 저장한다.

이러한 변경을 통해서 resource-change 리스너 코드가 실행되도록 하고 ModelNavigator가 모델을 업데이트 할 수 있다. ModelNavigator 뷰 리로드도 볼 수 있다. 트리를 확장하여 schoollibrary.ecore 파일을 검색하면, 우리가 했던 변경 사항들을 보게 된다. (그림 7)


그림 7. 리소스 업데이트가 된 ModelNavigator
리소스 업데이트가 된 ModelNavigator




위로


추가 단계들

ModelNavigator에 할 수 있는 마지막이자, 비교적 쉬운 확장은 Composed Adapter Factories를 사용하는 것이다. 우리가 생성했던 네비게이터는 Ecore 모델을 디스플레이 하지만 다른 유형의 EMF 모델은 어떠한가? EMF.Edit 프레임웍이 구현되는 방식 덕택에 쉽게 할 수 있다. 적절한 어댑터 팩토리를 ComposedAdapterFactory에 추가하고 새로운 모델에 대한 트리거를 설정함으로써, 최소한의 변경으로 더 많은 도메인 모델에 대한 지원을 추가할 수 있다.

복합 어댑터 팩토리 확장하기

예를 들어, genmodel 객체를 네비게이터에 추가하려면, 제너레이터 모델 아이템 프로바이더를 콘텐트와 레이블 프로바이더가 사용하는 어댑터 팩토리 리스트에 추가한다. MNComposedAdapterFactory 클래스에서, factories.add(new GenModelItemProviderAdapterFactory());createFactoryList() 메소드에 추가한다. 수정되어야 할 모델 네비게이터의 다른 부분은 콘텐트 프로바이더가 실행될 때를 네비게이터 콘텐트에 알려주는 것이다. 트리거 포인트와 같은 리소스 확장 체크 전략을 사용한다.


Listing 8. genmodel용 트리거 포인트
                
<and> 
    <instanceof value="org.eclipse.core.resources.IResource"/> 
    <test 
        forcePluginActivation="true" 
        property="org.eclipse.core.resources.extension" 
        value="genmodel"/> 
</and> 
		

현재 트리거 밑에 새로운 트리거 식을 추가함으로써, 객체가 IResource의 인스턴스이고 Ecore의 확장을 가질 때 또는 이것이 IResource 인스턴스 및 확장 genmodel일 경우에 네비게이터 콘텐트를 연관시킨다. 이 프로젝트를 다시 실행하면 Ecore 및 Generator EMF 모델을 통해 검색할 수 있다. (그림 8) 하지만, 이것은 우리가 의도했던 단순한 리소스 업데이트 스킴이 아니므로, 업데이트는 ModelNavigator 뷰에서 다른 모델을 통해 동기화 되지 않는다.


그림 8. 다중 모델을 가진 ModelNavigator
다중 모델을 가진 ModelNavigator




위로


결론

EMF 모델 콘텐트를 뷰어에 디스플레이 할 플러그인을 구현했다. Eclipse에서 제공하는 프레임웍을 사용하여 그 과정을 단순화 하는 방법을 설명했고, 플러그인에 간단한 기능도 추가해 보았다. 이 프레임웍에 의해 나타나는 기능들을 검토만 했기 때문에, Eclipse 컴포넌트를 연구하는 것은 여러분의 몫이다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
코드os-eclipse-emf.ModelNavigator.zip9.5KBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론


필자소개

Javier Torres는 IBM Software Group의 이머징 표준 분야의 소프트웨어 엔지니어이다. 2007년 IBM에 입사했으며, 현재는 에너지 및 유틸리티 업계를 위한 표준 기반 솔루션 개발 분야를 담당하고 있다. 플로리다국제대학교에서 컴퓨터 공학 석사 학위와 컴퓨터 엔지니어링 학사 학위를 받았다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



아니오잘 모르겠음
 


 


12345
 



위로


developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의