# Verständnisprobleme bei Observer-Pattern mit größerem Datenmodell



## kidsos (23. Apr 2010)

Hallo allerseits,

ich beschäftige mich zur Zeit mit dem Observer-Pattern und habe mir hierzu schon die FAQ aus diesem Forum bzw. Code-Beispiele und Erklärungen (u.a. von "Java ist auch eine Insel", usw.) aus dem Internet angesehen. Allerdings bin ich mit der Implementierung noch keinen Schritt weitergekommen. Als Framework nutze ich GWT, primär also die Webentwicklung und nichts mit Swing oder dergleichen (nur zur Information). Ich hoffe mal, dass ich hier im richtigen Unterforum gelandet, da das Problem auch nicht wirklich GWT-spezifisch ist.

Meistens ist es so, dass das Observer-Pattern gut erklärt wird, wenn man aber mal ein größeres Datenmodell einsetzt, dass nicht nur aus einer Klasse besteht, fangen schon die Probleme an. Da gibt es zum einem das Observer-Interface bzw. die Observable-Klasse als grundlegendes Pattern. Dann gibts es noch die Listener als erweiterte Observer-Pattern. Überall wird es verschieden in den Code implementiert, aber schlauer bin ich dadurch auch noch nicht geworden.

Also, worauf will ich hinaus. Ich zeige euch das am besten mal an meiner ApplicationModel-Klasse, siehe folgend:

```
public class ApplicationModel {

	private Map<String, ApplicationItem> itemHashMap;

	public ApplicationModel() {
		itemHashMap = new HashMap<String, ApplicationItem>();
	}

	public void setItemHashMap(Map<String, ApplicationItem> itemHashMap) {
		this.itemHashMap = itemHashMap;
	}

	public Map<String, ApplicationItem> getItemHashMap() {
		return itemHashMap;
	}
}
```
Die Map enthält dabei ApplicationItem-Objekte. Sobald nun also z.B. ein ApplicationItem-Objekt (für weitere Infos siehe Klassendiagramm) in der Map editiert, gelöscht oder ein neues hinzukommt, möchte ich darüber informiert werden. Das Mittel der Wahl wären hier also die PropertyChange-Klassen und die dazugehörigen Methoden, so viel hab ich schon rausgefunden. 

Aber wie genau implementiere ich das nun in der ApplicationModel-Klasse? Ich kann ja nicht in jeder Klasse ein eigenes Süppchen kochen. Der Sinn des MVC-Prinzips ist es ja grade, Änderungen am Modell nur in einer Klasse zu implementieren (hier die ApplicationModel-Klasse). Swing bietet hier ja die Möglichkeit Modelle an Komponenten zu binden. Ich arbeite aber mit dem GWT, wodurch ich da selbst Hand anlegen muss.

Am Ende soll das Hinzufügen eines PropertyChangeListeners in etwas so über die Bühne gehen:

```
ApplicationModel model = new ApplicationModel();
mode.addPropertyChangeListener(new PropertyChangeListener() {
     @Override
     public void onPropertyChange(PropertyChangeEvent event) {
          //hier kommt dann der Code hin
     }
});
```
Wie gesagt, es geht mir hier ums Prinzip, natürlich soll das dann später auch funktionieren. 

Wäre toll, wenn mir jemand dabei helfen könnte!


----------



## Wildcard (23. Apr 2010)

Erzeug dir dein Modell mit EMF, dann hast du eine fertige Observer Schnittstelle die alles kann was du möchtest (und mehr).
Wenn dein UML Tool als XMI abspeichern kann, solltest du sogar in der Lage sein das Modell direkt aus dem UML zu generieren.
Eclipse Modeling - EMF - Home


----------



## kidsos (23. Apr 2010)

Das UML-Diagramm war eigentlich nur dazu da, um das Modell zu zeigen. Mit EMF kenne ich mich noch nicht aus, aber ich probiere es grade. Hab mir dazu auch die entsprechenden Pakte in Eclipse installiert.

Momentan bin ich da beim Erstellen des Ecore-Diagramms. Wie kann ich das denn nun so einstellen, dass z.B. in der ApplicationItem-Klasse das "address"-Attribut vom Typ "Address" ist? Bei EType stehen mir da nur die primitiven Datentypen zur Verfügung. Muss ich da noch was gesondert einstellen?

Tipps/Links zum EMF-Einstieg wären auch hilfreich.


----------



## Wildcard (23. Apr 2010)

EAttributes können immer nur primitive Typen sein.
Für Klassen (EClass) brauchst du eine EReference.  Zur Einführung am besten mal ins WIki schauen


----------



## kidsos (24. Apr 2010)

Ich denke, dass ich das EMF-Modell jetzt soweit fertiggestellt habe (siehe Anhang). Die Modellklassen habe ich dazu bereits auch erstellen lassen. Stimmt doch soweit, oder?

Gut, jetzt habe ich ein EMF-Modell und die Modellklassen und kann mir dementsprechend auch eine Instanz des Modells erzeugen. Bisher habe ich aber mit JAXB meine Modellklassen erstellt, um mein Modell in eine XML-Datei zu schreiben bzw. daraus zu lesen. Gibt es bei EMF evtl. die Möglichkeit das Modell mit entsprechenden JAXB-Annotationen zu versehen?

Wenn ich später diese Modellklassen in mein GWT-Projekt übertrage, muss ich auch darauf achten, dass jede Klasse meines Modells die Schnittstelle Serializable implementiert, damit das Modell per GWT-RPC an den Client übertragen werden kann. Wie verhält sich das nun bei EMF? Wie kann man bei EMF eine bestimmte Schnittstelle zu einer Klasse hinzufügen?

Einen hab ich noch. 
In meiner bisherigen ApplicationModel-Klasse (siehe 1. Post) habe ich noch folgende 2 Methoden:

