티스토리 뷰

이 글은 Modifying EMF model using Commands를 제 관점에서 해석한 것에 지나지 않습니다혹시 문제가 된다면즉시 삭제 하도록 하겠습니다조금더 자세한 내용을 알고 싶거나오역으로 인해서 잘 이해가 가지 않는다면 아래의 레퍼런스를 참조하시기 바랍니다.

Title : Modifying EMF model using Commands

Reference : http://help.eclipse.org/ganymede/topic/org.eclipse.emf.doc/references/overview/EMF.Edit.html


 

개요

EMF.edit
는 Command framework를 제공한다. Command는 Redo Redo기능을 자동으로 구현하여 준다조금 유식한 말로 표현하자면, EMF는 Command-based editing of model을 지원한다조금 어려운 말로 들리 겠지만쉽게 말하자면 Model를 수정하는 것을 command(명령)을 통해서 하자는 말이다이러한 전략은 쉽게 Command의 실행을 취소 할 수 있고정형적으로 Model을 관리 할 있다는 것이다덕분에, Redo Undo를 별도의 노력없이 쉽게 구현 할 수 있는 장점이 있다



 

Editing domains


EMF
에서 제공되는 Command framework를 이해하기 위해서는 먼저 Editig domain을 이해해야 한다. Editing domain은 EMF model을 수정할 때 사용된다다시말해서 Commad frame work를 사용하려면, EMF모델을 수정할 때 꼭 Editing domain을 통해서 해야 한다는 말이다.

AdpaterFactoryEditingDomain이라는 Class가 있는데이것은 ItemProviderAdapterFactory를 통해서 구현이 되어 있다 Calss는 아래와 같은 2가지 Service를 제공한다.

1.     Command를 위한 factory (A factory for commands)

2.     Generic EMF.edit command(Add, Remove, Copy, etc…)를 위한 Provier

다시 말해서, Editing domain은 모델의 수정 및 쓰기를 위한 Provider(Write provider)이다이러한 관점에서 본다면 content provider와 read provider는 읽기를 위한 Provider(Read provider)가 된다.


 




모델 수정하기(Modifying a model)


모델을 수정하는 간단한 아래의 예제를 살펴보자모델을 수정하는 상황은 다음과 같다.

Company class는 Department class와 One-to-many(1…*) reference를 가지고 있다이떄, Company class에서 Department Class에 대한 참조를 삭제 하기 위해서는 아래와 같은 간단한 코드를 생각 할 수 있다 .

 

Department d = …

Company c = …

c.getDepartments().remove(d);

 

이 코드는 매우 간단하지만수정을 한다는 것 외에는 다른 기능을 제공하지 못한다반면에 다음과 같은 방법을 통해서 모델을 수정하여 보자.

 

Deaprtment d = …

Company c = …

EdintingDomain ed = …

RemoveCommand cmd =

 new RemoveCommand(ed, c, CompanyPackage.eINSTANCE.getCompany_Departments(), d);

ed.getCommandStack().excute(cmd);

 

위와 같은 방법으로 Model을 수정하면 다음과 같은 이점이 있다.

1.     Ed.getCommandStack.undo()를 호출 함으로써 수정한 내용을 취소(undo)할 수 있다.

2.     CommandStack을 보면, model이 수정되었는지를 쉽게 판단 할 수 있다따라서 쉽게 save, undo등을 활성화 시킬 수 있다.

3.     Cmd.cnaExecute()를 통해서 쉽게 command가 실행 가능한지 판단할 수 있다.



 

Editing domain을 이용하여 Command만들기



이전의 예제에서는 new를 호출 함으로써 RemoveCommand를 생성하였다이 방법은 작동은 하지만 재사용적 측면에서 본다면 비효율적이다이방법은 Company와 Department class에서만 제대로 동작한다이러한 방법 대신에, EditingDomain을 이용하여 객체(Object)의 종류에 상관 없이 삭제 할 수 있는 RemoveCommand를 만들어 보자.

EditingDomain은 createCommand()라는 command를 생성할수 있는 Factory method를 제공한다이 함수의 인터페이스는 다음과 같다.

 

Public interface EditingDomain

{

Command createCommand(Class commandClass, commandParameter CommandParameter);

}

 

이 함수를 사용하여 Command 객체를 생성하기 위해서는 먼저 CommandParameter 객체를 만들어야 한다. CommandParameter는 Command를 실행하기 위해 필요한 Parameter에 대한 정보를 가지고 있다다음으로 Create()함수를 호출 하게 되면 commandClass와 parameter를 전달 해주게 된다.

