─━ IT ━─

이클립스의 이MF 모델을 사용한 GEF 응용 프로그램 생성

DKel 2021. 8. 16. 00:33
반응형
첫 번째로 EMF(Eclipse Modeling Framework)는 구조화 모델의 정의 및 해당 모델을 편집하기 위한 코드 생성 기능을 갖춘 프레임워크입니다.그러나 EMF에 의해 생성되는 모델을 편집하기 위한 에디터는 JFace 뷰어를 사용한 것으로 모델의 시각적 표현으로 적합하지 않을 수 있습니다.그래서 이 기사에서는 GEF(Graphical Editing Framework)를 사용하여 EMF모델에게 보다 그래피컬한 표현을 부여하기 위한 방법을 소개합니다.대상독자 GEF를 사용한 어플리케이션을 작성한 적이 있는 분(GEF에 대한 일반적인 설명은 생략합니다). 필요한 환경 이클립스 SDK 3.1.1
EMF SDK 2 . 1 . 1
Graphical Editing Framework (GEF) SDK 3.1.1 EMF 모델의 정의 처음에 EMF 모델을 정의합니다.작성하는 모델은, 드라마나 소설등에서 등장 인물의 관계를 나타내기 위한 「인물 상관도」를 나타내는 것입니다.이러한 그림을 나타내기 위해 다음과 같은 간단한 모델을 정의했습니다.인물간의 관계는 단방향과 양방향 및 미정의 경우를 표현할 수 있도록 되어 있습니다.이 그림을 기본으로 EMF 모델을 정의합니다.EMF모델의 정의는 몇 가지 방법으로 할 수 있는데, 여기에서는 가장 손쉬운 ′주석이 달린 자바′ 를 사용하여 모델을 정의합니다.그 외의 방법으로 EMF 모델을 정의하는 경우는, EMF SDK 에 부속되는 문서를 참조해 주세요.그림2를 기본으로 작성한 주석이 있는 Java인터페이스 및 클래스 소스는 다음과 같습니다.또한 이 모델에서 ′코어 모델′(*.ecore), ′생성 프로그램 모델′(*.genmodel)의 작성까지를 이미 작성한 소스(model_src.zip)가 이 기사 첫 링크에서 다운로드할 수 있으므로 이 파일을 전개하여 프로젝트를 워크스페이스에 Import해 주십시오.「 CorrelationDiagram . java 」
package diagram . correlation ;

import java . util . List ;

/**
* @ model
*/
public interface CorrelationDiagram {

/**
* @ model default = ′ correlation diagram ′
*/
String getName ( ) ;

/**
* @ model type = ′ RelationShip ′ containment = ′ true ′
*/
List getRelationShips ( ) ;

/**
* @ model type = ′ Character ′ containment = ′ true ′
*/
List getCharacters ( ) ;
} 「 Character . java 」
package diagram . correlation ;

import java . util . List ;

/**
* @ model
*/
public interface Character {
/**
* @ model default = ′ unknown ′
*/
String getName ( ) ;

/**
* @ model default = ′ 20 ′
*/
int getAge ( ) ;

/**
* @ model default = ′ role ′
*/
String getRole ( ) ;

/**
* @ model
*/
int getX ( ) ;

/**
* @ model
*/
int getY ( ) ;

/**
* @ model default = ′ - 1 ′
*/
int getWidth ( ) ;

/**
* @ model
*/
boolean isMale ( ) ;

/**
* @ model type = ′ RelationShip ′ opposite = ′ source ′
*/
List getSourceRelationShips ( ) ;

/**
* @ model type = ′ RelationShip ′ opposite = ′ target ′
*/
List getTargetRelationShips ( ) ;
} 「 RelationShip . java 」
package diagram . correlation ;