```
@XmlElement(name = "company")
	private ApplicationItem[] getXmlApplicationList() {
		ApplicationItem[] appList = new ApplicationItem[itemHashMap.size()];

		int e = 0;
		for (String id : itemHashMap.keySet()) {
			appList[e++] = itemHashMap.get(id);
		}
		return appList;
	}

	@SuppressWarnings("unused")
	private void setXmlApplicationList(ApplicationItem[] replacements) {
		itemHashMap.clear();
		for (ApplicationItem c : replacements) {
			itemHashMap.put(c.getId(), c);
		}
	}
```
Im Prinzip mappe ich hier einfach meine Map auf ein Array um, damit die XML-Datei übersichtlicher ist (ApplicationItem-Objekte werden dann wie eine Liste geschrieben). Programmintern arbeite ich aber mit der Map, da ich ja jeden Wert mit einem bestimmten Key herausholen kann. Ist deutlich besser zu händeln. Diesen Sachverhalt müsste ich bei den EMF-Modellklassen ja auch irgendwie berücksichtigen. Wie kann ich das da bewerkstellingen?

Sorry, wenn ich so frage, aber bei der Fülle an Informationen, die EMF bietet, ist es schwer den Überblick zu behalten.


----------



## Wildcard (24. Apr 2010)

kidsos hat gesagt.:


> Ich denke, dass ich das EMF-Modell jetzt soweit fertiggestellt habe (siehe Anhang). Die Modellklassen habe ich dazu bereits auch erstellen lassen. Stimmt doch soweit, oder?


Sieht erstmal ok aus, hast du auch die Containment Properties im Ecore gesetzt? Wenn du in XML denkst, dann bestimmt das welche Elemente als Kind im XML erscheinen, und welche einfach referenziert werden. Wenn du eine EClass mit einer EReference hast und auf der EReference Containment auf true stellst, dann ist die EClass der Container für Instanzen dieser Referenz.



> Gut, jetzt habe ich ein EMF-Modell und die Modellklassen und kann mir dementsprechend auch eine Instanz des Modells erzeugen. Bisher habe ich aber mit JAXB meine Modellklassen erstellt, um mein Modell in eine XML-Datei zu schreiben bzw. daraus zu lesen. Gibt es bei EMF evtl. die Möglichkeit das Modell mit entsprechenden JAXB-Annotationen zu versehen?


Das schöne ist: EMF ist gleichzeitig ein wesentlich mächtigeres XML Binding Framework als JaxB. Du kannst dein Modell bereits jetzt als XML speicher.
Du erstellst einfach eine Resource, addest der Resource dein Root Element und rufst save auf, schon hast du ein XML.


> Wenn ich später diese Modellklassen in mein GWT-Projekt übertrage, muss ich auch darauf achten, dass jede Klasse meines Modells die Schnittstelle Serializable implementiert, damit das Modell per GWT-RPC an den Client übertragen werden kann. Wie verhält sich das nun bei EMF? Wie kann man bei EMF eine bestimmte Schnittstelle zu einer Klasse hinzufügen?


Am einfachsten du öffnest die generierten Interfaces. Dort ist über dem Interface JavaDoc mit [XML]<!--begin user doc-->
<!--end user doc-->[/XML]
Dazwischen trägst du folgendes ein:

```
@implements java.io.serializable
```
Wenn du anschließend neu generierst erweitern die Interfaces Serializable.




> Im Prinzip mappe ich hier einfach meine Map auf ein Array um, damit die XML-Datei übersichtlicher ist (ApplicationItem-Objekte werden dann wie eine Liste geschrieben). Programmintern arbeite ich aber mit der Map, da ich ja jeden Wert mit einem bestimmten Key herausholen kann. Ist deutlich besser zu händeln. Diesen Sachverhalt müsste ich bei den EMF-Modellklassen ja auch irgendwie berücksichtigen. Wie kann ich das da bewerkstellingen?


Siehe hier wie man eine Map modelliert:
EMF/FAQ - Eclipsepedia
Im Prinzip funktioniert das dann automatisch genaus wie du es bisher händisch gelöst hast.



> Sorry, wenn ich so frage, aber bei der Fülle an Informationen, die EMF bietet, ist es schwer den Überblick zu behalten.


Frag ruhig. Am Anfang gibt es viel was man sich bei EMF aneignen muss, wenn man aber die Zeit einmal investiert, kann man fortan für fast jedes Softwareprojekt EMF einsetzen, wird deutlich produktiver und muss sich nie mehr mit Low-Level Libraries wie JAXB herumschlagen


----------



## kidsos (25. Apr 2010)

So, ich musste mich erst mal durch die ganzen Tutorials lesen und hab das jetzt soweit hinbekommen (zumindest denke ich das). Allerdings wirft der Compiler noch eine Nullpointer-Exception in der main-Methode, siehe folgend:


```
public static void main(String[] args) {
	ModelFactory factory = ModelFactory.eINSTANCE;
	ApplicationModel model = factory.createApplicationModel();
	
	// hier erstelle ich beispielhaft ein ApplicationItem-Objekt und füge 
	// das dann dem ApplicationModel-Objekt hinzu
	// die notwendigen Objekte wurden alle korrekt erstellt
	ApplicationItem item = factory.createApplicationItem();
	item.setId("0");
	item.setAddress(address);
	item.setJob(job);
	item.getStatusList().add(status);
	model.getItemMap().put(item.getId(), item);
		
	ResourceSet resourceSet = new ResourceSetImpl();
	URI fileURI = URI.createFileURI(new File("jobs.xml").getAbsolutePath());
	Resource resource = resourceSet.createResource(fileURI);
	resource.getContents().add(model);  // <--- hier wirft der Compiler die Nullpointer-Exception
	try {
		resource.save(null);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
```
Jetzt frage ich mich: Wie kann das sein, wenn das ApplicationModel-Objekt deklariert und initialisiert wurde? Was hab da falsch gemacht?


----------



## Wildcard (25. Apr 2010)

Deine Resource ist null weil auf diesem ResourceSet noch keine ResourceFactory registriert ist.
Zum Testen instanzier einfach eine neue XMLResourceImpl und las das ResourceSet noch aussen vor.
Im nächsten Schritt kannst du dann in deinem Genmodel den Resource Type von NONE auf XML umstellen, dann sollte dir eine ApplicationModelResource generiert werden die du dann auf einem ResourceSet registrieren kannst.


