Courses/CS 491ab/Winter 2008/Hideyo Isaji

From CSWiki

Jump to: navigation, search

User:Hideyo

Contents

[edit] Contact Information

  • Email: hide.isaji@gmail.com

[edit] Week 1 - January 4, 2008

Introduction of CS491a. Discussed about how to use wiki and what the purpose of this class is.

[edit] Week 2 - January 11, 2008

This week, I was thinking about my project and searched some platforms that will help my project. I found some platforms that looked interesting for me. One of these is Eclipse Graphic Editor Framework(GEF). GEF


[edit] About Eclipse:

  • First of all, I would like to explain something about Eclipse. Eclipse is an open-source software framework written primarily in Java. Users can extend its capabilities by installing plug-ins written for the Eclipse software framework, such as development toolkits for other programming languages, and can write and contribute their own plug-in modules. There are a lot of kinds of frameworks on Eclipse. Here is the list of frameworks on Eclipse.


・Business Intelligence and Reporting Tools (BIRT) BIRT
・Data Tools Platform Data Tools Platform
・Graphic Editor Framework (GEF) GEF
・Eclipse Modeling Framework (EMF) EMF
・Graphical Modeling Framework GMF
・Eclipse Communication Framework Project
……
……


So far, I’m interested in Graphic Editor Framework (GEF) and Eclipse Modeling Framework (EMF).

[edit] What is GEF?

  • The GEF(Graphic Editor Framework) is an open source framework which is dedicated to providing a rich, consistent graphical editing environment for applications on the Eclipse Platform. GEF has two plug-ins which are org.eclipse.draw2d plug-in and org.eclipse.gef plug-in. In brief, Draw2d is for drawing, and GEF is for editing. If you want to just display data, you just need to use Draw2d, on the other hand, if you want to calculate your data, you need to use GEF. GEF is completely application neutral and provides the groundwork to build almost any application, including but not limited to: activity diagrams, GUI builders, class diagram editors, state machines, and even WYSIWYG text editors.


