# Fragen zu EMF



## Gast2 (9. Sep 2010)

Hallo zusammen,

hätte ein paar Fragen zu EMF. Ich habe gerade das Tutorial durchgemacht Eclipse Modeling Framework (EMF) - Tutorial. Mir ist jetzt noch nicht ganz klar was ich mit den ganzen generierten Klassen/Models anstellen kann:
1. Gibt es die Möglichkeit aufbauend auf meinem Model einen Editor für den RCP generieren zu lassen, damit der User ein Objekt mit den Attributen anlegen kann? Oder muss die Eingabe GUI + Databinding weiterhin manuell gemacht werden?
2. Falls 1. ja kann man eigene widgets für die Eingabefelder verwenden?
3. Gibt es irgendwas um die Klassen mit EclipseLink o.ä. persistent zu machen? Oder muss ich dafür nochmal neue Klassen anlegen um die Annotations zu setzen oder kann ich dafür die generierten verwenden?

Danke


----------



## code404 (9. Sep 2010)

Zu 1: Entweder du nimmst den EMF editor (im genmodel "generate editor code"). Wenn du in den Properties deines genmodel unter "Edit->Rich Client Platform -> true" angibst, wird dir ein kompletter RCP generiert.
Andere Möglichkeiten sind GEF / GMF zu verwenden.

Zu 3. Bei EMF ist alles für die Persistens schon dabei: Schaust du hier: Eclipse Modeling Framework (EMF) - Persisting models via XMI


----------



## Gast2 (9. Sep 2010)

code404 hat gesagt.:


> Zu 1: Entweder du nimmst den EMF editor (im genmodel "generate editor code"). Wenn du in den Properties deines genmodel unter "Edit->Rich Client Platform -> true" angibst, wird dir ein kompletter RCP generiert.


Ja hab ich versucht, aber der MultiPageEditor und die ganzen Views ist ja viel zu viel. 
Und irgendwie bekomm ich den Editor nicht in mein aktuellen RCP rein. Wenn ich eine Klasse Person mit Attributen habe bräuchte ich nur sowas wie die PropertyView als EingabeFormular um verschiedene Personen anzulegen. Der rest wäre overkill. Außerdem hab ich auch keine Möglichkeit gefunden eigene widgets für die Textfelder anzugeben.




code404 hat gesagt.:


> Zu 3. Bei EMF ist alles für die Persistens schon dabei: Schaust du hier: Eclipse Modeling Framework (EMF) - Persisting models via XMI


Muss ich mir mal anschauen, aber so wie ich das sehe speicher er alles in Dateien ab, ich müsste alles in eine DB speichern.


----------



## Gast2 (9. Sep 2010)

Hier hab ich was gefunden zu persitieren:
EMF/Teneo/EclipseLink/Understanding JPA Mapping - Eclipsepedia


> Mapping in XML vs. Annotations
> 
> If you are generating your mappings from Ecore an orm.xml file will be generated. If you are manually mapping then you should do all mapping in XML. The use of annotations is not recommended as they will be lost if/when you regenerate your model.



Mal schauen wie das orm.xml generiert bekomme^^...


----------



## Wildcard (11. Sep 2010)

Was meinst du mit den ganzen Views? Der EMF Editor ist nur ein Editor mit Anbindung an die Outline und die Properties View, also das was du dir vorgestellt hast. Ob der Editor MultiPage oder Single Page ist kannst du im Genmodel einstellen.
Wenn dir der Editor nicht zusagt (der ist gedacht um schnell sein Modell testen zu können, nicht unbedingt für Endanwender), dann kannst du wahlweise den Editor customizen, oder einen komplett neuen Editor schreiben. Dank des generierten EMF Edit Codes ist das ein Kinderspiel, da bereits Property View Support vorhanden ist, Content Provider und Label Provider generiert wurden, Notification Support vorhanden ist und Commands bereitstehen um Undo/Redo Funktionalität hinzuzufügen.