----------



## kidsos (25. Apr 2010)

Puh, so viel auf einmal. Das muss ich mir erstmal verinnerlichen. 

Also, ich hab den Resource Type vom Genmodel von NONE auf XML umgestellt und das Modell neu generieren lassen. In dem *.util Package sind jetzt 3 weitere Klassen hinzugekommen: ModelResourceFactoryImpl, ModelResourceImpl und ModelXMLProcessor.

Wie genau muss ich mir "auf einem ResourceSet registrieren" vorstellen? Könntest du da etwas Beispielcode zeigen?

Ich tue mich da noch relativ schwer das Geschriebene auf Java-Code und umgekehrt zu übersetzen, deshalb frage ich.

Edit: Ich habe mir mal testweise eine XSD aus dem Genmodel erstellen lassen. In der XSD sind alle Attribute als "xsd:attribute" gekennzeichnet. In der XML sollen die jedoch nicht als Attribute auftauchen, sondern als Elemente. Muss man da noch was einstellen? Oder kann das vielleicht sein, dass EMF das eutomatisch macht?


----------



## Wildcard (25. Apr 2010)

Wenn dir ein ganz bestimmtes XML Format vorschwebt ist es oft am einfachsten das XSD zu schreiben und dann das Schema in EMF zu importieren. Du kannst auch bei bestehenden Ecores die XML Persistenz durch EAnnotations anpassen, aber es ist einfacher ein XSD zu importieren.


> Wie genau muss ich mir "auf einem ResourceSet registrieren" vorstellen? Könntest du da etwas Beispielcode zeigen?


Ein ResourceSet kann Resourcen von ganz unterschiedlichen Typen gleichzeitig aufnehmen. Daher hält ein ResourceSet verschiedene Registries um anhand URI, Namespace, Dateiendung,... die richtige Art von Resource zu instanzieren.
Schau zB mal hier:
ResourceSet (EMF Javadoc)
Dort kannst du deine ModelResourceFactoryImpl auf zB eine Dateiendung registrieren.
Wenn du dann resourceSet.createResource oder getResource mit einer entsprechenden File URI aufrufst, dann wird zum Instanzieren der ModelResourceImpl deine ModelResourceFactory verwendet.


----------



## kidsos (25. Apr 2010)

Ah, ich glaub, ich komme langsam dahinter. Die Registries könnten z.B. in den weiteren Methoden von 
	
	
	
	





```
resourceSet.getResourceFactoryRegistry()
```
 festgelegt werden, je nachdem was man gerne möchte. Da kann man sich aber als Anfänger in Sachen EMF auch sehr schnell verzetteln bei den vielen Möglichkeiten.

So habe ich das jetzt realisiert:

```
URI fileURI = URI.createFileURI(new File("jobs.xml").getAbsolutePath());
ModelResourceFactoryImpl im = new ModelResourceFactoryImpl();
Resource res = im.createResource(fileURI);
res.getContents().add(model);
try {
	res.save(null);
} catch (IOException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
```
Wenn ich mir das so anschaue, ist es genau so wie du gesagt hast. Ich glaube, dass braucht noch seine Zeit, bis man die Zusammenhänge versteht. 

Schön, dass es erstmal grundsätzlich klappt. Allerdings stört mich die XML-Ausgabe noch. Sieht momentan aus:
[XML]
<?xml version="1.0" encoding="ASCII"?>
<model:ApplicationModel xmlns:model="http://model/1.0">
  <itemMap key="0" value="0"/>
</model:ApplicationModel>
[/XML]
Eigentlich sollten die Values der itemMap zu sehen sein und der Key als id-Attribut der entsprechenden Values. So z.B.:
[XML]
<?xml version="1.0" encoding="ASCII"?>
<model:ApplicationModel xmlns:model="http://model/1.0">
    <company id="0">
        // hier kommen die Inhalte
        // die Elementnamen sind nur ein Beispiel
    </company>
</model:ApplicationModel>
[/XML]
Wo müsste ich denn in dem Modell bzw. in den Klassen das Rädchen drehen, damit das Modell so in der XML gespeichert wird?

Noch eine Frage habe ich: Wie kann man das Encoding z.B. auf UTF-8  oder einen anderen Zeichensatz umstellen?

Edit: Ich sehe grade, dass es noch den Datentyp EFeatureMap gibt, der Key-Value-Paare in einer Liste darstellt. Würde das mein Problem lösen?


----------



## Wildcard (25. Apr 2010)

Die XML Ausgabe wird über Annotation im Ecore gesteuert. Am besten ist wirklich das du dir mal eine einfache XSD bastelst, sie mit EMF importierst und dir dann das ecore anschaust. Dann siehst du wie die entsprechenden Annotation verwendet werden.


----------



## kidsos (25. Apr 2010)

Bei der Erstellung der Modellklassen habe ich schon gesehen, dass in jede set-Methode auch was mit eNotfiy oder so ähnlich drinne steht. Das hängt wohl wahrscheinlich mit dem Observer Pattern zusammen, was ich ja eigentlich ursprünglich gefragt habe. Wie kann ich das nun genau bei mir einsetzen, sodass ich z.B. nach einer Veränderung eine Syntax wie im ersten Post angeben kann? Ich möchte da eben wissen, wer war der Urheber der Veränderung, was stand vorher drin, usw.

Achja, eine Frage fällt mir grad noch ein. Wenn man eine bestimmte XML vor Augen hat, dann ist ja jede Modellklasse im Ecore ein Element in der XML. Bei Verwendung von Wrapper-Elementen in der XML würde dann EMF daraus ja eine Klasse erstellen, die ja dann nur wie eine Art Container agiert. Würde EMF da nicht ein bisschen Balast produzieren, den man eigentlich gar nicht braucht? Ist doch eigentlich komfortabler und sauberer, erst in EMF das Modell zu erstellen und das dann z.B. in eine XSD oder ein UML-Diagramm zu exportieren. Oder irre ich mich da?