[edit] What is EMF?

  • The EMF(Eclipse Modeling Framework) is a modeling framework and code generation facility for building tools and other applications based on a structured data model. EMF consists of two fundamental frameworks: the core framework, responsible for basic code generation, and runtime, responsible for creation of Java implementation classes for a model. I found some projects that were created by using these two, GEF and EMF, platforms. This means that we can create any software taking advantage of combination of these two. (http://www.eclipse.org/articles/Article-GEF-EMF/gef-emf.html)


After I learned about these things, I started to download GEF. To download GEF, I have to have same version of installation of Eclipse. Since I had an old version of Ecilpse, I had to download a new version of Eclipse. And also, I downloaded some example of GEF and these plug-ins.


  • Next week, I am going to explore GEF more, and try to handle it well.

[edit] Week 3 - January 18, 2008

Last week, I talked about GEF. This week, I explored about this framework more and I tried to make a simple application using this framework.

Before we create a project using GEF, we have to know how to use plug-ins on Eclipse.

[edit] How to use plug-ins

There is the simplest example to start creating a plug-in project called “Hello World” plug-in project. Here is a general procedure of creating HelloWorld plug-in project.

<Creating a HelloWorld plug-in>
1. Choose [File]→[New]→[Project] from main menu on Eclipse, and choose [Plug-in Project] on 
   the new project screen page. Click [Next].
2. Enter a name for your project, then click [Next].
3. On the next page, accept all defaults and click [Next]. 
4. Make sure [Create a plug-in project using one of the templates] is selected, then select
   [Hello, World] from the list below and click [Next].
5. Accept all the defaults on this page and click [Finish]. 
6. A message that says about switching perspective may show up, if so, click [yes].

Now plug-in project will be created and switched to PDF perspective, we can create a build.xml file (manifest editor) for it to manage plug-in deployment.

  • About Manifest Editor

image:fig7.jpg

Figure 1. Tabs of Manifest Editor

  • Plug-in.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
  <extension
        point="org.eclipse.ui.actionSets"> 
     <actionSet
           label="Sample Action Set"
           visible="true"
           id="jp.sf.amateras.sample.actionSet"> 
        <menu
              label="Sample &Menu"
              id="sampleMenu">
           <separator
                 name="sampleGroup">
           </separator>
        </menu>
        <action
              label="&Sample Action"
              icon="icons/sample.gif"
              class="jp.sf.amateras.sample.actions.SampleAction"  
              tooltip="Hello, Eclipse world"
              menubarPath="sampleMenu/sampleGroup"
              toolbarPath="sampleGroup"
              id="jp.sf.amateras.sample.actions.SampleAction">
        </action>
     </actionSet>
  </extension>
</plugin>

[edit] Check plug-in operation

After you finish creating plug-in project, you can run it choosing “runtime workbench.” If your eclipse is old version like 3.0, you can find this run environment clicking [Run] → [Run As] → [Runtime Workbench].

But if you have new version of Eclipse, you have to click the line [Launch an Eclipse application] from the overview page of the manifest editor. Then, it will show a new screen of Eclipse aside from the previous Eclipse. This is the “runtime workbench.” On the menu bar, you will see the added menu [Sample Menu]. Click [Sample Menu] → [Sample Action]. Then, you will see the dialog with “Hello, Eclipse World.”


image:fig1.gif


image:fig2.jpg


  • What is “runtime workbench?”

image:fig6.jpg

Work space

Eclipse workspace is just a directory where your work will be stored.

Work bench

Workbench is the basic development environment for Eclipsed-based applications.

The runtime workbench is a second Eclipse workbench that is started when you are debugging an Eclipse plug-in that is under development. In some sense the normal Eclipse that you are running is also a 'Runtime', but 'Runtime workbench' usually means that second Eclipse during plug-in development.

References: http://www.aptana.com/docs/index.php/About_the_Eclipse_Workbench

[edit] About SWT

After I learned how to use plug-ins and stuffs, I tried to make a small sample of GEF application. GRE has two plug-ins which are Draw2D and GEF that I mentioned before. Thus, I started creating small Draw2D application.

Draw2D is a lightweight widget system hosted on a SWT Composite. A Draw2D instance consists of a SWT Composite, a lightweight system, and its contents' figures.

SWT (The Standard Widget Toolkit) is a graphical widget toolkit for the Java platform originally developed by IBM and maintained now by the Eclipse Foundation in tandem with the Eclipse IDE. It is an alternative to the AWT and Swing Java GUI toolkits provided by Sun Microsystems as part of the Java standard.

Before I create a Draw2D small application, I tried to create a small SWT application. Here is simple HelloWorld of SWT.

  • SWT Hello World
public class HelloWorld {
  public static void main(String[] args) {
   // Build display
   Display display = new Display();
   // Create shell of top level window
   Shell shell = new Shell(display);
   // set up the title of wiondow
   shell.setText("Hello World");
   // show shell
   shell.open();
   // event loop
   while (!shell.isDisposed ()){
     if (!display.readAndDispatch ()){
     display.sleep ();
     }
   }
   // dispose display
   display.dispose ();
 }
}

Result: we will see the window like below.

image:fig4.jpg

Then I created a small Draw2d applications but it doesn’t show the word “HelloWorld” which is supposed to be shown like below.

image:fig5.jpg


  • Next week:

I am going to create “Hello World” using Draw2d and GEF frameworks.

[edit] Week 4 - January 25, 2008

This week, I tried to create small “Hello World” applications using Draw2d and GEF.

[edit] Draw2d “HelloWorld”

The Graphical Editing Framework (GEF) ships with a painting and layout plug-in called Draw2D. However, Draw2D does not depend on GEF or Eclipse, we can use it independently. Draw2D is a lightweight toolkit of graphical components called figures.

Image:Clip_image002.jpg

<Figure>
Figure is simply a java object, with no corresponding resource in the operating system. 
Figures can be composed via a parent-child relationship. This figure class is implemented by
org.eclipse.draw2d.IFigure interface.

<Root Figure>
The figure at the root of the LightweightSystem. If certain properties (i.e. font, 
background/foreground color) are not set, the RootFigure will obtain these properties from 
LightweightSystem's Canvas.

<LightWeightSystem>
A LightweightSystem associates a figure composition with an SWT Canvas. 
The lightweight system hooks listeners for most SWT events, and forwards most of them to an 
EventDispatcher, which translates them into events on the appropriate figure.

Reference:

http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.draw2d.doc.isv/reference/api/org/eclipse/draw2d/Figure.html

To create a Draw2D Hello World, you need to add “swt.jar” and “draw2d.jar” file into a built path of the project.

Here is a code of Draw2d Hello World.

HelloWorld.java

public class HelloWorld {
 public static void main(String[] args) {

   // create and set shell
   Shell shell = new Shell(); 
   shell.setText("Draw2d Hello World");
   shell.setSize(200,200); // shell size
   shell.open();

   // create LightweightSystem of the shell
   LightweightSystem lws = new LightweightSystem(shell);
   
   // create root figure
   IFigure panel = new Figure();
   // add child figure(button) of the root figure
   Button button =new Button("Hello World");
   panel.add(button);
   // set Layout
   panel.setLayoutManager(new FlowLayout());
   // registration of the panel
   lws.setContents(panel);

   //same as SWT application
   Display display = Display.getDefault();
  
   while (!shell.isDisposed ()) {
     if (!display.readAndDispatch ())
       display.sleep ();
   }
 }
}

Result:

Image:fig5.jpg

Reference: http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=/org.eclipse.draw2d.doc.isv/reference/api/overview-summary.html

[edit] GEF “Hello World”

[edit] Overview of GEF

Draw2d focuses on efficient painting and layout of figures. The GEF plug-in adds editing on top of Draw2d. The purpose of this framework is to:

1.Facilitate the display of any model graphically using draw2d figures
2.Support interactions from mouse, keyboard, or the Workbench
3.Provide common components related to the above

The diagram below shows a high-level view of GEF.

image:Pic2.gif

GEF assumes you have a model you would like to display and edit graphically. To do this, GEF provides viewers (of the type EditPartViewer) that can be used anywhere in the Eclipse workbench. GEF viewers are based on a Model-View-Controller (MVC) architecture.

image:Pic1.gif


<Model>
Everything is in the model. The model is the only thing persisted and restored. 
Your application should store all important data in the model.

<View (Figures/Treeitems) >
The view is anything visible to the user. Both Figures and TreeItems can be used as view elements.

<Controller (EditPart) >
The controller is called an EditPart. Editparts are the link between the model and the view. 
They are also responsible for editing. Editparts contain helpers called EditPolicies, 
which handle the much of the editing task.
  • The flow of GEF application development
  1. Bring your own model.
  2. Define the view
  3. Making connections with Model-View-Controller
  4. Listening to the model
  5. Editing the model

Reference:

http://www.ibm.com/developerworks/library/os-eclipse-gef11/

[edit] “Hello World” Application

This simple application uses just one model which is a character “Hello World.” It uses a basic part of model, view, building of controller and creating a graphical viewer.

GEF application can operate on a view or an editor of Eclipse, or outside of Eclipse. However, most common pattern of creating GEF applications is the one that operates as editor-plugin of Eclipse. Therefore, this simple application is also created as editor-plugin of Eclipse. The first thing to do is creating the model of the editor-plugin.

I created a plug-in project as I did last week and modified the information of the plug-in project.

Here is the plugin.xml.

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin
  id="gef.example.helloworld"
  name="Helloworld PlugIn"
  version="1.0.0"
  provider-name=""
  class="gef.example.helloworld.HelloworldPlugin">

  <runtime>
     <library name="helloworld.jar"/>
  </runtime>
  <requires>
     <import plugin="org.eclipse.core.resources"/>
     <import plugin="org.eclipse.ui"/>
     <import plugin="org.eclipse.gef"/>
  </requires>
  <extension
        point="org.eclipse.ui.editors">
     <editor
           default="true"
           name="Hello World Editor"
           icon="example.gif"
           filenames="hello.world"
           class="gef.example.helloworld.HelloWorldEditor"
           id="gef.example.helloworld.editor1">
     </editor>
  </extension>
</plugin>


After this, I wrote java codes which have 3 packages, model, view and controller (editpart).

Package Model

HelloModel.java

public class HelloModel {
 private String text = "Hello World";
 public String getText() {
   return text;
 }
 public void setText(String text) {
   this.text = text;
 }
}


Packge EditPart

HelloEditPart.java

public class HelloEditPart extends AbstractGraphicalEditPart {
 protected IFigure createFigure() {
   HelloModel model = (HelloModel)getModel(); 
   Label label = new Label();
   label.setText(model.getText());
   return label;
 }
}

MyEditPartFactory .java

public class MyEditPartFactory implements EditPartFactory {
 public EditPart createEditPart(EditPart context, Object model) {
   EditPart part = null;
   // Create EditPart that corresponds a type of the model
   if(model instanceof HelloModel) 
     part = new HelloEditPart();
   part.setModel(model); // set the model to the EditPart
   return part;
 }
}
 

Package HelloWorld

Activator.java

public class Activator extends AbstractUIPlugin {
       // The plug-in ID
       public static final String PLUGIN_ID = "gef.example.helloworld";
       // The shared instance
       private static Activator plugin;
       public Activator() {
       }
       public void start(BundleContext context) throws Exception {
       	super.start(context);
       	plugin = this;
       }
       public void stop(BundleContext context) throws Exception {
       	plugin = null;
       	super.stop(context);
       }
   public static Activator getDefault() {
         return plugin;
  }
}


HelloWorldEditor .java

public class HelloWorldEditor extends GraphicalEditor {
 public HelloWorldEditor() {
     setEditDomain(new DefaultEditDomain(this));
 }
 protected void configureGraphicalViewer() {
   super.configureGraphicalViewer();
   
   GraphicalViewer viewer = getGraphicalViewer();
   // create and set EditPartFactory 
   viewer.setEditPartFactory(new MyEditPartFactory());
 }
 public boolean isDirty()  {
   return false;
 }
 public boolean isSaveAsAllowed()  {
   return false;
 }
 // add
 protected void initializeGraphicalViewer() {
    GraphicalViewer viewer = getGraphicalViewer();
    // set the root of the model
    viewer.setContents(new HelloModel());
  }
}

After all these work, you need to run “runtime workbench,” create a file and open it as editor-plugin. You will see the picture like below on your editorpane.

Result:

Image:Gef_sample8.gif


  • Next week:

I’m going to look into Draw2D and GEF more, and try to create some other applications.

[edit] Week 5 - February 1, 2008

This week I have been thinking about my project. Since I have been exploring GEF, I would like to create some new applications or plug-in using GEF. These are the ideas what I thought about below.

What can I do with GEF?

  • Create an automata diagram
  • Create a programming flow chart diagram
  • Create a class schedule diagram…

More advanced

  • Create state transition diagram using GMF (GEF and EMF)
  • Create own plug-in using PDE, GEF, EMF
  • Move on to searching about Visual Editor….


And also, following last week, I modified the GEF “Hello World” applications a little bit. Since GEF is based on a Model-View-Controller (MVC) architecture, we are able to have more models to view through the EditPart (Controller). Thus, I modified "Hello World" as below.


1. Created several models

2. Made the models visible and editabe

3. Add undo/redo feature


[edit] Operating multiple models

An editpart maintains children. Usually this corresponds to a similar containment found in the model. For example, the model may consist of a diagram containing nodes. There would then be a corresponding diagram editpart which contains multiple node editpart children. The parent-child relationship of editparts carries over into their figures. The parent's figure will contain the children's figures. You can have three separate hierarchical data structures which are approximately parallel to each other.


Image:Pict3.jpg


・ContentModel.java – To create a top-level model.

・ContentEditPart.java – EditPart (Controller) that corresponds to the top-level model.


ContentModel.java

public class ContentModel {
   private List children = new ArrayList(); // list of children model
      public void addChild(Object child) { 
	    children.add(child); // create children model
       }
      public List getChildren() {
            return children; // return children model
       }
 }

ContentEditPart.java

public class ContentsEditPart extends AbstractGraphicalEditPart {
   protected IFigure createFigure() {
     Layer figure = new Layer();
     figure.setLayoutManager(new XYLayout());
     return figure;
   }
   protected List getModelChildren() {
        return ((ContentModel) getModel()).getChildren();
   }
 @Override
 protected void createEditPolicies() {
      // install EditPolicies
      installEditPolicy(EditPolicy.LAYOUT_ROLE, new MyXYLayoutEditPolicy()
  )
 }

To set the model to visible, modified the EditPart.

HelloEditPart.java

public class HelloEditPart extends EditPartWithListener  {
  .....
 
  protected IFigure createFigure() {
    HelloModel model = (HelloModel)getModel();
    
    Label label = new Label();
    label.setText(model.getText());   
   
    // set outer frame and margin
    label.setBorder(new CompoundBorder(new LineBorder(), new MarginBorder(3)));
 
    // change background color to orange
    label.setBackgroundColor(ColorConstants.orange);
    // set background color to opaque
    label.setOpaque(true);
    
    return label;
  }
 ......
 }

At the end, to put model at different places, modified the viewer.

HelloWorldEditor.java

public class HelloWorldEditor extends GraphicalEditor {
 .....
  // add
  protected void initializeGraphicalViewer() {
	    GraphicalViewer viewer = getGraphicalViewer();
	    // set top-level model
	    ContentModel parent = new ContentModel();
	    
	    HelloModel child1 = new HelloModel();
	    // set constraint
	    child1.setConstraint(new Rectangle(0, 0, -1, -1));
	    parent.addChild(child1);
 
	    HelloModel child2 = new HelloModel();
	    child2.setConstraint(new Rectangle(30, 30, -1, -1));
	    parent.addChild(child2);
 
	    HelloModel child3 = new HelloModel();
	    child3.setConstraint(new Rectangle(10, 80, 80, 50));
	    parent.addChild(child3);
	    
	    viewer.setContents(parent);
	  }
  ......
 }

Result:

Image:Pic4.jpg

[edit] Editing model

After I created multiple models, I tried to make them editable. To make them editable, we have to create command and EditPolicy.

Image:Pict6.jpg

Command

Commands are passed around throughout editing. They are used to encapsulate and combine changes to the application's model.

EditPoliy

Editparts don't handle editing directly. Instead, they use EditPolicies. Each editpolicy is then able to focus on a single editing task or group of related tasks. This also allows editing behavior to be selectively reused across different editpart implementations. Also, behavior can change dynamically, such as when the layouts or routing methods change.


Reference:

http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.gef.doc.isv/guide/guide.html


I created a new command and EditPolicy packages and classes.

Package Command

ChangeConstraintCommand.java

public class ChangeConstraintCommand extends Command {
  private HelloModel helloModel; // model that is changed by command
  private Rectangle constraint; // changed constraint 
  private Rectangle oldConstraint; // previous constraint
  // override
  public void execute() {
    // change constraint of model
    helloModel.setConstraint(constraint);
  }
  public void setConstraint(Rectangle rect) {
    constraint = rect;
  }
  public void setModel(Object model) {
    helloModel = (HelloModel)model;
 // record precious info   
    oldConstraint = helloModel.getConstraint();
  }
 // override
  public void undo() {
    helloModel.setConstraint(oldConstraint);
  }
 }

Package EditPolicy

MyXYLayoutEditPolicy.java

public class MyXYLayoutEditPolicy extends XYLayoutEditPolicy {	
  protected Command createAddCommand(EditPart child, Object constraint) {
    // TODO automatically-generated method stub
    return null;
  }
  protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
	  // create command
	  ChangeConstraintCommand command = new ChangeConstraintCommand();
	  // set the model of editing object
	  command.setModel(child.getModel());
	  command.setConstraint((Rectangle)constraint);
	  return command;
  }
  protected Command getCreateCommand(CreateRequest request) {
    // TODO  automatically-generated method stub
    return null;
  }
  protected Command getDeleteDependantCommand(Request request) {
    // TODO  automatically-generated method stub
    return null;
  }
 }


Listener

EditPart operates the change of model, but it doesn’t have the feature that detects the result of change. To cover this problem, we can create listener to notify that model is changed. If the properties of the model changed, the model broadcast the event to all its listener and the editpart handle PropertyChangeEvent event use propertyChange method.


Here is an ablsract model class as listener.


AbstractModel.java

abstract public class AbstractModel {
  // Listener list
  private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
  // add listener
  public void addPropertyChangeListener(PropertyChangeListener listener) {
    listeners.addPropertyChangeListener(listener);
  }
  // broadcast the model changed 
  public void firePropertyChange(String propName, Object oldValue, Object newValue) {     
    listeners.firePropertyChange(propName, oldValue, newValue);
  }
  // delete listener
  public void removePropertyChangeListener(PropertyChangeListener listener) {
    listeners.removePropertyChangeListener(listener);
  }
 }

And also, to get this listener information, we have to create EditPart Listener.

EditPartWithListener.java

abstract public class EditPartWithListener extends AbstractGraphicalEditPart
  implements PropertyChangeListener {
  public void activate() {
    super.activate();
    // register itself in model as listener
    ((AbstractModel) getModel()).addPropertyChangeListener(this);
  }
  public void deactivate() {
    super.deactivate();
    // delete from model
    ((AbstractModel) getModel()).removePropertyChangeListener(this);
  }
 }

You can move those models and change their size.

Result:

Image:Pict1.jpg

[edit] Undo/Redo Feature

I also tried to create an undo/redo feature. To add this feature, we have to create editor action. To do so, modify the plugin.xml and add contributorClass into editor property. This EditorActionBarContributor class creates an empty editor action bar contributor. Here is contributor class.

MyContributor.java

public class MyContributor extends ActionBarContributor {
  public MyContributor() {
  }
  protected void buildActions() {
   	//create undo action
    addRetargetAction(new UndoRetargetAction());
    // create redo action
    addRetargetAction(new RedoRetargetAction());
  }
  public void contributeToToolBar(IToolBarManager toolBarManager) {
    // add undo action
    toolBarManager.add(
      getActionRegistry().getAction(GEFActionConstants.UNDO));
    // add redo action
    toolBarManager.add(
      getActionRegistry().getAction(GEFActionConstants.REDO));
  }
 }

After you run the workbench, you will see the undo/redo action icon on the tool bar.

Result:

Image:Pic5.jpg



  • Next week:

I’m going to try to add more actions of GEF and think about my project.

[edit] Week 6 - February 8, 2008

[edit] Automata diagram examples

This week, I kept thinking about my project. And I started searching about Automata applets since professor Russ Abbott gave me some examples how automata editor tools look like. And I searched some another examples below.


http://www.mat.unb.br/~ayala/TCgroup/MinFSAs/

http://www.cosc.canterbury.ac.nz/mukundan/thco/DFA.html


References:

http://www.belgarath.org/java/fsme.html

http://www.cs.montana.edu/~dynalab/fsa/fsa.html


With reference to these examples, I thought about features that I could add on my GEF application.

  • Start state, final state and others…
  • DFA and NFA states
  • Flexible transition
  • Run or minimize
  • Automata diagram for Turning Machine (includes left or right)


The benefit of creating Automaton editor tool using GEF is that we can edit and delete states or transition easily compared to those applets.

[edit] Createing a palette

And also, I started to create a new “AutomataGEF” project on my Eclipse to create an automata diagram editor tool. I implemented MVC architecture and editing features from GEF HelloWorld examples. Then I tried to create a palette on the editor pain. Here is a result.

Result:

Image:week6-1.jpg


Here is a code for creating this palette.


AutomataEditor.java

public class AutomataEditor extends GraphicalEditorWithPalette{
 ...
 ...
  protected PaletteRoot getPaletteRoot() {
	//PaletteRoot
	PaletteRoot root = new PaletteRoot();
 
	// Group that stores tools except Model creating
	PaletteGroup toolGroup = new PaletteGroup("Tool");
 
	// create and add 'Selection' and 'Marquee'tool
	ToolEntry tool = new SelectionToolEntry();
        toolGroup.add(tool);
        root.setDefaultEntry(tool);// tool that becomes active by default 
        tool = new MarqueeToolEntry();
        toolGroup.add(tool);
	
	// Group that stores tool which create models
	PaletteDrawer drawer = new PaletteDrawer("Component");
 
        ImageDescriptor descriptor = ImageDescriptor.createFromFile(
		                     AutomataEditor.class, "circle.jpg");
 
	// create and add 'Create State' tool 
	CreationToolEntry creationEntry = new CreationToolEntry(
		        "Create State", // String shown on Palette
		        "Create State", // toolchip
		        new SimpleFactory(StateModel.class), // Factory that creates model
		        descriptor, // show 16x16 image on palette
		        descriptor);// show 24x24 image on palette 
		    
		        drawer.add(creationEntry);
 
	// add two created group into root
        root.add(toolGroup);
	root.add(drawer);
 
	return root;
 
    }  
 ...
 ...
 }


I tried to put this image on the edior pain, but it didn't work.


  • Next week:

I'm going to try to put images on the editor pain or start exploring about EMF(Eclipse Modeling Frameworks).

[edit] Week 7 - February 15, 2008

This week, I started exploring about EMF(Eclipse Modeling Frameworks). To learn about EMF, I read a book that is about how to create plug-ins and also it includes how to use EMF and GEF stuffs. And I tried couple of examples from a book.

Here is brief overview of EMF


[edit] EMF archtecture

EMF(Eclipse Modeling Framework) The EMF project is a modeling framework and code generation facility for building tools and other applications based on a structured data model.


Image:week7-1.jpg


EMF model

When we use EMF, we create a model at first. EMF model is the model that is for handling integrated modeling by java, UML and XML.

<Core model>

Core model hold the content of models. We have to create core model at first when we use EMF.

<Generator model>

Generator model is the model for generating source codes. The generator model shows a root object, representing the whole model.


Ecore

Ecore is a model that defines a core model.


EMF generator

EMF generator generates source code according to the content of provided EMF model.

<java Emitter Template(JET)>

JET is a technology that centrals to EMF generator.

<JMerge>

JMerge enables you to customize the generated models and editors without having your changes battered by regenerating the code.


Reference:

http://www.eclipse.org/articles/Article-Using%20EMF/using-emf.html


[edit] Download Topcased

Ecore Tool from Topcased

Topcased is an open source of UML editor, but it also has Ecore tools that is an editor of EMF core model. If you use Topcased, you can create core model graphically using UML diagram tool.


Download Topcasted ecore tool


Problem occurred….

Problem

Eclipse+EMF+GEF+Topcasted

[edit] Concept of EMF unit test

After I downloaded this Eclipse, I started to try to create examples from my book.


The concept of this example is this; Let’s think about a unit test that has a class of “bank account” like below.


Account.java

/**Class of bank account*/
 public class Account {
	/**balance*/
	int balance;
	
	/**balance inquiry*/
	public int getBalance(){
		return balance;
	}
	
	/**deposit*/
	public void deposit(int amount){
		this.balance += amount;
	}
	
	public void withdraw(int amount) throws AccountException{
		if(amount > balance){
			throw new AccountException();			
		}
	this.balance -=amount;	
	}
 }


Let’s say that we want to run this unit test as this case;

The case that we deposit $1000 into a bank account that balance is $0:

  • The result of balance inquiry has to be $1000.
  • If we withdraw $3000, exception occurs.


AccountTest.java

public class AccountTest extends TestCase{
 
	Account account;
	
	protected void setUp() throws Exception{
		this.account = new Account();
	}
	
	public void testGetBalance(){
		account.deposit( 1000 );
		assertEquals("Balance doesn't match.", 100, account.getBalance());	
	}
	
	public void testWithdraw() throws AccountException{
		account.deposit( 1000 );
		
		account.withdraw(3000);
		fail("Expected exception didn't occur");
	}
 }


However, instead of writing those codes…. “Can we make an editor of the unit test using EMF, and generate a model of content of the unit test graphically?”


The procedure to create this EMF example is as below.

1. Create core model

2. Create generator model

3. Generate source code

4. Execute editor

5. Customize source code

6. Create execution tool of unit test


First of all, I tried to create the core model using Topcased.

Image:week7-2.jpg


And this is genarator model.


Image:week7-3.jpg


But I was stuck before execute editor. So many errors occurred.


  • Next week:

I’m going to reinstall Eclipse, and try to solve these problems and finish the procedure.

[edit] Week 8 - February 22, 2008

This week, I continued working on the book about EMF. Finally, I succeeded in installing “Topcased” into Eclipse europa(3.3). And I tried to complete the example of the UnitTest from the book.


Last week, I stuck in step 3 of the procedure (last week’s page), and I started from first step this week since I reinstall Eclipse and all features.


[edit] Execute editor

After generating models, we can execute the created editor. Last week, I stuck here, I couldn’t find my created editor on a workbench. But this time, I could find my “Test model.”

You can also check from “Help” → “about Eclipse platform” → “plug-in detail” if there exists your named editor.


Image:week8@1.jpg


[edit] Customize source code

We can also edit the generated source code. However, when we customize source code, we have to be careful to make sure that the code is generated or not generated. Otherwise, it is going to overwrite the customized code when it regenerates the code. To do so, you just need to put “NOT” after “@generated” tags.


As you see generated model code, there are some empty methods. Therefore, you need to add implementation by yourself.

Here are examples of implementation of the UnitTest for execution.


  • UnitTestAutomationImpl.java
/**
	 * <!-- begin-user-doc -->
	 * execute all testcase
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void doAutomation() {
		doTestCases();
	}
	
	protected boolean prepareObjects(){
		for(int i =0; i<getObject().size(); i++){
			NamedJavaObject namedObj =  (NamedJavaObject)getObject().get(i);
			namedObj.prepare();
			if(namedObj.getValue() == null)
				return false;		
		}
		return true;
	}
	
	protected void doTestCases(){
		int success = 0;
		int failure = 0;
		int invalid = 0;
		
		System.out.println("Execute UnitTest ["+getName()+"].");
		for(int i=0; i<getTestCases().size(); i++){
			if(prepareObjects()){
				//execute testCase
				TestCase testCase = (TestCase)getTestCases().get(i);
				System.out.println("Execute TestCase["+testCase.getId()+"].");
				TestResult result = testCase.doTest();
				
				switch(result.getValue()){
					case TestResult.SUCSESS_VALUE: success++; break;
					case TestResult.FAILURE_VALUE: failure++; break;
					case TestResult.INVALID_VALUE: invalid++; break;
				}				
			}else{
				System.out.println("Unable to prepare test object");
				invalid++; break;
			}
		}
		System.out.println("Execution Result of the UnitTest ["+getName()+"].");
		System.out.println(" "+TestResult.SUCSESS.getLiteral()+":"+success);
		System.out.println(" "+TestResult.FAILURE.getLiteral()+":"+failure);
		System.out.println(" "+TestResult.INVALID.getLiteral()+":"+invalid);
	}


  • TestCaseImple.java
/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public TestResult doTest() {
		for(int i=0; i<getAction().size(); i++){
			TestAction action = (TestAction)getAction().get(i);
			TestResult result = null;
			
			try{
				//execute test action
				result = action.execute();
				
				//in case of failure or invalid action, terminate test case.
				switch(result.getValue()){
				   case TestResult.FAILURE_VALUE:
				   case TestResult.INVALID_VALUE:
				   return result;  
				} 				
			}catch(Exception ex){
				System.out.println("Test Action is failed:"+ex.getMessage());
				return TestResult.FAILURE;
			}
		}
		//If there are no failure or invalid action, testCase is success.
		return TestResult.SUCSESS;
	}
  • AssertEqualAction.java
public TestResult execute(){
        //execute method call of check object
	MethodCallAction methodCall = getSubject();
	methodCall.execute();
		
	//seccess if the value is expected value compared to result
	Object result = methodCall.getResult();
	if(result instanceof Integer){
		if(((Integer)result).intValue() == getValue()){
			return TestResult.SUCSESS;
		}
		//otherwise, failure
		else{
			System.out.println("failed checking integer value ");
			return TestResult.FAILURE;
			}
		}
		
	//Invalid, if the type is not expected one	
        System.out.println("This is not type of integer" +result);
	return TestResult.INVALID;
 }

[edit] Create UnitTest Execution Tool

After we customize model code, we can create UnitTest model execution tool.

First of all, we create ".test" file that represents the UnitTest model on generated editor. Next, copy the created ".test" file into the project that has sampleBank account class. Here is an example of created UnitTest model.


Image:week8@2.jpg


It automatically creates xml file as below.


  • AccountTest.test
<?xml version="1.0" encoding="UTF-8"?>
<test:UnitTestAutomation xmi:version="2.0" 
xmlns:xmi="http://www.omg.org/XMI"   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:test="http://test" name="">
  <testCases id="testGetBalance">
   <action xsi:type="test:MethodCallAction" methodName="deposit" callTarget="//@object.0">
     <parameter xsi:type="test:IntParameter" qualifiedName="1000" intValue="1000"/>
   </action>
   <action xsi:type="test:AssertEqualsIntAction" message="1000" value="1000">
     <subject methodName="account.getBalance()" callTarget="//@object.0"/>
   </action>
 </testCases>
 <testCases id="depositTest">
   <action xsi:type="test:MethodCallAction" methodName="deposit" callTarget="//@object.0">
     <parameter xsi:type="test:IntParameter" qualifiedName="1000" intValue="1000"/>
   </action>
   <action xsi:type="test:AssertExceptionRaisesAction" exceptionTypeName="sampleBank.AccountExeption">
     <subject methodName="withdraw" callTarget="//@object.0">
       <parameter xsi:type="test:IntParameter" qualifiedName="1000" intValue="1000"/>
     </subject>
   </action>
 </testCases>
 <object qualifiedName="sampleBank.Account" name="account"/>
</test:UnitTestAutomation>


And at last, create AccountTestAutomation.java class that executes UnitTest model that is givin in command line argument into sampleBank account project.


  • AccountTestAutomation.java
/**
 * Execute UnitTest Class
 */
 
 public class AccountTestAutomation {
	/**
	 * Execute UnitTest model that is givin in command line argument.
	 * @param args
	 *  Give resource path of *.test file
	 *    to first command line argument
	 */
	
	public static void main(String[] args){
		URI resURI = URI.createURI(args[0]);
		doTest(resURI);
	}
 
	private static void doTest(URI uri) {
		//register name space[http://AutoUnit]
		TestPackage pkg = TestPackage.eINSTANCE;
		
		//read test script created on Editor
		XMIResource resource = new XMIResourceImpl(uri);
		
		try{
			resource.load(null);
		}catch(IOException e){
			System.err.println("fail to read resource. check a resource path"+uri);
			e.printStackTrace();
			return;
		}
		
		UnitTestAutomation automation = (UnitTestAutomation)resource.getContents().get(0);
		automation.doAutomation();
		
	}
}


  • Result of Execution

It was expected as below…..

If the UnitTest is success….

Execute UnitTest [AccountTest].
Execute TestCase[testGetBalance].
Execute TestCase[depositTest]
Execution Result of the UnitTest [AccountTest].
  sucsess:2
  failure:0
  invalid:0


However, I got result of invalid……


Even though I couldn’t get an expected result, I learned how to use EMF and how it works. But I figured out that understanding all about EMF is so deep and complicated, I still have so many questions about all this procedures.

After I explored EMF, I was thinking about my project. Can I implement run feature or others using EMF? If we can create this kind of UnitTest, maybe it’s possible….. But how can I create models from GEF editorpain???

My study of GEF and EMF seems to take more and more time...


  • Next week

Back to GEF, and I’m going to try to create more features and continue to think about my project.

[edit] Week 9 - February 29, 2008

This week, I tried to create following features into my GEF Automata diagram.

  • drag image into editor from palette
  • delete models
  • change the name of state from property command

Result:

Image:week9-1.jpg


[edit] Add image into editor from palette

Last time, I created a palette but I couldn’t put image onto editorpaint. This time, I tried another way to create this features.

First of all, to add model, we need to create command class.

  • CreateCommand.java
public class CreateCommand extends Command {
  private Diagram parent;
  private NodeElement element;
  private int x;
  private int y;
  
  public CreateCommand(Diagram parent, NodeElement element, int x, int y){
	  super();
	  this.parent = parent;
	  this.element = element;
	  this.x = x;
	  this.y = y;
  }
  
  public void execute() {
	  element.setX(x);
	  element.setY(y);
      parent.addChild(element);
  }
 
  public void undo() {
    parent.removeChild(element);
  }
 }


To create this command, we need to add following method into editpolicy (for creating command).


  • DiagramEditPart.java
public class DiagramEditPolicy extends XYLayoutEditPolicy {
 ...
  //add model creation command
  protected Command getCreateCommand(CreateRequest request) {
	  Point point = request.getLocation();
	  NodeElement element = (NodeElement)request.getNewObject();
	  Diagram diagram = (Diagram)getHost().getModel();
    return new CreateCommand(diagram, element, point.x, point.y);
  }
 ...
 }


And also, add method that calls editpolicy in editpart. Then it is completely created the editing architecture that I showed before.


  • DiagramEditPart.java
public class DiagramEditPart extends AbstractModelEditPart {
 ...
 protected void createEditPolicies() {
	// install EditPolicies
    installEditPolicy(EditPolicy.LAYOUT_ROLE, new DiagramEditPolicy());
 }
 ...
 }

[edit] Delete models

Creating a delete features is also same way as adding model.

  • Add delete method into command class
  • Edit or create editpolicy to create the command class
  • Edit or create editpart to call editpolicy

Here is a command that deletes model.


  • DeleteElementCommand.java
public class DeleteElementCommand extends Command {
	private Diagram diagram;
	private NodeElement element;
	
	public DeleteElementCommand(Diagram diagram, NodeElement element){
		this.diagram = diagram;
		this.element = element;
	}
	//delete children from diagram
	public void execute(){
		diagram.removeChild(element);
	}
	//undo
	public void undo(){
		diagram.addChild(element);
	}
 }


Here is editpolicy that corresponds to delete command class.


  • ElementComponentEditPolicy.java
public class ElementComponentEditPolicy extends ComponentEditPolicy {
	 public Command createDeleteCommand(GroupRequest req){
		  Diagram model = (Diagram)getHost().getParent().getModel();
		  NodeElement element = (NodeElement)getHost().getModel();
		  return new DeleteElementCommand(model, element);
	  }
 }


And install this editpolicy into editpart.


  • NodeElementEditPart.java
public abstract class NodeElementEditPart extends AbstractModelEditPart{
 ...
 protected void createEditPolicies() {
	installEditPolicy(EditPolicy.COMPONENT_ROLE, new ElementComponentEditPolicy());
 }
 ...
 }


Reference:

http://www.eclipse.org/articles/Article-GEF-diagram-editor/shape.html

[edit] Change the name of states

There are several ways to create the feature of changing name of model. The simplest way is using "property source". Add methods of property source into model that you want to edit its name.


  • EllipseModel.java
public class EllipseModel extends NodeElement implements IPropertySource{
 ...
 public IPropertyDescriptor[] getPropertyDescriptors(){
	return new IPropertyDescriptor[] {
		//edit name usint text box
		new TextPropertyDescriptor("name", "name")};
	}
	public Object getPropertyValue(Object id){
		//null check
		if(id.equals("name")){
			return name != null ? name : "";
		}
		return null;
	}
	public boolean isPropertySet(Object id){
		return id.equals("name");
	}
	public void resetPropertyValue(Object id){
	}
	public void setPropertyValue(Object id, Object value){
	    if(id.equals("name")){
		setName(String.valueOf(value));
	    }
	}
 }


  • Next week

I’m going to try to find the way how to put image file onto editorpaint, implement the connection features and also start filling out the final report.

[edit] Week 10 - March 7, 2008

This week, I searched how to use EMF model within a GEF application. And I tried to modify my GEF Automata application which is not completed yet, and looked into how it works together.

To incorporate EMF in GEF, we change following features of GEF. And most of them are changing EditPart. (because it operates model and view.)


  • Change notification mechanism (Notifier and Adapter of EMF)
  • Save and read file (Resource of EMF)
  • Create PropertySource (ContentProvider of EMF)
  • Method of model generation (Factory of EMF)


[edit] Using Adapter

To use EMF, we have to use the method “Notifier#eAdapters” to register listeners instead of JavaBeans. (but it’s just changed API)


  • AbstractModelEditPart.java
public abstract class AbstractModelEditPart extends AbstractGraphicalEditPart
  implements Adapter {
...
 private Notifier target;
 
public void activate() {
	        super.activate();
	        // add adapter
	        ((Notifier) getModel()).eAdapters().add(this);
      }
public void deactivate() {
	        // remove adapter
	        ((Notifier) getModel()).eAdapters().remove(this);
	        super.deactivate();
	  }
public Notifier getTarget() {
	        return target;
	  }
	  public boolean isAdapterForType(Object type) {
	        return type.equals(getModel().getClass());
	  }
	  public void setTarget(Notifier newTarget) {
	        this.target = newTarget;
	  }
 }


And also, instead of using PropertyChangeListener#propertChanged() method, we have to use Adapter#notifyChanged() method. (but it just differs in API)


  • NodeElementEditPart.java
public abstract class NodeElementEditPart extends AbstractModelEditPart 
implements NodeEditPart{
 ... 
	  public void notifyChanged(Notification notification) {
	      //get ID that shows which attribute was changed
	      int id = notification.getFeatureID(States.class);
	      switch (id) {
	      case EMFAutomataPackage.STATES__FIRST:
	      case EMFAutomataPackage.STATES__FINAL:
	      case EMFAutomataPackage.STATES__STATES:
	          refreshVisuals();
	      break;
	    //case    :
            //breake;
	      }
	  }
...
 }


[edit] Create PropertySource

EMF supports ItemProviderFactory and AdapterFactoryContentProvider instead of IPropertySource to display/edit value from property sheet. Thus, we don’t need to implement IPropertySource to each model.


  • AutomataDiagramEditor.java
public class AutomataEditor extends GraphicalEditorWithPalette{
...
/**connect to EMF */
	private ComposedAdapterFactory adapterFactory;
 
    public AutomataEditor() {
      setEditDomain(new DefaultEditDomain(this));
      List factories = new ArrayList();
      factories.add(new ResourceItemProviderAdapterFactory());
      factories.add(new EMFAutomataItemProviderAdapterFactory());
      factories.add(new ReflectiveItemProviderAdapterFactory());
      adapterFactory = new ComposedAdapterFactory(factories);
    }
...
/**EMF*/
  public Object getAdapter(Class type) {
        if(IPropertySheetPage.class.equals(type)) {
        PropertySheetPage propertySheetPage
          = new PropertySheetPage();
        UndoablePropertySheetEntry entry
          = new UndoablePropertySheetEntry(getCommandStack());
        //provide property source using EMF.edit 
        entry.setPropertySourceProvider(
          new AdapterFactoryContentProvider(adapterFactory) {
          public IPropertySource getPropertySource(Object object) {
            //if the model is instance of EditPart, 
        	//create IPropertySource using the model  
            if (object instanceof EditPart)
              return super.getPropertySource(
                ((EditPart) object).getModel());
 
            return super.getPropertySource(object);
          }
          protected IPropertySource createPropertySource(
            Object object, IItemPropertySource itemPropertySource) {
            return new PropertySource(object, itemPropertySource) {
              public void setPropertyValue(
                Object propertyId, Object value) {
                // for undo/redo command
                Object adapter = adapterFactory
                               .adapt(value, IItemPropertySource.class);
                if (adapter != null) {
                  IItemPropertySource propertySource
                    = (IItemPropertySource) adapter;
                  value = propertySource.getEditableValue(value);
                }
                super.setPropertyValue(propertyId, value);
              }
            };
          }
        });
        propertySheetPage.setRootEntry(entry);
        return propertySheetPage;
      }
      return super.getAdapter(type);
    }
...
 }


[edit] Create Model

Basically, we can’t instantiate model directly with EMF. So we have to create dedicated factory class of EMF model to create palette instead of using SimpleFactory.


  • AutomataFactory.java
public class AutomataFactory implements CreationFactory {
	private EClass eClass;
		    public AutomataFactory(EClass eClass) {
		    	super();
		        this.eClass = eClass;
		    }
		    /* 
		     * create through EMFAutomata Factory
		     */
		    public Object getNewObject() {
		        return EMFAutomataFactory.eINSTANCE.create(eClass);
		    }
		    public Object getObjectType() {
		    	return eClass;
		     //   return new Integer(eClass.getClassifierID());
		    }
		    protected PaletteRoot getPaletteRoot(){
		    	PaletteRoot root = new PaletteRoot();
		    	
		    	PaletteGroup group = new PaletteGroup("Tool");
		    	group.add(new PanningSelectionToolEntry());
		    	group.add(new MarqueeToolEntry());
		    	root.add(group);
		    	
		    	 ImageDescriptor descriptor = ImageDescriptor.createFromFile(
		 		        AutomataEditor.class, "/icons/circle.jpg");
		    	
		    	PaletteDrawer drawer = new PaletteDrawer("Componenet");
		    	drawer.add(new CreationToolEntry("Create States", "States", 
		    			new AutomataFactory(EMFAutomataPackage.eINSTANCE.getStates()),
		    			descriptor,
		    			descriptor));
		    	return root;
		    }
 }

Reference:

http://www.redbooks.ibm.com/redbooks/pdfs/sg246302.pdf

[edit] Final Report

[edit] Brief project description

An Automata Diagram Editor created by using Eclipse GEF (Graphical Editor FrameWorks) and EMF (Eclipse Modeling FrameWorks). Users may edit and run an automata diagram easier than any other automata applets. For example, adding states easily, changing name of states directly, flexible connections, undo/redo/delete easily, etc.

[edit] Anticipated users

The users who are studying about automata or planning to create some applications or programs which are required to draw automata diagrams.

[edit] Main objects

The primary objects are states (start, final and other states) and connections which imply transition functions (a or b, 0 or 1), etc.

[edit] Primary operations

The editor tool will enable editor to edit an automata diagram simply such as adding states and connections between states, and test whether input strings are accepted or not (run feature).

[edit] Why I am interested in this project

Since I am interested in drawing, I was looking for some frameworks that can draw something. Then, I found Graphical Editor Frameworks. Also, I was interested in CS 386 which is about automata. Thus, I came up with the idea that I could create a graphical automata editor tool using GEF frameworks.

[edit] Status

So far, I have created and learned following features.

  • Create each state from the Palette
  • Delete/Undo/Redo States models from the screen
  • Change the name of states from the property sheet
  • How to use EMF
  • How to incorporate GEF in EMF

However, I have not known about EMF well yet. Therefore, I need to continue exploring EMF and GEF more.

In addition, I am going to add connections, run and other features using EMF and GEF.