# Objektstruktur aus XML-Datei erzeugen



## JanHH (15. Okt 2009)

Hallo, 

die Frage mag jetzt etwas anfängerhaft erscheinen, trotzdem stelle ich sie. Für ein Softwareprojekt, welches eine gewisse Programmierbarkeit der Anwendung erfordert, scheint es mir die einfachste Lösung, eine interne Objektstruktur (bzw. eigentlich sogar Dokumentstruktur) aus einer XML-Datei zu erzeugen. Gibt es dafür irgendwelche automatischen Verfahren, oder sollte man einen SAX-basierten XML-Parser nehmen, der mit den entsprechenden callback-Funktionen, die Funktionen meiner Objekte, die das dann "per Hand" zusammenbauen, den Kram zusammenbaut? Oder was fällt euch da spontan zu ein?

Es handelt sich da um ein nebenbei-Hobbyprojekt, welches aber, wenn es gut wird, durchaus eine grosse Zukunft haben könnte. Daher suche ich eine Lösung, die mit möglichst wenig aufwand möglichst viel automatisch macht (wobei - sowas such wir Programmierer ja immer  ).

Gruß+Danke
Jan


----------



## Wildcard (15. Okt 2009)

Nun, dann ist meiner Meinung nach EMF das richtige für dich. Wenn du ein Schema zu deiner XML hast erzeugt dir EMF ein extrem leistungsfähiges Modell inklusive XML Binding und vieler extras.
Es gibt auch eine Sparvariante von XML Binding, das wäre dann zB JaxB. Damit bekommst du ein XML Binding und ein Java Modell (das allerdings aus nichts weiter als dummen Datencontainern besteht).
Also mein Tipp ist definitiv EMF, da es dir in praktisch jedem Software Projekt viel Arbeit abnehmen kann, selbst wenn kein XML im spiel ist. Eine gewisse Einstiegshürde musst du allerdings meistern...


----------



## JanHH (15. Okt 2009)

Klingt auf jeden Fall beides interessant, wobei das JaxB-Ding schon ausreichend sein dürfte.

Generell soll das Projekt so aufgebaut sein, dass möglichst viele Standard-Frameworks und -tools benutzt werden können (also auf jeden Fall JSF, Seam, JPA), und XML für die Dokumentstruktur kommt mir da wie eine gute Ergänzung vor. Vermutlich gibt es jede Menge Tools, die einem viel abnehmen, wenn man einmal ein XML-Schema für die Dokumentstruktur entwickelt hat? Also auch visuelle Editoren, mit denen man die XML-Dokumenten auf Basis dieses Schemas "zusammenklicken" kann? Wie gesagt, bin ziemlich unerfahren mit dem Thema, daher die Fragen.


----------



## Wildcard (15. Okt 2009)

Aus EMF Modellen lassen sich sehr unterschiedliche Dinge vollautomatisch erzeugen. grafische (Diagramm) Editoren, Baum Editoren, textuelle Editoren,... (die sind allerdings Eclipse RCP basiert)
Wie gesagt, schau es dir vielleicht einfach mal an. In EMF Modelle kannst du Business Logik unterbringen (die ein gutes Modell haben sollte), validieren, queries, hast eine tolle Observer Schnittstelle. Ausserdem gibt es Bindungs zu anderen Persistenzschichten wie zB Hibernate, du kannst dir Unit Test automatisch generieren lassen, hast Databinding Support für die UI, automatischen Undo/Redo Support, Transaktionssupport,...
Ich halte EMF schon alleine deshalb für den besseren Ansatz, weil sich das Modell selbst konsistent hält.
JaxB sind wirklich nur Java Klassen mit gettern und settern, ohne jede Logik oder komfort.
Aber naja, du musst selbst entscheiden was für dich das richtige ist.


----------



## JanHH (15. Okt 2009)

Ich wills einfach erstmal vorsichtig angehen lassen .


----------



## JanHH (16. Okt 2009)

Auf jeden Fall natürlich Danke!


----------



## JanHH (16. Okt 2009)

Hab JAXB mal überflogen, und dazu gleich eine Frage:

Kann ich die XML-Datei mit JAXB nur auf die vom Schema Compiler generierten Klassen mappen lassen, sondern auch auf eigene? Die default-Klassen sind ja eher inhaltsleer, ich will natürlich, dass aus der XML-Datei ein "richtiges" Dokument mit der geforderten Funktionalität erzeugt wird. Wenn das geht, dann hab ich ja eigentlich das, was ich brauche..

Aber jetzt erstmal ein Blick auf EMF.