Dann danke ich dir schon mal für die tolle Unterstützung. Hast mir echt weitergeholfen!


----------



## Wildcard (25. Apr 2010)

kidsos hat gesagt.:


> Bei der Erstellung der Modellklassen habe ich schon gesehen, dass in jede set-Methode auch was mit eNotfiy oder so ähnlich drinne steht. Das hängt wohl wahrscheinlich mit dem Observer Pattern zusammen, was ich ja eigentlich ursprünglich gefragt habe. Wie kann ich das nun genau bei mir einsetzen, sodass ich z.B. nach einer Veränderung eine Syntax wie im ersten Post angeben kann? Ich möchte da eben wissen, wer war der Urheber der Veränderung, was stand vorher drin, usw.


Jedes Object pflegt eine Liste mit Adaptern. Adapter sind gleichzeitig Observer und zusätzliche Funktionalität. In deinem Fall ist die Observer Funktionalität wohl das entscheidende.
Mit object.eAdapters().add(yourAdapter) addest du einen neuen Observer. Es gibt auch fertige Adapter wie zB der EContentAdapter. Wenn du ihn auf ein Objekt addest, dann fügt er sich rekursiv allen Kindern hinzu. Kommt ein neues Kind hinzu fügt er sich auch dort ein, verschwindet ein Kind, entfernt er sich. Einen EContentAdapter kannst du also sehr einfach verwenden wenn du rekursiv einen ganzen Objektbaum beobachten möchtest.
In der notify Methode bekommst du dann mitgeteilt was sich wo geändert hat, welcher art die Änderung war (add, remove, move, change,...) und den alten und neuen Wert.


> Achja, eine Frage fällt mir grad noch ein. Wenn man eine bestimmte XML vor Augen hat, dann ist ja jede Modellklasse im Ecore ein Element in der XML. Bei Verwendung von Wrapper-Elementen in der XML würde dann EMF daraus ja eine Klasse erstellen, die ja dann nur wie eine Art Container agiert. Würde EMF da nicht ein bisschen Balast produzieren, den man eigentlich gar nicht braucht? Ist doch eigentlich komfortabler und sauberer, erst in EMF das Modell zu erstellen und das dann z.B. in eine XSD oder ein UML-Diagramm zu exportieren. Oder irre ich mich da?


Der Balast fällt nicht weiter ins Gewicht, die EMF Modelle sind äussert schmal gehalten und lassen sich bei Bedarf noch weiter entschlacken (automatischer Support für Bitmasken um viele Boolean Flags auf einen Int zu mappen, diverse Optimierungen um mehrere Features transparent in einem einzigen Array abzulegen, MinimalEObject,...).
Klar ist es komfortabler ein ECore zu erstellen als eine XSD zu schreiben. Wenn du allerdings eine ganz bestimmte XML vor Augen hast, dann ist es oft einfacher die passende XSD zu schreiben, als die ganzen Annotations selbst zu erstellen.
Sauberer würde ich eigentlich nicht sagen, denn in beiden Fällen erhälst du ja ein Ecore und ein Genmodel das du nach belieben editieren kannst...



> Dann danke ich dir schon mal für die tolle Unterstützung. Hast mir echt weitergeholfen!


Als überzeugter EMF Jünger verbreitet man die Botschaft gerne weiter


----------



## kidsos (26. Apr 2010)

So, ich habe noch mal mein aktualisiertes EMF-Modell angehängt, damit man einige Sachen evtl. besser nachvollziehen kann. Dort, wo es nötig war, habe ich die entsprechenden Annotationen hinzugefügt (u.a. bei "Content Kind" auf "element" gestellt). Dadurch erhalte ich jetzt folgende XML-Struktur (die Inhalte habe ich rausgenommen):

[XML]
<ApplicationModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://model/1.0">
  <itemMap key="0">
    <value id="0">
      <address>
        <contacts>
          <title></title>
          <firstName></firstName>
          <lastName></lastName>
          <phoneNumber></phoneNumber>
          <email></email>
        </contacts>
        <name></name>
        <street></street>
        <zipCode></zipCode>
        <city></city>
        <state></state>
        <senderFormat></senderFormat>
      </address>
      <job>
        <title></title>
        <profession></profession>
      </job>
      <statusList>
        <type></type>
        <title></title>
        <notes></notes>
        <date></date>
      </statusList>
    </value>
  </itemMap>
</ApplicationModel>
[/XML]
Das "itemMap" und das "value"-Element haben bei mir die gleiche Bedeutung. Jedes Item hat eine ID und die habe ich auch als Keys in meiner Map verwendet. Daher tauchen die jetzt auch doppelt auf. Kann man das irgendwie verhindern? Im Prinzip brauche ich nur ein Element von den zweien.

Der Grund, weshalb ich jetzt keine XSD als Basis verwende, ist der, dass ich ja zuvor bei dem JAXB-Modell von der Map auf das Array gemappt habe (klingt irgendwie komisch) und das dann gespeichert habe. Diesen Sachverhalt kann ja aber nicht auf die XSD übertragen werden, weil woher soll die XSD wissen das hier ein Mapping erfolgt. Daher versuche ich jetzt, von dem EMF-Modell mit den EAnnotations die passende XML-Struktur zu erzeugen. Wollte ich nur mal so als Info sagen. 

Kannst du diese Frage noch beantworten:


> Wie kann man das Encoding z.B. auf UTF-8 oder einen anderen Zeichensatz umstellen?



Und zu guter letzt: Beim Lesen der XML benötige ich ja auch eine ResourceFactory, um dann per getResource() auf die Resource zuzugreifen. Leider implementiert meine Klasse ModelResourceFactoryImpl diese Methode nicht. Wie komme ich denn da jetzt ran?


----------



## Wildcard (26. Apr 2010)

> Wie kann man das Encoding z.B. auf UTF-8 oder einen anderen Zeichensatz umstellen?


Dir wird vielleicht aufgefallen sein das die save Methode einer Resource eine Map mit Options erwartet. Dort übergibst du eine HashMap mit einem Key XMLResource.OPTION_ENCODING und Value dein gewünschtes Encoding.