/**
* @ model
*/
public interface RelationShip {

/**
* @ model default = ′ outline ′
*/
String getOutline ( ) ;

/**
* @ model opposite = ′ sourceRelationShips ′
*/
Character getSource ( ) ;

/**
* @ model opposite = ′ targetRelationShips ′
*/
Character getTarget ( ) ;

/**
* @ model
*/
RelationShipType getRelationShipType ( ) ;
} 「 RelationShipType . java 」
package diagram . correlation ;

/**
* @ model
*/
public class RelationShipType {

/**
* @ model name = ′ Undecided ′
*/
public static final int UNDECIDED = 0 ;

/**
* @ model name = ′ OneWay ′
*/
public static final int ONE _ WAY = 1 ;

/**
* @ model name = ′ TwoWay ′
*/
public static final int TWO _ WAY = 2 ;

}}모델을 편집하기 위한 에디터 생성에서는 생성 프로그램 모델(correlation.genmodel)을 사용하여 인물상관도 모델을 편집할 에디터 플러그인을 생성해 보겠습니다.이것은 매우 간단합니다.먼저 패키지 탐색기에서 correlation.genmodel 파일을 더블 클릭하여 열어 주세요.트리 형식으로 표시되고 있는 생성 프로그램·모델의 루트·모델을 오른쪽 클릭해[모델·코드의 생성]을 실행합니다.그러면 프로젝트에 몇 가지 코드와 플러그인 매니페스토 파일 등이 추가됩니다.또, 조금 전 추가한 인터페이스나 클래스에도 변경이 가해집니다.이 조작에 의해서 단지 인터페이스와 enum클래스만 정의한 프로젝트가 실제로 동작하는 모델 플러그인 프로젝트가 됩니다.또한 이 때의 변경에 의해서 Character 인터페이스와 Correlation Diagram 인터페이스에 경고가 표시되는데, 이러한 인터페이스 내에서 사용하던 java.util.List가 이것을 확장한 EList로 변경됨에 따라 List의 Import 선언이 미사용이 되기 때문입니다.생성된 모델의 구현 클래스는 모델의 속성이나 참조 등이 변경되었을 때 알림을 하는 기능이 추가됩니다.이러한 구현 클래스는 동시에 생성되는 팩토리 클래스(Correlation Factory 및 Correlation Factory Impl)를 통해서만 작성할 수 있습니다.또한 모델의 형이라던가 속성 형을 특정하기 위한 정수를 포함한 패키지(Correlation Package 및 Correlation Package Impl)도 생성됩니다.조금 전 모델·코드를 생성했을 때와 같은 순서로,[편집 코드의 생성]을 실행해 주세요.그러면 워크스페이스에 ′diagram.correlation.edit′이라고 하는 프로젝트가 추가됩니다.이 프로젝트는 EMF 모델을 편집하기 위한 어플리케이션을 만드는 경우에 필요한 기능을 추가하기 위한 것입니다.예를 들어 JFace 뷰어를 사용해 UI를 작성할 때 이 프로젝트에 포함되는 XXXItem Provider는 각 모델에 대한 컨텐츠 프로바이더나 라벨 프로바이더로서 기능합니다.또한 뷰어에서 모델이 선택된 경우에는 모델에 프로퍼티 소스 지원을 추가하여 모델의 속성을 이클립스의 ′프로퍼티′ 뷰로 편집할 수 있도록 합니다.조금 전 모델 코드를 생성했을 때와 같은 순서로, 「에디터 코드의 생성」을 실행해 주세요.그러면 워크스페이스에 ′diagram.correlation.editor′라고 하는 프로젝트가 추가됩니다.이 프로젝트는 정의한 모델을 편집하기 위한 에디터와 신규로 모델을 작성하기 위한 마법사가 포함되어 있습니다.이제 모든 준비가 되었으니 생성된 에디터를 실제로 사용해 보겠습니다.우선 런타임 워크벤치를 기동합니다.런타임 워크벤치의 메뉴에서 [신규] → [기타]와 선택하고, 그 후 [샘플 EMF 모델 작성 마법사]→[Correlation Model]로 선택합니다.다음으로, 적당한 파일명과 부모 폴더를 지정해, 위저드의 마지막 페이지에서[Model Object]에[Diagram]을 지정하고 위저드를 종료합니다.이 에디터에서는 루트 모델인 [Diagram] (Correlation Diagram)을 오른쪽 클릭하고 [New Child] → [Character] 로 함으로써 ′Character′ 모델을 추가할 수 있습니다.′Relation Ship′ 을 추가하는 경우도 마찬가지입니다.또, pop-up·메뉴로부터[Show properties View]를 선택하면[프로퍼티]뷰를 표시할 수 있습니다.뷰에서는 에디터에서 모델을 선택했을 때 그 모델의 속성을 편집할 수 있습니다.GEF를 사용한 EMF 모델·에디터의 작성 지금까지의 작업으로, 일단 인물 상관도를 나타내는 모델을 편집하는 에디터가 완성되었습니다만, 이 에디터에서는 인물 사이의 관계를 보기 어렵고, UI 에는 모델의 속성 중 1 개 밖에 표시되지 않기 때문에, 별로 사용하기 좋은 것은 아닙니다.거기서, 모델을 편집하는 에디터로서 GEF의 그래피컬·뷰어를 사용한 에디터를 도입합니다.GEF를 사용하면, 인물 사이의 관계를 connection으로 나타낼 수 있고, 필요한 정보를 모두 표시할 수도 있습니다.또, EMF모델은 변경을 통지하는 기능을 갖추고 있고, EMF모델은 GEF어플리케이션에서 취급하기에 적합하다고 말할 수 있습니다.GEF를 사용한 인물 상관도 모델·에디터·프로젝트(correlation_GEF_src.zip)를, 기사 첫머리의 링크에서 다운로드할 수 있습니다.이 에디터를 동작시키기 위해서는 워크스페이스에 「diagram.correlation」 및 「diagram.correlation.edit」프로젝트가 필요합니다(이들 프로젝트는 조금 전에 작성한 「모델·코드」와「편집 코드」입니다).먼저, GEF 를 사용한 인물 상관도 에디터가 어떠한 것인지를 확인하기 위해서 실행해 보겠습니다.런 타임 워크 벤치를 실행하고, 패키지 익스플로러에서 아까 만든 ′*. correlation′파일을 오른쪽 클릭하고[애플리케이션으로부터 열기]→[인물 상관 도표 에디터]으로 선택합니다.그러면 아래 그림과 같은 에디터가 열릴 겁니다.이 인물상관도 에디터에서는 EMF가 생성하는 디폴트의 것에 비해 인물간의 관계를 상당히 쉽게 파악할 수 있다고 생각합니다.EMF모델의 읽기와 저장 EMF모델은 앞서 작성한 기본 에디터를 보면 알 수 있듯이 트리구조로 되어 있습니다.이것은 작성한 「*.correlation」파일을 텍스트 에디터로 펼쳐 보시면 잘 알 수 있을 것입니다.따라서 읽어들이는 모델은 루트 모델인 「Correlation Diagram」이라는 것이 됩니다.「 GraphicalCorrelationEditor . java 」 の 一部
public class GraphicalCorrelationEditor
extends GraphicalEditorWithFlyoutPalette {
...
private Resource resource; // 모델을 포함하는 파일
private CorrelationDiagram diagram; // 루트 모델
...
protected void setInput ( IEditorInput input ) {
super . setInput ( input ) ;

// 에디터 입력에서 파일 가져오기
IFile file = (( IFileEditorInput ) input ) . getFile ( ) ;

setPartName ( file . getName ( )) ;

ResourceSet resourceSet ;
if ( resource == null )
resourceSet = new ResourceSetImpl ( ) ;
else
resourceSet = resource . getResourceSet ( ) ;
URI uri = URI . createPlatformResourceURI ( file . getFullPath ( )
. toString ( )) ;
// 리소스 로드
resource = resourceSet . getResource ( uri , true ) ;
// 루트 및 모델 취득
diagram
= ( CorrelationDiagram ) resource . getContents ( ) . get ( 0 ) ;
}
...
} EMF 모델을 읽기 위해서는 먼저 자원(Resource)을 취득해야 합니다.리소스는 EMF모델을 포함한 파일(여기서는 *.correlation)에 대응합니다.또한 리소스는 리소스 세팅(Resource Set)에 의해 작성/관리됩니다.여기에서는 이미 리소스 파일(*. correlation)이 에디터 입력으로 건네지므로 ResourceSet #getResource 메서드에 파일의 경로를 URI로 변환해 주고 리소스를 취득하기만 하면 됩니다(로드도 동시에 이루어집니다).리소스를 로드하면 루트 모델을 취득할 수 있습니다.루트 모델은 자원의 컨텐츠·리스트의 선두에 있습니다.리소스를 저장하려면 Resource#save 메서드를 사용합니다.「 GraphicalCorrelationEditor . java 」 の 一部
public class GraphicalCorrelationEditor
extends GraphicalEditorWithFlyoutPalette {
...
private void performSave ( IFile file ) {
URI uri = URI . createFileURI ( file . getFullPath ( ) . toString ( )) ;

if ( ! uri . equals ( resource . getURI ( )))
resource.setURI(uri);// 리소스의 URI 변경하기

WorkspaceModifyOperation operation
= new WorkspaceModifyOperation ( ) {

public void execute ( IProgressMonitor monitor ) {
try {
// 자원 저장
resource . save ( Collections . EMPTY _ MAP ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
}
};

try {
// 저장 운영 실행
new ProgressMonitorDialog ( getSite ( )
. getShell ( )) . run ( true , false , operation ) ;
} catch ( InvocationTargetException e ) {
e . printStackTrace ( ) ;
} catch ( InterruptedException e ) { }

// 명령어 및 스택 갱신
getCommandStack ( ) . markSaveLocation ( ) ;
}
...
}save 메서드는 저장 방법을 지정하기 위한 옵션을 전달할 수 있습니다.지정할 수 있는 옵션은 많이 있습니다.예를 들어 인코딩을 변경하고 싶은 경우는 아래와 같이 합니다.그 밖의 옵션에 대해서는 EMF의 API 문서를 참조해 주십시오.코드 예시
Resource resource …
HashMap options = new HashMap ( ) ;
options . put ( XMLResource . OPTION _ ENCODING , ′ ISO - 8859 - 1 ′ ) ;
resource.save(options); 모델과 EditPart를 지원하는 GEF 어플리케이션에서는 일반적으로 모델의 구조를 EditPart를 지원합니다.EMF 모델은 루트·모델을 취득하면 계층을 더듬어 갈 수 있기 때문에, 간단하게 이것을 실현할 수 있습니다.「 DiagramEditPart . java 」 の 一部
public class DiagramEditPart extends BaseGraphicalEditPart {
...
private CorrelationDiagram getCorrelationDiagram ( ) {
return ( CorrelationDiagram ) getModel ( ) ;
}
...
protected List getModelChildren ( ) {
// Character 취득
return getCorrelationDiagram ( ) . getCharacters ( ) ;
}
...
}}또한 인물간의 관계를 나타내는 ′RelationShip′ 모델은 connection으로 표현하고 싶기 때문에 아래와 같이 하겠습니다.『캐릭터편집Part.java』가 있습니다.
public class CaracterEditPart는 BaseGraphicalEditPart를 확장합니다.
NodeEditPart { 구현
...
개인 문자 getCharacter() {
return(문자) getModel();
}
...
보호된 목록 getModelSourceConnections() {
getCharacter().getSourceRelation을 반환합니다.배송();
}

보호된 목록 getModelTargetConnections() {
getCharacter().getTargetRelation을 반환합니다.배송();
}
...
}あとは、これらのeditpartをeditpartfactoryでモデルと対応付けるだけです。モデルの変更通知gefアプリケーションでは、モデルが変更された場合、editpartで変更通知を受け、ビュー、またはeditpartの構造を
공용 추상 클래스 BaseGraphicalEditPart
AbstractGraphicalEditPart 확장
{ 어댑터 구현
개인 통지자 대상;

공개 보이드 활성화 {
super.vmd;
// アダプターを登録
((Notifier) getModel()입니다.eAdapter().add(이것);
}

public void 비활성화 {
// アダプターの除去
((Notifier) getModel()입니다.eAdapter().제거(이것);
super.competate;
}

공개 알림 getTarget() {
반환 대상;
}

public boolean isAdapterForType(개체 유형) {
type.equals(getModel().getClass();
}

publicvoid setTarget(Notifier newTarget) {
대상 = 새 대상;
}

public void notify변경됨(알림 알림) {
// このメソッドをオーバーライドして変更通知を受ける
}
}ここでは、editpartクラスでadapterインターフェイスをインプリメントして自身をアダプターとして登録していますが、abstractconnectioneditpartクラスのサブクラス(relationshipeditpart)では、adapter#gettargetメソッドがconnectioneditpart#gettarget()メソッドと重複してしまうので上記コードとは異なる方法でアダプターを登録しています。これで、editpartでモデルの変更通知を受け取るこventtypeメソッドによって取得できます。各editpartでは、この情報を利用して更新処理を行います。「diagrameditpart.java」の一部
공용 클래스 다이어그램EditPart가 BaseGraphicalEditPart {}을(를) 확장합니다.
...
public void notify변경됨(알림 알림) {
inttype = notification.getEventType();

스위치(유형) {
사례 통지.추가:
사례 통지.ADD_MANY:
사례 통지.제거:
사례 통지.제거_MANY:
refreshchildren();//子モデルの追加、または削除が行われた
깨지다;
사례 통지.세트:
비주얼 새로 고침();
깨지다;
}
}
...
}また、変更された部分のみを更新したい場合は、notification オブジェクトのgetfeatureID()는 CharacterEditPart.java입니다.
public class CaracterEditPart는 BaseGraphicalEditPart를 확장합니다.
NodeEditPart { 구현

public void notify변경됨(알림 알림) {
// どの属性が変更されたかを示すidの取得
intid = notification.getFeatureID(문자.클래스);
스위치(ID) {
case correlation Package.문자__X:
case correlation Package.문자__Y:
case correlation Package.문자__폭:
비주얼 새로 고침();
깨지다;
case correlation Package.문자__나이:
새로 고침 기간();
깨지다;

}

}
...
}기능 가져오기idメソッドには「character.class」が渡されていますが、これは多重継承のモデルを使用する場合に、idの重複を避けるために必要です。モデルの作成emfでは、モデル·クラスのインスタンスを直接作成(new)せずに、「パッケージ名+factory」というファクトリーを使用して作成することを推奨しています。「cor
공용 클래스 상관 관계 모델 팩토리에서 CreationFactory {을(를) 구현합니다.
사설 EC 클래스;

공개 상관 관계 모델 팩토리(EClassClass) {
이거.eClass = eClass;
}

/*
* ファクトリーを通して作成する
*/
공용 개체 getNewObject() {
return 상관 관계 공장.eInstance.create(eClass);
}

공용 개체 getObjectType() {
새 정수(eClass.getClassifierID())를 반환합니다.
}
}このファクトリーのコンストラクタに渡すeclassは以下のようにして取得できます。コード例
EC 클래스 문자EClass = 상관 관계 패키지.einstance.getcharacter();プロパティー·ソース·サポートの追加前述のとおり、emfが生成した「編集コード」には、各emfモデルに対して、eclipseの[プロパティー]ビューを使用するためのプロパティー·ソース『그래픽 상관 편집기.java』
공용 클래스 그래픽 상관 편집기
그래픽 편집기를 확장합니다.Flyout Palette 사용 {
...
전용 컴포지트 어댑터 공장;
...
공용 그래픽 상관 편집기() {
SetEditDomain(새 DefaultEditDomain(이));

목록 공장 = 새 배열 목록();
factory.add(새 리소스 항목 공급자 어댑터 팩토리());
factors.add(새 상관 관계)ItemProviderAdapterFactory();
factory.add(새 반사 항목 공급자 어댑터 공장());

어댑터 공장 = 새 구성 어댑터 공장(공장);
}
...
공용 개체 getAdapter(클래스 유형) {
// プロパティ·ビュー·ページの作成
if(I 속성)SheetPage.class.equals(유형) {
속성시트 페이지 속성시트 페이지
= 새 속성시트 페이지();
실행 취소 가능한 속성시트 항목
= 새로운 실행 취소 가능 속성SheetEntry(getCommandStack();

// emf.editを使用してプロパティ·ソースを提供する
entry.setPropertySourceProvider()
새 AdapterFactoryContentProvider(AdapterFactory) {

공용 IPpropertySourcegetPropertySource(개체 개체) {
// editpartが選択された場合はそのモデルを使用して
// IPpropertySource는 다음과 같습니다.
if(EditPart의 객체 인스턴스)
super.getPropertySource를 반환합니다.
((부품 편집) 객체).get Model();

super.getPropertySource(개체)를 반환합니다;
}

보호된 IPpropertySource createPropertySource()
개체 개체, IItemPropertySource 항목PropertySource) {
새 PropertySource(개체, 항목PropertySource) 반환 {
public void setPropertyValue()
개체 속성 ID, 개체 값) {
// アンドゥ/リドゥ·コマンド用の対策
개체 어댑터 = 어댑터 공장
.adapt(값, IItemPropertySource.class);
if(수정 != null) {
IItemPropertySource 속성 원본
= (IItemPropertySource) 어댑터;
value = propertySource.getEditableValue(값);
}

super.setPropertyValue(propertyId, 값);
}

};
}
});

재산시트 페이지.setRootEntry(항목);

재산을 반환하다시트 페이지;
}

super.getAdapter(유형)를 반환합니다;
}
...
}실행 불가능한 속성시트 항목 、 sheet sheetgefアプリケーションが標準で提供するプロパティー·シート·エントリーで、[プロパティー]ビューで値が変更されたときに、内部的にコマンドを作成し、gefのコマンド·スタックにそのコマンドを追加しまpartからプロパティー·ソースを作成する必要があります。そこで、undoablepropertysheetentryクラスのgetpropertysourceメソッドをオーバーライドして、editpartが持つemfモデルをプロパティー·ソースの作成に使用するようにします。あとは、プロパティー·ソース·プロバイダーとして追加されたadapterfactorycontentproviderに含まれる、correlationItemProviderAdapterFactory▼emfモデルからプロパティー·ソースを作成してくれます。これで、emfが生成する編集コードを使用してgefアプリケーションにプロパティー·ソース·サポートを加えることができました。完全なgefemfとgefを組み合わせて利用したアプリケーションは数多く見られます。emfを使用すれば、モデルの定義や操作、およびシリアライゼーションなどについての機能を手軽に手に入れることができまし、geapiリファレンス
IBM RedBook ′그래픽 편집 프레임워크 및 Eclipse 모델링 프레임워크를 사용한 Eclipse 개발′
이클립스 위키
IBM developerWorks eEclipse Modeling Framework モ回: 回1回
IBM developerWorks ′Eclipse Modeling Framework를 사용한 모델, 파트 1′
IBM developerWorks ′Eclipse Modeling Framework를 사용한 모델, 파트 2′
IBM developerWorks ′Model with Eclipse Modeling Framework, Part3′는 Eclipse CVS에 포함되어 있으며, EMF→GEF에 포함되어 있거나 eclipse.ge.예: ediagram에 포함되어 있습니다.
반응형