----------



## Gast2 (11. Sep 2010)

Wildcard hat gesagt.:


> Was meinst du mit den ganzen Views? Der EMF Editor ist nur ein Editor mit Anbindung an die Outline und die Properties View, also das was du dir vorgestellt hast. Ob der Editor MultiPage oder Single Page ist kannst du im Genmodel einstellen.
> Wenn dir der Editor nicht zusagt (der ist gedacht um schnell sein Modell testen zu können, nicht unbedingt für Endanwender), dann kannst du wahlweise den Editor customizen, oder einen komplett neuen Editor schreiben. Dank des generierten EMF Edit Codes ist das ein Kinderspiel, da bereits Property View Support vorhanden ist, Content Provider und Label Provider generiert wurden, Notification Support vorhanden ist und Commands bereitstehen um Undo/Redo Funktionalität hinzuzufügen.



Ja dachte vielleicht dass es schon was "fertiges" gibt. Okay muss mal schauen was ich davon verwenden kann find die generierten View und Editor ein bischen unübersichtlich^^


----------



## Gast2 (15. Sep 2010)

Also ich hab nochmal 2 Fragen zu EMF und Teneo:
1. Ist das Metamodel (ecore) immer in dem plugin wo auch der generierte Code vom genmodel ist?
2. Wenn man aus dem ecore Model sich das orm.xml generieren lässt hat man 4 required bundels mehr in seinem plugin die man später man eigentlich gar nicht benötigt? Geht das irgendwie elegeanter?
Oder gibt es was besser als Teneo?


Gruß


----------



## Wildcard (15. Sep 2010)

> 1. Ist das Metamodel (ecore) immer in dem plugin wo auch der generierte Code vom genmodel ist?


Nein, du kannst im genmodel einstellen wohin der Code generiert werden soll.


> 2. Wenn man aus dem ecore Model sich das orm.xml generieren lässt hat man 4 required bundels mehr in seinem plugin die man später man eigentlich gar nicht benötigt? Geht das irgendwie elegeanter?
> Oder gibt es was besser als Teneo?


Ich habe Teneo noch nicht benutzt, daher kann ich dir nicht allzuviel dazu sagen. Aber woher weißt du das du die Plugins nicht benötigst? Du hast vielleicht keine statische Abhängigkeit im Code, aber da es vermutlich seinen Grund hat das diese Dependencies hinzugefügt wurden, würde ich vermuten das sie zur Laufzeit vorhanden sein müssen.


----------



## Gast2 (16. Sep 2010)

Wildcard hat gesagt.:


> Nein, du kannst im genmodel einstellen wohin der Code generiert werden soll.



Ja das hab ich im genmodel gesucht finde nur das package wo der Code hingeneriert wird, wie heißt die Properties wo ich das Plugin einstellen kann?
Aber da Teneo das ecore model neben den generierten Code brauch ist es eigentlich eh egal.



Wildcard hat gesagt.:


> Ich habe Teneo noch nicht benutzt, daher kann ich dir nicht allzuviel dazu sagen. Aber woher weißt du das du die Plugins nicht benötigst? Du hast vielleicht keine statische Abhängigkeit im Code, aber da es vermutlich seinen Grund hat das diese Dependencies hinzugefügt wurden, würde ich vermuten das sie zur Laufzeit vorhanden sein müssen.



Soweit ich gesehen hab werden die Plugins benötigt um die orm.xml zu generieren. Aber zum Code sehe ich keine Abhänigkeiten, falls das so ist könnte ich die Plugins ja optional deklariern oder?

Kennst du noch ein anderes Framework als Teneo? Das Framework sieht noch nicht ausgereift aus, wenn man irgendwelche Plugin vergisst zum generieren bekommt man als user nachricht einen NPE Error^^...
Schon mal was mit CDO gemacht?


----------



## Wildcard (17. Sep 2010)