> Und zu guter letzt: Beim Lesen der XML benötige ich ja auch eine ResourceFactory, um dann per getResource() auf die Resource zuzugreifen. Leider implementiert meine Klasse ModelResourceFactoryImpl diese Methode nicht. Wie komme ich denn da jetzt ran?


Wenn in deinem ResourceSet die ResourceFactory korrekt registriert wurde, dann reicht folgender Code zum Laden:


```
Resource resource = resourceSet.getResource(uri, true); //resource sollte dann automatisch eine 'YourResource' sein
YourModelRoot root = (YourModelRoot)resource.getContents().get(0);
```


----------



## kidsos (26. Apr 2010)

> Wenn in deinem ResourceSet die ResourceFactory korrekt registriert wurde, dann reicht folgender Code zum Laden:


Den folgenden Code meinst du wohl mit "registrieren". Ich glaube, dass ist es auch, was du weiter oben meintest mit "auf eine bestimmte Dateiendung registrieren".

```
ResourceSet resSet = new ResourceSetImpl();
resSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml", new ModelResourceFactoryImpl());
```
Die Options-Map muss ich mir wohl so wie ne Art Konfigurationsliste vorstellen. Je nachdem, was man noch an zusätzlichen Angaben in die XML reinpacken möchte, kann man dort angeben.