이 부분이 잘 이해가 가지 않을 것이다조금 더 자세히 설명을 하자면, Command 객체를 생성하기 위해서는 commadClass CommandParameter가 필요하다다음과 같은 상황을 가정하여 보자. RemoveCommand class를 만들기 위해서 RemoveCommand().create(editingDomain, parameter)를 호출 하게 되면, EditingDomain에서 createCommaand()를 호출하게 된다이 때, RemoveCommand commandClass가 되는 것이고, parameter commandParamer가 되는 것이다여기서 이해가 잘 가지 않는 사람은 다음 이 글의 다음 섹션인 [EditingDomain에서 createCommand()를 어떻게 처리 할까?]를 참조 하기 바란다.

이러한 방법을 통해서 removeCommand를 만들게 되면 아래와 같은 방법으로 모델을 수정 할 수 있다.

Department d = …

EditingDomain ed = …

Command cmd = RemoveCommand.create(ed, d);

Ed.getCommandStack().excute(cmd);

단순히 코드만을 본다면 별로 달라진게 없어 보인다하지만실제로는 매우 큰 변화가 있었다일전의 방법은 3(ed를 포함하면 4) parameter를 필요했던 것에 반하여이 방법은 1개의 parameter만을 필요로한다또한, RemoveCommand는 객체의 종류에 상관없이 사용 가능 하게 되었다.



 

EditingDomain에서 createCommand()를 어떻게 처리 할까?


createCommand()
가 어떻게 동작하는지 알아 보기 위해서 RemoveCommand.create()를 추적해보자.


public static Command create(EditingDomain domain, Object value)

  {

    return domain.createCommand(

      RemoveCommand.class,

      new CommandParameter(null, null, Collections.singleton(value)));

}

 

위의 code를 살펴보면, RemoveCommand.create()는 단지 editing domain createCommand()를 호출 해주는 mapper의 역할 밖에 하지 않는다.

위의 코드를 수행하면 AdpaterFactoryEditingDomain이 요청을 받아서 item provider로 정보들을 넘겨 준다참고로 이 과정은 standard delegatin pattern을 사용하였다.


public Command createCommand(Class commandClass, CommandParameter commandParameter)

  {

    Object owner = ...  //get the owner object for the command

    IEditingDomainItemProvider adapter =

      (IEditingDomainItemProvider)

        adapterFactory.adapt(owner, IEditingDomainItemProvider.class);

    return adapter.createCommand(owner, this, commandClass, commandParameter);

}

 

위의 코드를 보면 owner라는 객체가 새롭게 등장 하였다. Owner는 item provider에 접근하기 위해서 사용된다예제에서 owner는 company object가 된다. Editing domain은 삭제될 객체의 item provider의 getParent() 함수를 사용하여 owner의 객체를 얻을 수 있다.

최종적으로 createCommand()는 삭제될 객체의 parent(owner) item provider에서 처리 된다우리의 예제를 살펴보면 Company item provider에서 처리 된다. CompanyItemProvier는 다음과 같은 방법으로 createCommand()를 구현 한다.

 

public class CompanyItemProvider ...

{

   ...

   public Command createCommand(final Object object, ..., Class commandClass, ...)

   {

    if (commandClass == RemoveCommand.class)

     {

       return new RemoveCommand(object,

                                CompanyPackage.eINSTANCE.getCompany_Departments(),

                                commandParameter.getCollection());

      }

    ...

   }
}

 

이와 같은 방법으로 commandCreate()가 작동하게 된다하지만 더 좋은 방법이 있다!!

모든 item provider class는 EMF.edit가 제공하는 ItemProviderAdapter를 확장하여 구현된다. ItemProviderAdapter에는 대부분의 표준 command class를 위한 createCommand()가 구현되어 있다이것은 item provider subclass에 구현 되어있는 몇가지 간단한 함수를 호출 한다이것은 Template Method design pattern을 사용하였다.

예제에서 CompanyItemProvider는 아래의 함수만을 구현함으로써 RemoverCommand를 작동하게 할 수 있다.

 

public Collection getChildrenFeatures(Object object)

{

    return Collections.singleton(CompanyPackage.eINSTANCE.getCompany_Departments());

}

 

이 코드를 보면 알겠지만한 개 또는 더 많은 객체들을 리턴한다예제에서는 단지 department의 레퍼런스만을 리턴한다이 함수가 호출 된 후, createCommand()의 기본 구현(default implementation)은 단지 어떤 객체를 removeCommand가 사용할 지만을 정해주면 된다.

 

여기 까지 딱 반적었네요. Overriding Commands, Model change notification, composed adapter factories 3개의 섹션이 더 남아 있는데 이건 시간되는 데로 정리 해서 올리도록 하겠습니다허접하게 번역해서 올렷는데도움이 되면 좋겠네요.. ^^

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31