----------



## Wildcard (16. Okt 2009)

Richtig, es wird auf die generierten Klassen gemappt, die, wie du ja bemerkt hast, recht leer sind (nur getter und setter).
Mit EMF mappst du zwar auch auf generierte Klassen, kannst allerdings beliebig Methoden hinzufügen und automatisch generierten Code mit händischem Code mischen.


----------



## JanHH (18. Okt 2009)

Danke auf jeden Fall für den EMF-Tipp, das scheint wirklich das perfekte zu sein für das, was ich machen will. Ich fand die Einstiegshürde auch nicht so wahnsinnig hoch, ein paar Stunden Tutorials lesen und basteln, und dann geht schon einiges.

Eine Frage allerdings ist wichtig: In meiner Applikation sind eine Menge Baumstrukturen vorhanden, deren Knoten (composite-pattern) jeweils Unterklassen einer abstrakten Knotenklasse sind. Das ist ja eigentlich nichts besonders exotisches, trotzdem noch mal ein Beispiel: Ein Knoten ist entweder ein Objekt der Klasse ListenKnoten (welcher eine Liste weiterer Unterknoten darstellt) oder ein FinalerKnoten (welcher ein tatsächliches Datenobjekt darsatellt). Die gemeinsame Oberklasse von beiden sei AbstrakterKnoten. Also wie im Windows Explorer, jeder Knoten ist ja ein Verzeichnis (ListenKnoten) oder eine Datei (FinalerKnoten).

Ich nehme an, EMF eignet sich auch für sowas? Mir ist bisher nur nicht ganz klar, wie, bzw wie man das per xml-Tags realisieren soll, wenn ein Tag 1:1 auf eine Klasse gemappt wird. Als abstraktes Beispiel könnte ich mir das so vorstellen, es gibt einen Knoten-Tag, und ein type-Attribut, welcher die Art angibt:

```
<AbstrakterKnoten type="liste"
   <AbstrakterKnoten type="final">
      .. irgendwelche Daten
   </AbstrakterKnoten>
   <AbstrakterKnoten type="final">
      .. irgendwelche Daten
   </AbstrakterKnoten>
   <AbstrakterKnoten type="final">
      .. irgendwelche Daten
   </AbstrakterKnoten>
   <AbstrakterKnoten type="final">
      .. irgendwelche Daten
   </AbstrakterKnoten>
</AbstrakterKnoten>
```

Also, geht sowas? Kann mir allerdings kaum vorstellen dass es nicht geht, weil sowas ja nun eine absolute Standardstruktur in Datenmodellen ist..


----------



## Wildcard (19. Okt 2009)

Die XML Serialisierung ist weitgehend über eAnnotations im Modell steuerbar. Interessanter ist an der Stelle eher das Modell selbst. Vererbung und auch Mehrfachvererbung sind möglich und damit ist dein Use-Case ja eigentlich abgedeckt.
Da du anscheindend eine spezielle XML Syntax im Sinn hast, würde ich empfehlen ein entsprechendes Schema zu bauen und dann aus dem Schema das Ecore erzeugen zu lassen.
Vererbung würde beispielsweise durch eine Substitution Group ausgedrückt werden.


----------



## JanHH (19. Okt 2009)

Eine spezielle XML-Syntax war nur eine Idee, keine Notwendigkeit. Wichtig ist eigentlich nur, dass es schnell und effizient geht. Ein Dokument mit dem automatisch erzeugten Editor zu erzeugen ist für den Anfang ausreichend. Für das Erstellen des Modells scheint mir die Variante mit den annotierten Interfaces am einfachsten, ausserdem kann ich das schon und muss mich da nicht auch noch extra einarbeiten (was bei XML-Schemata der Fall wäre) . Die nächste Hürde, die es zu überwinden gilt, ist das Einbinden des EMF-Modells in ein JEE-Seam-Projekt, weil das ganze ja eine Webapplikation werden soll. Aber vermutlich kann man EMF in andere Umgebungen einbiden, weils ja sonst eigentlich eher sinnlos wäre !?


----------



## Wildcard (19. Okt 2009)

Am einfachsten finde ich eigentlich den EMF Ecore Editor (ist ein mit EMF erzeugter Baumeditor um Ecore Dateien direkt zu erstellen). Damit musst du dann keinen Code schreiben. Aber Java Interfaces funktioniert natürlich auch.
Klar, EMF kannst du standalone verwenden, du brauchst nur ein paar Eclipse jars (die sind auch in der EMF Hilfe angegeben wenn ich mich nicht irre).


----------