Hab das jetzt auch noch mit den Adapter ausprobiert. Ist ja echt ne tolle Sache. Ich muss ja quasi um fast gar nichts mehr kümmern. EMF generiert für mich die Modellklassen samt Observer. 
Ich hab noch ein bissl weiter geforscht und gesehen, dass auch EMF auch mit EclipseLink umgehen kann. Damit brauch man nur noch das Modell zu entwerfen, den Rest erledigt EMF (inkl. Modellklassengenerierung und der dazugehörigen Datenbankstruktur. Die Möglichkeiten sind ja riesig und ich hab wahrscheinlich nur an der Oberfläche gekratzt. 

Hast du zufällig hier noch ne Idee (siehe letzter Post von mir):


> Das "itemMap" und das "value"-Element haben bei mir die gleiche Bedeutung. Jedes Item hat eine ID und die habe ich auch als Keys in meiner Map verwendet. Daher tauchen die jetzt auch doppelt auf. Kann man das irgendwie verhindern? Im Prinzip brauche ich nur ein Element von den zweien.


----------



## Wildcard (26. Apr 2010)

kidsos hat gesagt.:


> Die Options-Map muss ich mir wohl so wie ne Art Konfigurationsliste vorstellen. Je nachdem, was man noch an zusätzlichen Angaben in die XML reinpacken möchte, kann man dort angeben.


Ja, einfach eine menge ein Einstellmöglichkeiten für's Laden und Serialisieren. Du kannst auch direkt auf der XMLResource (deine Resource sollte ja von XMLResourceImpl erben) setEncoding aufrufen, kommt aufs gleiche raus.



> Hab das jetzt auch noch mit den Adapter ausprobiert. Ist ja echt ne tolle Sache. Ich muss ja quasi um fast gar nichts mehr kümmern. EMF generiert für mich die Modellklassen samt Observer.
> Ich hab noch ein bissl weiter geforscht und gesehen, dass auch EMF auch mit EclipseLink umgehen kann. Damit brauch man nur noch das Modell zu entwerfen, den Rest erledigt EMF (inkl. Modellklassengenerierung und der dazugehörigen Datenbankstruktur. Die Möglichkeiten sind ja riesig und ich hab wahrscheinlich nur an der Oberfläche gekratzt.


Richtig, das war nur die Oberfläche, dazu kommen:
-verteilte Modellrepositories (funktioniert auch für riesige Modelle) mit CDO 
-DB artige Queries auf EMF Modelle mit EMF Query 
-generischer Stuktureller Vergleich samt Diff Modell, Match Modell, merge, Compare Editor mit EMF Compare
-Die Fähigkeit einen funktionsfähigen Eclipse Editor mit einem Klick aus dem Modell zu erzeugen
-OCL Support
-Vollständige Unit Tests per Mausklick generieren
-Statt XML textuelle Syntax mit mächtigem automatisch generiertem Lexer, Parser, Linker mit XText
-einen extrem mächtigen Eclipse Editor (Autocompletion, Outline, Linking, CrossReferences, Refactoring, Folding,...) für textuelle Modelle generieren (ebenfalls XText)
-Komplette Grafische Eclipse Editoren aus einem Ecore generieren (GMF)

Und vieles, vieles mehr 




> Das "itemMap" und das "value"-Element haben bei mir die gleiche Bedeutung. Jedes Item hat eine ID und die habe ich auch als Keys in meiner Map verwendet. Daher tauchen die jetzt auch doppelt auf. Kann man das irgendwie verhindern? Im Prinzip brauche ich nur ein Element von den zweien.


Du kannst den Map Zugriff (itemMap?) auf transient und derived stellen (im ecore). Dann wird es nicht serialisiert. Derived gibt an das sich das Feature aus anderen Features berechnet. Damit kannst du dann den entsprechenden getter selbst implementieren und auf das values Feature delegieren.
Gibt sicherlich auch noch andere Möglichkeiten, dafür müsste ich mir dein Modell mal genauer ansehen.


----------



## kidsos (26. Apr 2010)

Ok, denke das soweit erstmal alles steht. Den Rest muss ich jetzt einfach durch Probieren selbst herausfinden.

Ich setze den Thread vorerst auf erledigt. Bekommst noch nen Danke für die Top-Hilfe! :toll:


----------



## kidsos (27. Apr 2010)

Hm, ich habe nun schon gegoogelt, aber den passenden Lösungsansatz für mein Problem zu finden, ist bei der Masse an Informationen schier unüberwindbar. Dazu ist mein Problem einfach zu konkret.



> Du kannst den Map Zugriff (itemMap?) auf transient und derived stellen (im ecore). Dann wird es nicht serialisiert. Derived gibt an das sich das Feature aus anderen Features berechnet. Damit kannst du dann den entsprechenden getter selbst implementieren und auf das values Feature delegieren.


Wie würde denn das bei mir aussehen? Bei einer Datenbank ist das doch auch nicht anders, oder nicht. Man hat ein id-Attribut, dass jeden Datensatz eindeutig identiziert. Nichts anderes macht ja eigentlich meine Map. Bin ich da auf dem falschen Weg?



> Gibt sicherlich auch noch andere Möglichkeiten, dafür müsste ich mir dein Modell mal genauer ansehen.


Ich kann dir mein Modell zur Verfügung, musst nur sagen wie. Denn ich glaube, ohne fremde Hilfe komme ich hier nicht weiter


----------



## Wildcard (27. Apr 2010)

Poste hier doch einfach mal das Ecore (im Text Editor öffnen und dann Copy/Paste).


----------



## kidsos (27. Apr 2010)

Bitte schön:
[XML]
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model"
    nsURI="http://model/1.0" nsPrefix="model">
  <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
    <details key="qualified" value="false"/>
  </eAnnotations>
  <eClassifiers xsi:type="ecore:EClass" name="ApplicationModel">
    <eStructuralFeatures xsi:type="ecore:EReference" name="itemMap" upperBound="-1"
        eType="#//StringToApplicationItemMap" containment="true"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Status">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
        <details key="wildcards" value=""/>
        <details key="name" value="type"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="title" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="notes" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="date" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Job">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="title" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="profession" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Contact">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="title" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="firstName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="lastName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="phoneNumber" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="email" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Address">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="street" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="zipCode" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="city" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="state" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="senderFormat" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
    <eStructuralFeatures xsi:type="ecore:EReference" name="contacts" upperBound="-1"
        eType="#//Contact" containment="true"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="ApplicationItem">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
        iD="true"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="address" lowerBound="1"
        eType="#//Address" containment="true"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="job" lowerBound="1" eType="#//Job"
        containment="true"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="statusList" upperBound="-1"
        eType="#//Status" containment="true"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="StringToApplicationItemMap" instanceClassName="java.util.Map$Entry">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="key" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="value" lowerBound="1" eType="#//ApplicationItem"
        containment="true">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
</ecore:EPackage>
[/XML]


----------



## Wildcard (27. Apr 2010)

Also: um nochmal kurz zusammenzufassen was du möchtest (ob ich es auch richtig verstanden habe).
-ApplicationModel ist primär eine Map (zumindest bisher).
-Jedes ApplicationItem ist ein Map Entry.
-Du fügst neue items ein mit put(id, item).
-Du brauchst in deinem ApplicationItem eine ID (daher hast du sie dort modeliert)
-Nun wird der Key 2 Mal serialisiert, einmal als 'key' und einmal als 'ID' des ApplicationItem

Die Einfachste Lösung währe das ID Attribut des ApplicationItem auf transient=true zu stellen. Dadurch wird er nicht mehr serialisiert.
Das ist allerdings unsexy, weil du den Key jetzt doppelt Pflegen musst, in der Map und im ApplicationItem.
Mein Vorschlag wäre also:
Stell ID auf volatile (es wird kein Feld generiert) und transient (der Wert wird nicht serialisiert).
EMF generiert dir nun einen Method Stub für getID der eine UnsupportedOperationException wirft.
Diesen Stub implementierst du in etwa so:

```
/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public String getId() {
		EObject o = eContainer();
		if (o instanceof StringToApplicationItemMapImpl) {
			StringToApplicationItemMapImpl entry = (StringToApplicationItemMapImpl) o;
			return entry.getKey();
			
		}
		return "this has either no container, or the wrong container...";
	}
```

Hier noch Testcode:

```
ModelFactory factory = ModelFactory.eINSTANCE;
		ModelResourceImpl resource = new ModelResourceImpl(URI.createFileURI("test.xml"));
		ApplicationModel model = factory.createApplicationModel();
		resource.getContents().add(model);
		ApplicationItem item = factory.createApplicationItem();
		System.out.println(item.getId()); //liefert this has either no container, or the wrong container...
		model.getItemMap().put("1", item);
		System.out.println(item.getId()); //liefert 1
		Address address = factory.createAddress();
		address.setName("Musterstadt");
		item.setAddress(address);
```

In XML sieht das dann so aus:
[XML]<?xml version="1.0" encoding="ASCII"?>
<model:ApplicationModel xmlns:model="http://model/1.0">
  <itemMap key="1">
    <value>
      <address name="Musterstadt"/>
    </value>
  </itemMap>
</model:ApplicationModel>[/XML]


----------



## kidsos (27. Apr 2010)

> Also: um nochmal kurz zusammenzufassen was du möchtest (ob ich es auch richtig verstanden habe).


Richtig erfasst.

Noch ne Anmerkung: Bisher hatte ich mir immer vorher (zu Testzwecken) eine ApplicationItem-Objekt erzeugt und alle notwendigen Felder gesetzt, u.a. auch mit 
	
	
	
	





```
item.setId("0");
```
. Da ich ja jetzt das ID-Attribut auf transient=true und volatile=true gesetzt habe, ist diese Anweisung ja gar nicht mehr möglich, eben weil es nicht mehr serialisiert wird. Im Prinzip reicht es, wenn ich nur über 
	
	
	
	





```
model.getItemMap().put("1", item);
```
 den Key setze. Die vorherige Anweisung ist also nicht mehr nötig, richtig? 
Wozu wird dann eigentlich noch der Method Stub von der setId-Methode generiert? Wozu ist das gut?

Wenn ich bei meiner Anwendung noch etwas weiter denke, soll der Key ja bspw. nicht nur aus 
	
	
	
	





```
key="1"
```
 bestehen, sondern setzt sich z.B. aus dem aktuellen Datum und einer fortlaufenden Zahl zusammen (bei jedem neuen Tag beginnt sie wieder von vorne, also von 1). So in etwa 
	
	
	
	





```
key="201004271"
```
 (entsprechend formatiert), um nur ein Beispiel zu nennen, könnte auch anders aussehen. Es reicht dann also über 
	
	
	
	





```
model.getItemMap().put("201004271", item);
```
 diesen Wert zu setzen?

Das 
	
	
	
	





```
<value>
```
-Element gänzlich in der XML nicht anzeigen zu lassen, sodass man folgende Ausgabe erhält, ist wohl nicht möglich?
[XML]
<?xml version="1.0" encoding="ASCII"?>
<model:ApplicationModel xmlns:model="http://model/1.0">
  <itemMap key="1">
    <address name="Musterstadt"/>
  </itemMap>
</model:ApplicationModel>
[/XML]
Wenn das zu viel Aufwand bedeuten würde, dann belasse ich das so. Ist nicht weiter schlimm.


----------



## Wildcard (27. Apr 2010)

> Da ich ja jetzt das ID-Attribut auf transient=true und volatile=true gesetzt habe, ist diese Anweisung ja gar nicht mehr möglich, eben weil es nicht mehr serialisiert wird. Im Prinzip reicht es, wenn ich nur über model.getItemMap().put("1", item); den Key setze. Die vorherige Anweisung ist also nicht mehr nötig, richtig?


Ja, das ist richtig, du brauchst jetzt kein setID mehr.


> Wozu wird dann eigentlich noch der Method Stub von der setId-Methode generiert? Wozu ist das gut?


Die sollte verschwinden wenn du im Ecore ID auf changable=false setzt.



> Es reicht dann also über model.getItemMap().put("201004271", item); diesen Wert zu setzen?


Ja. Da EMF den generierten Code mit händisch geschriebenem Merged steht dir auch frei beliebig viele zusätzlich Methoden in deinem Modell zu programmieren um zB solche Keys automatisch zu generieren. Du kannst Methoden auch im Ecore selbst modellieren (eOperations), dann werden dir schon entsprechende Stubs generiert.



> Das <value> -Element gänzlich in der XML nicht anzeigen zu lassen, sodass man folgende Ausgabe erhält, ist wohl nicht möglich?


Möglich in jedem Fall. Allerdings verwende ich EMF nur selten im Zusammenhang mit XML und kann dir nicht genau sagen welche EAnnotations du dafür brauchst.
Im Zweifelsfall würde ich wieder zur Minimalen Beispiel XSD raten. Schreib eine XSD die so etwas abbilded, generier daraus ein Ecore und schau dir die generierten EAnnotations an. Das solltest du dann auf dein Ecore übertragen können.


----------



## kidsos (27. Apr 2010)

Wie du in meinem Ecore siehst, halte ich in einem ApplicationItem-Objekte noch eine Liste von Status-Objekten (bei mir "statusList"). Für entsprechende Wrapper-Elemente im XML-Dokument müsste ich daher ja eine Klasse erstellen, die zwischen Status-Klasse und der ApplicationItem-Klasse liegt und die Objekte in einer Liste aufnimmt (siehe Anhang). Wenn ich dann z.B. ein Status-Objekt erstellen möchte, muss ich ja zuerst ein ProgressHistoryType-Objekt über die ModelFactory erstellen und erst dann kann ich diesem ein Status-Objekt hinzufügen. Gibt es da die Möglichkeit zu sagen, dass automatisch ein ProgressHistoryType-Objekt instanziert werden soll sobald ein Status-Objekt erstellt wird? Hoffe, dass das irgendwie verständlich ist.



> Da EMF den generierten Code mit händisch geschriebenem Merged


Hm, sobald ich über das Genmodel das Model neu generiere, ist auch die Implementierung der getId()-Methode verschwunden. Wie kann ich denn nur die Änderungen auf die Modellklassen übertragen und nicht die gesamte Neugenerierung? Drücke ich da die falschen Knöpfe ???:L



> steht dir auch frei beliebig viele zusätzlich Methoden in deinem Modell zu programmieren um zB solche Keys automatisch zu generieren


Wie sähe denn so was aus?


----------



## Wildcard (28. Apr 2010)

kidsos hat gesagt.:


> Wie du in meinem Ecore siehst, halte ich in einem ApplicationItem-Objekte noch eine Liste von Status-Objekten (bei mir "statusList"). Für entsprechende Wrapper-Elemente im XML-Dokument müsste ich daher ja eine Klasse erstellen, die zwischen Status-Klasse und der ApplicationItem-Klasse liegt und die Objekte in einer Liste aufnimmt (siehe Anhang). Wenn ich dann z.B. ein Status-Objekt erstellen möchte, muss ich ja zuerst ein ProgressHistoryType-Objekt über die ModelFactory erstellen und erst dann kann ich diesem ein Status-Objekt hinzufügen. Gibt es da die Möglichkeit zu sagen, dass automatisch ein ProgressHistoryType-Objekt instanziert werden soll sobald ein Status-Objekt erstellt wird? Hoffe, dass das irgendwie verständlich ist.


Welchen Mehrwert bring der ProgressHistoryType denn? Anders gefragt, warum nicht direkt eine Liste mit Stati?
Wer legt ein Status Objekt an? Kennt der Erzeuger das entsprechende ApplicationItem (das wäre ja Bedingung dafür das automatisch ein ProgressHistoryType im ApplicationItem erstellt werden kann.




> Hm, sobald ich über das Genmodel das Model neu generiere, ist auch die Implementierung der getId()-Methode verschwunden. Wie kann ich denn nur die Änderungen auf die Modellklassen übertragen und nicht die gesamte Neugenerierung? Drücke ich da die falschen Knöpfe ???:L


Wichtig: Du musst bei jeder generierten Methode die du veränderst die Javadoc anpassen.
Dort steht ein 
	
	
	
	





```
@generated
```
 tag. Dieses Tag ersetzt du durch 
	
	
	
	





```
@generated NOT
```
.
Der generator lässt diese Methode dann in Ruhe.



			
				Wildcard hat gesagt.:
			
		

> steht dir auch frei beliebig viele zusätzlich Methoden in deinem Modell zu programmieren um zB solche Keys automatisch zu generieren





> Wie sähe denn so was aus?


Am saubersten ist solche Methoden im Ecore einzutragen. Eine neue EOperation anlegen, einen Return Type der Methode festlegen, beliebig viele Parameter und Exceptions eintragen und neu generieren.
Die Methoden sind dann in den Interfaces vorhanden und in den Implementierungen werden Stubs angelegt. Dort dann die Implementierung durchführen und mit @generated NOT markieren.

Übrigens, Tipp am Rande (für manche Modelle ist das sehr nützlich), EMF erlaubt im Gegensatz zu Java auch Mehrfachvererbung...


----------



## kidsos (28. Apr 2010)

> Welchen Mehrwert bring der ProgressHistoryType denn?


Dient einfach nur als Wrapper-Element, um die Liste in einem Element zusammenzufassen. Bei JAXB gibt es bspw. die Annotation 
	
	
	
	





```
@XmlElementWrapper(name = "progressHistory")
```
, womit ich um eine Liste ein zusätzliches Element fasse. Es geht wie gesagt nur darum, dass die XML besser lesbar und übersichtlicher ist. Mehr macht das eigentlich nicht.



> Anders gefragt, warum nicht direkt eine Liste mit Stati?


Wenn ich den Upper Bound auf * festlege (wie in meinem Modell), wird dann nicht automatisch eine EList erzeugt?
Ich habe mal probehalber in der ApplicationItem-Klasse ein zusätzliches Attribut "statusHolder"vom Typ EList<Status> angelegt, dann kann ich aber das Genmodel nicht laden. Da kommt dann die Meldung: "The attribut 'ApplicationItem.statusHolder' is not transient so it must have a data type that is serializable". Also habe ich statusHolder aus transient=true gesetzt, dann quitiert mir mit der Compiler das aber mit einer Nullpointer-Exception sobald ich Status-Objekte der Liste hinzufüge.



> EMF erlaubt im Gegensatz zu Java auch Mehrfachvererbung...


Mal so aus Interesse: Wie wird das dann in den Modellklassen gelöst?


----------



## Wildcard (28. Apr 2010)

> Dient einfach nur als Wrapper-Element, um die Liste in einem Element zusammenzufassen. Bei JAXB gibt es bspw. die Annotation @XmlElementWrapper(name = "progressHistory") , womit ich um eine Liste ein zusätzliches Element fasse. Es geht wie gesagt nur darum, dass die XML besser lesbar und übersichtlicher ist. Mehr macht das eigentlich nicht.


Wie gesagt sind die spezielleren Features was das XML Binding angeht nicht mein Spezialgebiet. Meines Wissens deckt EMF deutlich mehr XSD Features ab als JAXB, daher muss es auch gehen, aber da kann dir das EMF Buch oder die Newsgroup wohl besser helfen.
Codetechnisch lässt es sich zB über ein derived Feature lösen, aber wenn es direkt über Annotations lösen lässt würde ich diesen Weg bevorzugen (da es für das Modell keine Relevanz hat, nur für die XML Darstellung).



> Wenn ich den Upper Bound auf * festlege (wie in meinem Modell), wird dann nicht automatisch eine EList erzeugt?


Ja, Upper Bound auf -1 und dann wird es eine Liste.


> Ich habe mal probehalber in der ApplicationItem-Klasse ein zusätzliches Attribut "statusHolder"vom Typ EList<Status> angelegt, dann kann ich aber das Genmodel nicht laden. Da kommt dann die Meldung: "The attribut 'ApplicationItem.statusHolder' is not transient so it must have a data type that is serializable". Also habe ich statusHolder aus transient=true gesetzt, dann quitiert mir mit der Compiler das aber mit einer Nullpointer-Exception sobald ich Status-Objekte der Liste hinzufüge.


Die EList brauchst du nicht direkt, du setzt nur die Lower und Upper Bounds.



> Mal so aus Interesse: Wie wird das dann in den Modellklassen gelöst?


Nach aussen wird immer nur das Interface angesprochen und Mehrfachvererbung für Interfaces ist für Java kein Problem.
Bei den Implementierungen wird der erste ESuperType als Oberklasse gewählt und dann werden die implementierungen für die fehlenden Features aus den anderen ESupertypes in die Implementierungsklasse generiert.
Das führt natürlich teilweise zu doppeltem Code (auch EMF kann nur mit Wasser kochen),  aber doppelter Code ist bei generierten Klassen auch nicht so problematisch wie bei handgeschriebenem Code.
EMF Modelle sind allerdings auch nicht immer generierter Java Code. EMF hat eine mächtige Reflection API die es ermöglicht ECore Modelle zur Runtime zu erstellen  (dynamic Ecore) und genauso zu verwenden wie statische, generierte Modelle (inklusive serialisierung, Observer,...). Da passt echte Mehrfachvererbung dann zB wunderbar...


----------



## kidsos (29. Apr 2010)

Eine Sache bleibt noch übrig. Ganz am Anfang hatte ich ja geschrieben, dass ich das Modell in einem GWT-Projekt verwenden möchte. Allerdings bekomme ich da noch einen Fehler. Sollte ich da nicht vielleicht einen neuen Thread eröffnen, der nur das GWT-spezifische Problem beinhaltet (ggf. kann ich ja für das EMF-Modell auf diesen Thread verweisen)? Möchte da jetzt auch nicht zu viel vorwegnehmen, falls du dich mit dem GWT nicht auskennst?


----------



## Wildcard (29. Apr 2010)

Neuer Thread schadet sicherlich nicht da ich noch nie GWT verwendet habe und sich viele einen Thread mit so vielen Antworten wohl gar nicht ansehen werden...


----------



## Wildcard (29. Apr 2010)

Das hier könnte übrigens Interessant für dich sein:
eclipse-dev: EMF + Databinding + GWT 1.5 - it works


----------



## kidsos (29. Apr 2010)

So, ich denke, dass ich diesen Thread jetzt als "erledigt" markieren kann, da das eigentliche Problem nun gelöst ist.

Vielen Dank nochmal


----------