Neben Teneo fällt mir spontant CDO und SDO ein. Übrigens, nur weil das Tooling nicht narrensicher ist, heißt nicht, dass der Runtime Teil nicht ausgereift ist.


----------



## Gast2 (18. Sep 2010)

Wildcard hat gesagt.:


> Neben Teneo fällt mir spontant CDO und SDO ein. Übrigens, nur weil das Tooling nicht narrensicher ist, heißt nicht, dass der Runtime Teil nicht ausgereift ist.



Ja hab ich auch nicht behauptet nur ist es mal milde ausgedrückt nich optimal wenn du alles so einstellst wie in der Anleitung beschrieben und du immer eine NPE als Fehlermeldung bekommst, damit kann man wenig Anfangen um den Fehler zu suchen. Macht die Sache halt schwer bedienbar...
Aber das orm.xml wo Teneo generiert sieht auf dem ersten Blick ganz ordentlich aus. Schade, dass die Docu noch so rar ist, hab mir mal paar Bsp. aus dem SVN ausgecheckt um so zu sehen was man alles einstellen kann.

Die Frage ist jetzt wenn ich meine Klassen mit EMF generieren lasse und mit Teneo die orm.xml generien lasse. Dann sind meine Peristenz Klassen und meine Modelklassen genau die gleichen Klassen. Ist das sinvoll? Oder wie sieht das bei euch in der Firma aus?

Ja CDO hab ich mir auch angeschaut nur noch nicht so ganz gecheckt was ich damit machen kann. Was der Vorteil davon ist.

SDO werd ich mal suchen.


----------



## Gast2 (22. Sep 2010)

Okay noch ne kleine Arichtektur Frage dazu. Ich lass mein ganzes Model nur mit EMF generieren und mit Teneo die orm.xml generieren. Jetzt sind ja die Objekte welche ich peristiere und meine model objekte die gleichen ist das in Ordnung?


----------



## Wildcard (22. Sep 2010)

Klar, was ist denn daran auszusetzen?


----------



## Gast2 (22. Sep 2010)

Mhm ja ich kannte es bis jetzt nicht so ...
Kannte bis jetzt Klassen, die peristiert werden (DBObject) und drum herum die Modeklassen(DBObjectModel), die die Notification übernehmen und zueinander ne 1:1 Beziehung haben.

EDIT: 1. Gibt es eigentlich irgendwo ein Tutorial für Undo/Redo für EMF?
2. Wie füge ich einer EList einen Eintrag hinzu?


----------



## Gast2 (13. Okt 2010)

Also das mit dem Undo/Redo klappt irgendwie nicht so recht.

Ich habe ein einfaches Aufnahme Formular für alle Attribute.
Also Beispiel habe ich jetzt mal ein Textfeld rausgesucht, welches ich mit JFace EMF-Datbinding binde.
Ich hab mir dazu mal den Part hier druchgelesen, aber komme nicht so recht klar damit.
WebSphere Application Server Version 6.0.2.

Ich weiß dass ich jetzt AdapterFactoryEditingDomain benötige, dafür hab ich den Code aus dem generierten Editor geklaut. Aber der CommandStackListener wird nie aktiv. In dem Artikel wird nur erklär wie ich ein Command ausführe aber wie funktioniert das mit dem Databinding da führe ich ja keine Commands selber aus??????:L... Finde die Undo/Redo API sehr verwirrend habe ich noch nicht ganz durchleuchtet wie das genau klappt. Wenn jemand ein paar Tipps/Erklärungen hätte wäre sehr nett...