## JanHH (19. Okt 2009)

Gute Sache zumindest. Vielen Dank!


----------



## Wildcard (19. Okt 2009)

Hier die Dependencies.


----------



## JanHH (26. Okt 2009)

Eine weitere Frage stellt sich ein.. Wenn man also das EMF-Model erfolgreich erzeugt hat, einen rudimentären Eclipse-Editor dafür, und mit diesem dann ein konkretes Modell erstellt, welches als XML-Datei gespeichert wird.. und dieses dann in seiner stand alone-Application laden will. Dafür gibts dann z.B. in Tutorials den Code


```
URI fileURI = URI.createFileURI(new File("mylibrary.xmi").getAbsolutePath());
Resource resource = resourceSet.getResource(fileURI, true);
```

Nun kenne ich mich aber weder mit URIs besonders gut aus, noch habe ich den XML-Code in meiner Applikation als Datei vorliegen, sondern in einem String, welcher per JPA aus einer Datenbank geladen wird. Da das ganze innerhalb eines Application Servers laufen soll, sind Dateien auch definitiv keine Lösung, die brauchbare wäre.

Wie geht denn sowas? Sofern das überhaupt geht? Wobei ich mir eigentlich nicht vorstellen kann, das es nicht geht?


----------



## Wildcard (26. Okt 2009)

Ist ganz einfach. Du erzeugst eine URI die deine Resource irgendwie identifiziert (irgendeine, die muss nirgends hinzeigen, das dient nur als Identifier). Dann Rufst du auf dieser Resource.load mit einem InputStream aus. Fertig. Damit die richtige Resource Factory verwendet wird, sollte die URI zu der Dateiendung passen die du am ResourceSet registriert hast.


----------



## JanHH (27. Okt 2009)

Danke für die Antwort, immerhin gut zu wissen dass es einfach geht. Allerdings kann ich nicht viel damit anfangen ohne mich da vorher erstmal eingearbeitet zu haben. Aber klingt ja grundsätzlich nicht so kompliziert.


----------



## Wildcard (27. Okt 2009)

Viele Wege führen nach Rom, das ist einer davon:

```
//registriert all file endings auf deine resource factory
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*", new
YourGeneratedResourceFactory());
//Resources leben normalerweise in einem ResourceSet, ist aber kein requirement
ResourceSet resourceSet = new ResourceSetImpl();
URI uri = new URI("doesn't/really/matter/only/an/ID/in/your/case");
//deine factory ist auf alle file (URI) endings registriert, also wird EMF deine Factory verwenden um die richtige Resource zu erzeugen
//diese Resource ist noch leer
Resource resource = resourceSet.createResource(uri);
//Deine generierte XText Resource weiß automatisch wie sie sich aus der textuellen Repräsentation laden kann
resource.load(yourInputStream, Collections.EMPTY_MAP);
YourModel model = (YourModel)resource.getContents().get(0);
```


----------



## JanHH (28. Okt 2009)

danke danke!


----------



## JanHH (29. Okt 2009)

Ich komme halbwegs voran, aber was mir unklar ist.. in dem Codebeispiel... was genau ist "YourGeneratedResourceFactory"?

Also angenommen mein EMF-Projekt heisst ABC.. dann habe ich dort generiert bekommen: Ein Interface ABCFactory, und eine Klasse ABCFactoryImpl. Wenn ich aber letztgetnannte verwendet an dieser Stelle, kommt ein Fehler:

java.lang.ClassCastException: ABC.impl.ABCFactoryImpl cannot be cast to org.eclipse.emf.ecore.resource.Resource$Factory

Bin nun wieder ratlos.


----------



## Wildcard (29. Okt 2009)

Wurde dir keine ABCResourceFactoryImpl generiert? Ich habe gerade kein Beispielprojekt zur Hand. Es geht auch anders, müsste ich allerdings erst nachschlagen. Du kannst aber einfach das Interface selbst in einer Klasse implementieren AFAIR musst du nur eine createResource(URI) Methode implementieren und dort dann einfach deine ABCResource instanzieren.


----------



## JanHH (30. Okt 2009)

Es gibt nur eine Stelle im eclipse-Projekt, wo der Suchstring *ResourceFactoryImpl* auftaucht, und das ist im test-Package:

		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put
			(Resource.Factory.Registry.DEFAULT_EXTENSION, 
			 new XMIResourceFactoryImpl());

Aber ich hab ja jetzt auch das EMF-Buch, das wird schon.. zumindest hat EMF einen Fan mehr. Danke nochmal für den Hinweis.


----------