```
ublic void createPartControl(Composite parent) {
		verwaltung = VerwaltungFactory.eINSTANCE.createVerwaltung();
		parent.setLayout(new GridLayout());
		
		lastName = new Text(parent, SWT.BORDER);
		lastName.setMessage("Name eingeben");

		GridDataFactory.fillDefaults().applyTo(lastName);
		bindValue();
		initializeEditingDomain();
	}

	private void bindValue() {
		m_bindingContext = new EMFDataBindingContext();

		m_bindingContext.bindValue(SWTObservables.observeText(lastName,SWT.Modify), EMFObservables.observeValue(verwaltung,
				VerwaltungPackage.Literals.VERWALTUNG__NAME), null, null);
	}
	private void initializeEditingDomain() {
		// Create an adapter factory that yields item providers.
		//
		ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);

		adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
		adapterFactory.addAdapterFactory(new VerwaltungItemProviderAdapterFactory());
		adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());

		// Create the command stack that will notify this editor as commands are executed.
		//
		BasicCommandStack commandStack = new BasicCommandStack();

		// Add a listener to set the most recent command's affected objects to be the selection of the viewer with focus.
		//
		commandStack.addCommandStackListener
			(new CommandStackListener() {
				 public void commandStackChanged(final EventObject event) {
					 System.out.println("hier");
					  getSite().getShell().getDisplay().asyncExec
						 (new Runnable() {
							  public void run() {
								  firePropertyChange(IEditorPart.PROP_DIRTY);
							  }
						  });
				 }
			 });
		
		editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack, new HashMap<Resource, Boolean>());
	}
```


----------



## Gast2 (13. Okt 2010)

Ah hier ist ein sehr guter Blog zum Databinding und Undo/Redo =)...
Tutorials  Tomsondev Blog


----------



## Gast2 (14. Okt 2010)

Also ich hab mein Databinding nun angepasst:


```
IEMFEditValueProperty valueProperty = EMFEditProperties.value(editingDomain, VerwaltungPackage.Literals.VERWALTUNG__NAME);
        observableValue  = valueProperty.observe(verwaltung);
        m_bindingContext.bindValue(SWTObservables.observeText(lastName,SWT.Modify),
                observableValue , null, null);
```

hab einen CommandStackListener der immer ein dirty event schmeißt


```
commandStack.addCommandStackListener
			(new CommandStackListener() {
				 public void commandStackChanged(final EventObject event) {
					  getSite().getShell().getDisplay().asyncExec
						 (new Runnable() {
							  public void run() {
								  firePropertyChange(IEditorPart.PROP_DIRTY);
							  }
						  });
				 }
			 });
```

Damit ich weiß ob was geändert wurde. Sobald ich was eingeb funktioniert die Sache auch. Aber
die Undo und Redo Commands sind immer disable was mach ich falsch? Oder was fehlt mich noch?

```
@Override
	public boolean isDirty() {
		BasicCommandStack basicCommandStack = (BasicCommandStack) editingDomain.getCommandStack();
		return basicCommandStack.isSaveNeeded();
	}
```

Im ActionBarAdvisor habe ich es auch registriert:

```
protected void makeActions(IWorkbenchWindow window) {
        // Edit
        register(ActionFactory.UNDO.create(window));
        register(ActionFactory.REDO.create(window));

    }
```


----------



## Gast2 (15. Okt 2010)

Okay falls es jemand interessiert, ich musste in der extension point Editor in meiner im Feld contributorClass folgende Klasse verwenden -->EditingDomainActionBarContributor und der Editor muss das interface IEditingDomainProvider implementieren :
Für eine View habe ich sowas noch nicht gefunden deshalb habe ich zum Test mal eine eigene implementierung vorgenommen, was ganz gut klappt.


```
public class ViewEditingDomainActionBarContributor extends EditingDomainActionBarContributor{
		
		protected IViewPart activeView;
		
		@Override
		public void setActiveView(IViewPart part) {
			init(part.getViewSite().getActionBars());
			this.activeView = part;
			activate();
		}
		
		  public void activate()
		  {
			  activeView.addPropertyListener(this);

		    deleteAction.setActiveWorkbenchPart(activeView);
		    cutAction.setActiveWorkbenchPart(activeView);
		    copyAction.setActiveWorkbenchPart(activeView);
		    pasteAction.setActiveWorkbenchPart(activeView);
		    undoAction.setActiveWorkbenchPart(activeView);
		    redoAction.setActiveWorkbenchPart(activeView);

		    if (loadResourceAction != null)
		    {
		      loadResourceAction.setActiveWorkbenchPart(activeView);
		    }

		    if (controlAction != null)
		    {
		      controlAction.setActiveWorkbenchPart(activeView);
		    }

		    if (validateAction != null)
		    {
		      validateAction.setActiveWorkbenchPart(activeEditor);
		    }

		    ISelectionProvider selectionProvider = 
		    	activeView instanceof ISelectionProvider ?
		        (ISelectionProvider)activeView :
		        	activeView.getViewSite().getSelectionProvider();

		    if (selectionProvider != null)
		    {
		      selectionProvider.addSelectionChangedListener(deleteAction);
		      selectionProvider.addSelectionChangedListener(cutAction);
		      selectionProvider.addSelectionChangedListener(copyAction);
		      selectionProvider.addSelectionChangedListener(pasteAction);

		      if (validateAction != null)
		      {
		        selectionProvider.addSelectionChangedListener(validateAction);
		      }

		      if (controlAction != null)
		      {
		        selectionProvider.addSelectionChangedListener(controlAction);
		      }      
		    }

		    update();
		  }

		  public void update()
		  {
		    ISelectionProvider selectionProvider = 
		    	activeView instanceof ISelectionProvider ?
		        (ISelectionProvider)activeView :
		        	activeView.getViewSite().getSelectionProvider();

		    if (selectionProvider != null)
		    {
		      ISelection selection = selectionProvider.getSelection();
		      IStructuredSelection structuredSelection =
		        selection instanceof IStructuredSelection ?  (IStructuredSelection)selection : StructuredSelection.EMPTY;

		      deleteAction.updateSelection(structuredSelection);
		      cutAction.updateSelection(structuredSelection);
		      copyAction.updateSelection(structuredSelection);
		      pasteAction.updateSelection(structuredSelection);

		      if (validateAction != null)
		      {
		        validateAction.updateSelection(structuredSelection);
		      }

		      if (controlAction != null)
		      {
		        controlAction.updateSelection(structuredSelection);
		      }
		    }

		    undoAction.update();
		    redoAction.update();

		    if (loadResourceAction != null)
		    {
		      loadResourceAction.update();
		    }
		  }
	
	
	  public void deactivate()
	  {
		  activeView.removePropertyListener(this);

	    deleteAction.setActiveWorkbenchPart(null);
	    cutAction.setActiveWorkbenchPart(null);
	    copyAction.setActiveWorkbenchPart(null);
	    pasteAction.setActiveWorkbenchPart(null);
	    undoAction.setActiveWorkbenchPart(null);
	    redoAction.setActiveWorkbenchPart(null);

	    if (loadResourceAction != null)
	    {
	      loadResourceAction.setActiveWorkbenchPart(null);
	    }

	    if (controlAction != null)
	    {
	      controlAction.setActiveWorkbenchPart(null);
	    }

	    if (validateAction != null)
	    {
	      validateAction.setActiveWorkbenchPart(null);
	    }

	    ISelectionProvider selectionProvider = 
	    	activeView instanceof ISelectionProvider ?
	        (ISelectionProvider)activeView :
	        	activeView.getViewSite().getSelectionProvider();

	    if (selectionProvider != null)
	    {
	      selectionProvider.removeSelectionChangedListener(deleteAction);
	      selectionProvider.removeSelectionChangedListener(cutAction);
	      selectionProvider.removeSelectionChangedListener(copyAction);
	      selectionProvider.removeSelectionChangedListener(pasteAction);

	      if (validateAction != null)
	      {
	        selectionProvider.removeSelectionChangedListener(validateAction);
	      }

	      if (controlAction != null)
	      {
	        selectionProvider.removeSelectionChangedListener(controlAction);
	      }
	    }
	  }
	}
```


----------

