# xsd->java  mit Eclipse?! oder wie?



## dermoritz (14. Sep 2010)

dies ist eines der wenigen Dinge wo ich mehr Erfahrung mit C# habe: die Erzeugung von Klassen aus XSD-Dateien. Bei c# gibts eine xsd.exe der man einfach eine xsd-Datei und einen Klassennamen übergibt und schwupps hat man Code.

Gibt es etwas ähnlich einfaches für Java oder besser gleich Eclipse (Rechtsklick auf xsd-> "generate Class(es))? 

Googeln hat nur bedingt geholfen: man findet JAXB - das schein aber etwas sehr kompliziertes zu sein (in meinem Fall mit Kanonen auf spatzen geschossen?!). Dann findet man für Eclipse "xjc Eclipse Plugin" und "XMLBeans plugin" aber beide scheinen mehr oder weniger tote Projekt zu sein?! Dann findet man noch ein Maven Plugin das wohl sowas kann.

Bei Java setzen sich normalerweise für bestimmte Use-Cases "Quasistandards" durch. Wie sieht es denn hier aus? Wie generiert man Java-Code aus XSD "normalerweise"?


----------



## fastjack (14. Sep 2010)

> man findet JAXB - das schein aber etwas sehr kompliziertes zu sein (in meinem Fall mit Kanonen auf spatzen geschossen?!



ne ne, ist ganz easy!

Einbindung des Tasks in ANT:
[XML]
    <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
        <classpath>
            <fileset dir="PFAD_ZU_JAXB" include="jaxb-xjc.jar" />
        </classpath>
    </taskdef>
[/XML]

Benutzung:
[XML]
        <xjc schema="NAME_DER_XSD_DATEI" destdir="./tmp/generated" removeOldOutput="yes" extension="yes"/>
[/XML]

Es gibt dazu auch sehr viele Tutorials.

Zu Eclipse, schau mal hier:

https://jaxb-workshop.dev.java.net/plugins/eclipse/xjc-plugin.html


----------



## dermoritz (14. Sep 2010)

Danke, ich bin gerade schon dabei das xjc-Plugin zu testen (xjc ist quasi das Analogon zur xsd.exe ).  
Dabei ist mir gleich ein grundsätzliches Problem aufgefallen: beim einlesen ("unmarshalling") muss man jaxb miteilen was denn das Rootelement sein soll.
(das Problem wird hier Java Technology & XML - JAXB ClassCastException und hier https://jaxb.dev.java.net/guide/_XmlRootElement_and_unmarshalling.html beschrieben)
Ich hab mich mal für letzteres entschieden also die unmarshall-Methode mit source und class. Ist das ok? oder kann man das Problem besser umgehen?


----------



## Wildcard (14. Sep 2010)

Nimm EMF. Ist wesentlich besser als JAXB und du kannst alles in der Eclipse Oberfläche (also ohne Ant Tasks) erledigen.
Eclipse Modeling - EMF - Home


----------



## dermoritz (15. Sep 2010)

Zu diesem Schluss bin ich auch grad gekommen. (wieso weiß google das nur noch nicht - wenn man xsd to jav googelt ist emf ziemlich weit unten)
Gibts für meinen speziellen use-case (xsd<->java) eine art tutorial? Soweit ich verstanden habe werde ich für diesen Zweck nur an der EMF-Oberfläche kratzen.
Erstmal werde ich nur "EMF - SDK 2.6" per update Manager in Eclipse laden oder? - nochwas?

EDIT: (für xsd reicht nicht emf. der xsd model importer muss auch installiert werden.)

Inzwischen hab ich meine xsd in Java-Code verwandelt - nur was mach ich damit?! Erstmal hab ich keine Ahnung wie ich den benutze und 2. wie bekomme ich etwas, was ich in einem Maven-Project verwenden kann?! Ich kann nicht zufällig den ganzen EMF kram auch in einem Maven-Projekt verwenden? - das stört mich bei Eclipse- dass man für bestimmte use-cases andere "Projektsorten" braucht und die sind natürlich nicht "kompatibel".

gibt es irgendwie einen minimal Ansatz: xsd->java->benutzen in maven project


----------



## fastjack (15. Sep 2010)

> Zu diesem Schluss bin ich auch grad gekommen. (wieso weiß google das nur noch nicht - wenn man xsd to jav googelt ist emf ziemlich weit unten)
> 
> Gibts für meinen speziellen use-case (xsd<->java) eine art tutorial? Soweit ich verstanden habe werde ich für diesen Zweck nur an der EMF-Oberfläche kratzen.
> Erstmal werde ich nur "EMF - SDK 2.6" per update Manager in Eclipse laden oder? - nochwas?
> ...



Es ist besser, aber nicht einfacher  Du kannst Dir aber mal die Tutorials von Lars Vogel (vogella) ansehen, findest Du bei Google. (vogella eclipse emf)



> Inzwischen hab ich meine xsd in Java-Code verwandelt - nur was mach ich damit?! Erstmal hab ich keine Ahnung wie ich den benutze und 2. wie bekomme ich etwas, was ich in einem Maven-Project verwenden kann?! Ich kann nicht zufällig den ganzen EMF kram auch in einem Maven-Projekt verwenden? - gibt es irgendwie einen minimal Ansatz: xsd->java->benutzen in maven project



Für XJC/XSD gibt es ein Maven-Plugin (auch Google).



> das stört mich bei Eclipse- dass man für bestimmte use-cases andere "Projektsorten" braucht und die sind natürlich nicht "kompatibel".



Das ist der "Vorteil" einer IDE...


----------



## dermoritz (15. Sep 2010)

"Das ist der "Vorteil" einer IDE... " - ich finde Netbeans löst das schöner. da kann ich unabhängig von einer Projektstruktur z.B. JPA-Code generieren - unabhängig von einem "JPA-Project" wie in Eclipse.
Und nun kann ich eben nicht einfach EMF benutzen um mir Klassen zu erzeugen die einfach in einem Maven-Projekt landen.

Wie auch immer das vogella Tutorial hab ich gelesen - dort wird beschrieben wie man ein eigenes (Meta)Modell bastelt. Wie man dann den Code benutzt wird auch angerissen - das nützt mir aber alles nix.

Wenn ich nach XJC/XSD Maven Plugin google finde ich nur JAXB basierte Geschichten, aber Jaxb ist unbrauchbar für mich (http://www.java-forum.org/xml-co/105875-jaxb-validierung-verification-marshalling.html)

Also hat schon mal jemand emf benutzt um eine Api zu erzeugen mit der man xml liest/und schreibt (basierend auf einer xsd-Datei). Eigentlich will ich es sofort nach der Codegenerierung von Eclipse lösen - also wie benutzt man den EMF-generierten Code unabhängig von Eclipse. Endziel wär ein Mavenmodul welches ein Artefakt ausspuckt und dieses Artefakt beinhaltet alle EMF Abhängigkeiten und eben die XML-Api.


----------



## fastjack (15. Sep 2010)

"Vorteil" war bewußt in Anführungszeichen  Mich nervt das ganze hin und her Geklicke auch und am Ende kann man nix mehr ohne IDE machen...


----------



## Wildcard (15. Sep 2010)

> Inzwischen hab ich meine xsd in Java-Code verwandelt - nur was mach ich damit?! Erstmal hab ich keine Ahnung wie ich den benutze und 2. wie bekomme ich etwas, was ich in einem Maven-Project verwenden kann?! Ich kann nicht zufällig den ganzen EMF kram auch in einem Maven-Projekt verwenden? - das stört mich bei Eclipse- dass man für bestimmte use-cases andere "Projektsorten" braucht und die sind natürlich nicht "kompatibel".



Wie man es benutzt? Es führen viele Wege nach Rom, einer davon ist dieser:

```
Resource resource = new DeineResourceImpl();
resource.load(new FileInputStream("file.xml"),null);
DeinRootElement root = resource.getContents().get(0);
```

Du brauchst keinen speziellen Projekttyp um EMF Modelle zu erstellen, insofern ist das auch kein Problem mit Maven.



> Also hat schon mal jemand emf benutzt um eine Api zu erzeugen mit der man xml liest/und schreibt (basierend auf einer xsd-Datei). Eigentlich will ich es sofort nach der Codegenerierung von Eclipse lösen - also wie benutzt man den EMF-generierten Code unabhängig von Eclipse. Endziel wär ein Mavenmodul welches ein Artefakt ausspuckt und dieses Artefakt beinhaltet alle EMF Abhängigkeiten und eben die XML-Api.



Hier steht welche Abhängigkeiten man in Standalone Anwendungen braucht:
EMF/FAQ - Eclipsepedia


----------



## dermoritz (16. Sep 2010)

Danke für die Hinweise...

"Du brauchst keinen speziellen Projekttyp um EMF Modelle zu erstellen, insofern ist das auch kein Problem mit Maven."

aber wie geht das? Irgendwie ist das einzige was ich in Eclipse gefunden habe nach der emf Installation ein neuer Projekttyp. Und alle Tutorials starten auch mit einem EMF Projekt. Ansich wäre das nicht so schlimm wenn ich genau wüsste was ich wohin vom genrierten Kram in ein Eclipse-Projekt kopieren muss und welche Abhängigkeiten ich brauche.
Einfacher wäre es irgendwie emf einfach auf eine xsd-loszulassen und generieren zu lassen - geht das aus Eclipse heraus? oder gibt es externe Tools?

Danke auch für den Link zu Eclipspedia: dort wird ja explizit auf EMF 2.3 verwiesen. Das ist auch das aktuellste was man in Maven-Repositories findet. Muss man sich da Sorgen um die Kompatibilität zu 2.6 machen (aktuelle Version in Eclipse)?!

Edit: ich glaub ich hab schon eine Inkompatibilität festgestellt "The method getResourceLocator() is undefined for the type EObjectValidator"
Und tatsächlich diese Methode gibts in Version 2.3 des ecore nicht in Version 2.6 schon. :-|
Was mach man da - die aktuellen Versionen downloaden und dem Mavenprojekt zur Verfügung stellen oder irgendwie 2.3 benutzen?! Wieso gibts 2.6 eigentlich noch nicht in Mavenrepositories?


----------



## Wildcard (17. Sep 2010)

> aber wie geht das? Irgendwie ist das einzige was ich in Eclipse gefunden habe nach der emf Installation ein neuer Projekttyp. Und alle Tutorials starten auch mit einem EMF  Projekt. Ansich wäre das nicht so schlimm wenn ich genau wüsste was ich wohin vom genrierten Kram in ein Eclipse-Projekt kopieren muss und welche Abhängigkeiten ich brauche.
> Einfacher wäre es irgendwie emf einfach auf eine xsd-loszulassen und generieren zu lassen - geht das aus Eclipse heraus? oder gibt es externe Tools?


Du brauchst kein spezielles Projekt. Leg in irgendeinem Projekt ein neues Genmodel an und wähle im Wizard ein XSD Schema als Input aus.
Wohin das ganze generiert wird bestimmen die Einstellungen im genmodel.




> Danke auch für den Link zu Eclipspedia: dort wird ja explizit auf EMF 2.3 verwiesen. Das ist auch das aktuellste was man in Maven-Repositories findet. Muss man sich da Sorgen um die Kompatibilität zu 2.6 machen (aktuelle Version in Eclipse)?!
> 
> Edit: ich glaub ich hab schon eine Inkompatibilität festgestellt "The method getResourceLocator() is undefined for the type EObjectValidator"
> Und tatsächlich diese Methode gibts in Version 2.3 des ecore nicht in Version 2.6 schon. :-|
> Was mach man da - die aktuellen Versionen downloaden und dem Mavenprojekt zur Verfügung stellen oder irgendwie 2.3 benutzen?! Wieso gibts 2.6 eigentlich noch nicht in Mavenrepositories?


Mach doch einfach deine eigene pom für die 2.6 Version


----------



## dermoritz (20. Sep 2010)

vielen Dank, dass man einfach so ein "genmodel" anlegen kann wusste ich nicht - praktisch. und was Version 2.6 betrifft, bin ich genau so verfahren. ich hab mir in mein 3rd-Party Repository die aktuellen Versionen reingestellt.

Edit: ich hab mal noch eine Frage zum generierten Code: Kann man irgendwie das Zielpaket beeinflussen? Standardmäßig wird dafür irgendwie der Targetnamespace verwendet. Aber wie dieser zu einem Paket uminterpretiert wird ist irgendwie eigenartig bzw. zumindest nicht sehr transparent ("CamelCase" landet z.b. in einem Paket camel.case). Gibt es einen Eintrag in den Properties von genmodel oder wo anders?

Edit: habs glaube gefunden - "Base Package" eine Ebene unter "genmodel". Nun wäre noch interessant zu wissen ob man den root Pfad für den generierten Code ändern kann, als nach "src/main/java", dann wäre es direkt mavekompatibel.


----------



## dermoritz (20. Sep 2010)

Wildcard hat gesagt.:


> Wie man es benutzt? Es führen viele Wege nach Rom, einer davon ist dieser:
> 
> ```
> Resource resource = new DeineResourceImpl();
> ...



Irgendwie funktioniert das nicht so - bei mir gibts nur ein "new DeineResourceImpl(URI);" und mit null lässt sich das nicht füttern. Ich hab es jetzt so gemacht wie es der generierte Test Code macht:
[Java]
private static ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION, new MeineResourceFactoryImpl());
		resourceSet.getPackageRegistry().put(MeinePackage.eNS_URI, MeinePackage.eINSTANCE);
		URI xmlFile=URI.createURI(TestXmlImport.class.getResource("meins.xml").toURI().toString());
		resource = resourceSet.getResource(xmlFile,true);
...
[/code]
das läuft aber deins find ich irgendwie eleganter wildcard, vorallem weiß ich nicht wofür ich ein Resource SET baruche.


----------



## Wildcard (20. Sep 2010)

> Nun wäre noch interessant zu wissen ob man den root Pfad für den generierten Code ändern kann, als nach "src/main/java", dann wäre es direkt mavekompatibel.


Ja, auch das kannst du im genmodel einstellen.


> Irgendwie funktioniert das nicht so - bei mir gibts nur ein "new DeineResourceImpl(URI);" und mit null lässt sich das nicht füttern


Richtig, die URI hatte ich unterschlagen. Welche URI du übergibst ist völlig egal wenn du load mit InputStream aufrufst. Falls du Dateibasiert arbeitest kannst du einfach URI.createFileURI verwenden.


> das läuft aber deins find ich irgendwie eleganter wildcard, vorallem weiß ich nicht wofür ich ein Resource SET baruche.


Das ResourceSet erfüllt zwei Aufgaben:
1. Du musst nicht wissen welche konkrete Resource verwendet wird, das herauszufinden wird an die Registry delegiert
2. Wenn du Resourcen hast die Objekte aus andere Resourcen referenzieren dann müssen sie im gleichen ResourceSet liegen damit du Transaktionen verwenden kannst und um sinnvoll serialisieren zu können.


----------



## dermoritz (21. Sep 2010)

Vielen dank Wildcard!

du weißt nicht zufällig wo im Genmodell (also in welcher ebene und welche Property) man den Zielpfad einstellt?!

Das mit der Laderei hab ich nun so hingekriegt:

```
URI xmlFile=URI.createURI(TestXmlImport.class.getResource("/mein.xml").toURI().toString());
Resource resource = new MeineResourceImpl(xmlFile);
```
also es funktioniert auch ohne "resource.load". Mit load könnte ich dann einfach falls nötig eine neue XML-Datei reinladen, oder? Wenn nicht wäre load ja irgendwie sinnlos?!

Das mit dem Resourceset hab ich nicht ganz verstanden - werd ich wohl mal irgendwo nachlesen oder spätestens wenn mans braucht verstehen. Ich brauche ResourceSet nicht um (einfache)xml zu serialisieren oder deserialiseren oder?

EDIT: hab mich geirrt das (Resource resource = new MeineResourceImpl(xmlFile) funktioniert nicht. Damit gibt "resource.getContents()" immer eine leere Liste zurück. Auch ein resource.load(null); hat nix geholfen. 
mit "resource = resourceSet.getResource(xmlFile,true);" und dem ResourceSet-Kram funktioniert es.


----------



## Wildcard (21. Sep 2010)

> du weißt nicht zufällig wo im Genmodell (also in welcher ebene und welche Property) man den Zielpfad einstellt?!


In der Model Section -> Model Directory



> Ich brauche ResourceSet nicht um (einfache)xml zu serialisieren oder deserialiseren oder?


Nein, brauchst du nicht. Ein ResourceSet ist einfach ein Container für mehrere Resourcen.


----------



## dermoritz (21. Sep 2010)

Danke nochmal,

mit dem Resourceset ist nur das blöde, dass ich nur so das xml Laden kann und anschließend "getContents()" nicht leer ist. 

Aber mal davon abgesehen wie ich an eine Resource mit Inhalt komme: Was mache ich dann damit, also wie komme ich an die einzelnen Elementen und deren getter und setter?

Bei den settern wäre noch gut zu wissen ob die automatisch überwacht werden (also die Überprüfung der Konsistenz mit dem Modell) oder ob man das "anschalten" muss.


----------



## Wildcard (21. Sep 2010)

> mit dem Resourceset ist nur das blöde, dass ich nur so das xml Laden kann und anschließend "getContents()" nicht leer ist.


Es geht auch ohne, du machst es nur falsch.

```
new Resource(URI.createFileURI(new File("path").getAbsolutPath());
```



> Aber mal davon abgesehen wie ich an eine Resource mit Inhalt komme: Was mache ich dann damit, also wie komme ich an die einzelnen Elementen und deren getter und setter?





> YourRootElement root = (YourRootElement)resource.getContents().get(0);
> Foo foo = root.getFoo();


usw. 
ist ganz normaler Java Code.
Wie die Methoden und Klassen bei dir heißen kann ich natürlich nicht wissen, da ich dein Modell ja nicht kenne.


> Bei den settern wäre noch gut zu wissen ob die automatisch überwacht werden (also die Überprüfung der Konsistenz mit dem Modell) oder ob man das "anschalten" muss.


Nein, das funktioniert voll automatisch.
Wenn du zB eine Parent Child Beziehung modelierst dann sorgt EMF dafür das alles konstent bleibt. Wenn du auf dem Child einen neuen Parent setzt wird im Parent die Children Liste entsprechend aktualisiert. Wenn du im Parent die Children Liste veränderst wird automatisch die Parent Reference im Child korrigiert usw.
Vorraussetzung dafür ist natürlich das du korrekt modelliert hast, also Containment, Container und EOpposite an den richtigen Stellen verwendet hast.
Da du eine XSD verwendet hast liegen vermutlich keine EOpposites vor und Containment/Container wurde automatisch aus der XSD berrechnet. Sollte also alles schon passen


----------



## dermoritz (22. Sep 2010)

Und nochmal danke,


YourRootElement root = (YourRootElement)resource.getContents().get(0);

das ist genau das was ich wissen wollte - irgendwie hat mich die Autovervollständigung in Eclipse nicht mit der Nase ins "get()" gedrückt ;-)

Zu den Verifikationen - meine stamen wie du sagst aus dem xsd. es sind "constraints" z.b. reguläre ausdrücke enums usw. Wenn man beim Einlesen verifizieren will muss man ja sowas machen:


```
for (EObject eObject : resource.getContents()) {
		Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
		if (diagnostic.getSeverity() != Diagnostic.OK) {
			System.out.println(ParseWrapperUebergabe.printDiagnostic(diagnostic, ""));
		}
}
```
so macht es zumindest der Beispielcode("printDiagnostic" findet man auch im Beipsiel/Testcode). Da frag ich mich, falls man das nicht macht kann man dann ein invalides Objekt haben oder wird spätestens beim cast auf mein Root element (...get(0)) irgendeine Art von Exception ausgelöst?

EDIT: Die Validierung ist doch nicht ganz so automatisch: Ich hab gerade probiert einen Wert auf einen laut XSD invaliden Wert zu setzen - das hat leider funktioniert. Nun ist die Frage wie man hinkriegt, dass sobald das EObject nicht mehr dem Modell genügt eine Exception ausgelöst wird.
ich hab schon etwas rumgelesen und mir die Implementierung der Setter angeschaut: dort gibt es immer ein

```
if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ...
```
Irgendwie kann/muss man einen "Observer" registrieren. Das kann man wohl auch global auf dem Wurzelelement machen?! Und dann wird einem wohl bei jeder Objektänderung irgendwas mitgeteilt?! Weiß jemand wie das geht?


----------



## Wildcard (22. Sep 2010)

> Da frag ich mich, falls man das nicht macht kann man dann ein invalides Objekt haben oder wird spätestens beim cast auf mein Root element (...get(0)) irgendeine Art von Exception ausgelöst?


EMF wird soviel Parsen wie irgend möglich, die Resource kann also auch invalide Objekte enthalten. Wenn beim einlesen ein Problem auftritt wird dieses Problem in der Resource vermerkt resource#getWarnings und resource#getErrors

Wenn du bei jeder Änderung validieren möchtest (würde ich mir gut überlegen, mit dem Modell zu arbeiten wird dann recht teuer...), dann ist ein Observer tatsächlich das Schlagwort.
Jedes EMF Objekt füllt eine komplette Observer Schnittstelle aus, du musst also nur noch einen Listener anhängen.
Grundsätzlich funktioniert das entweder über die AdapterFactory, oder direkt mit

```
eObject.eAdapters().add(new YourAdapter());
```
Wenn du einen einzigen Listener verwenden möchtest der über alle Änderungen des gesamten Objektbaums (oder eines Teilbaums) informiert wird, dann hilft dir der EContentAdapter. Dieser Adapter fügt sich rekursiv allen Kindern des EObjects hinzu und aggregiert damit alle Change Events.
Der EContentAdapter hat auch kein Problem damit wenn zur Laufzeit neue Kinder hinzukommen, oder Kinder entfernt werden, das funktioniert alles automatisch.


----------



## dermoritz (23. Sep 2010)

"würde ich mir gut überlegen, mit dem Modell zu arbeiten wird dann recht teuer..."

jetzt muss mal etwas ausholen:
eigentlich war für mich der Hauptgrund dafür generierten Code zu benutzen um möglichst immer nah am Modell zu sein - natürlich insbesondere wenn man die Objekte bearbeitet. Setter-Code generieren der nur "setzt" kann eben auch eclipse von selbst, oder?
Oder anders gefragt: bei handgemachtem Code würde man doch in die Setter bestimmte Prüfungen einbauen die ggf. eine illegal Argument Exception werfen?! Nun frag ich mich wie man in die Nähe dieser Funktionalität bei generiertem Code kommt - wie machst du das zum Beispiel Wildcard?

Andererseits, da ich nun schon für meine Verhältnisse sehr viel über EMF gelernt habe würde ich gerne die Sache mit dem "EContentAdapter" ausprobieren. Das scheint ja unabhängig von meinem Modell zu funktionieren?!
Also das 

```
root.eAdapters().add(new EContentAdapter());
```
hab ich mal gemacht - und nun? Also ich hätte nun gerne die Information ob das eObjekt noch dem Modell genügt.


----------



## Wildcard (23. Sep 2010)

> Oder anders gefragt: bei handgemachtem Code würde man doch in die Setter bestimmte Prüfungen einbauen die ggf. eine illegal Argument Exception werfen?! Nun frag ich mich wie man in die Nähe dieser Funktionalität bei generiertem Code kommt - wie machst du das zum Beispiel Wildcard?


Nein, das würde ich nur zu einem gewissen Grad machen. Viele Validierungsregeln stehen in Bezug zu mehr als einem Element. Da du aber immer nur einen Wert gleichzeitig manipulieren kannst muss dein Modell in der Lage sein temporär während der Bearbeitung einen ungültigen Zustand anzunehmen.
Sehr einfache Dinge (z.B. null ist als Parameter nicht erlaubt) kann man natürlich so behandeln, aber echte Validierungslogik sollte man in einen Validator auslagern.
Wenn man einen solchen Validator hat will man ihn nicht bei *jeder* Modelländerung antriggern, denn das kann sehr teuer sein. Stell dir vor Eclipse würde bei jedem einzelnen Keystroke im Java Editor kompilieren und validieren...
Ich würde die Validierung also eher an Usereingaben koppeln, oder zu bestimmten Zeitpunkten triggern (speichern, laden,... hängt vom angestrebten Workflow ab).
Stell dir mal vor du validierst wirklich bei jeder Modelländerung:
Früher oder später wirst du vielleicht automatisiert ein komplettes Modell im Speicher erstellen.
Was ist jetzt sinnvoller, das dein Modell bei jedem setXXX validiert, oder das es einmal validiert wenn du fertig bist?



> Andererseits, da ich nun schon für meine Verhältnisse sehr viel über EMF gelernt habe würde ich gerne die Sache mit dem "EContentAdapter" ausprobieren. Das scheint ja unabhängig von meinem Modell zu funktionieren?!


Richtig, die Adapter funktionieren auf jedem EMF Modell.


> Also das
> 
> ```
> root.eAdapters().add(new EContentAdapter());
> ...


Einfach einen EContentAdapter zu instanzieren bringt noch nicht viel. Das wäre das gleiche wie wenn du in Swing einen leeren MouseAdapter registrierst.
Du musst die notifyChanged Methode überschreiben. Dort wirst du über *jede* Änderung im Modell informiert.


----------



## dermoritz (24. Sep 2010)

ohh vielen Dank jetzt schnall ich's langsam - glaube ich: man baut sich ein Api um das Ecore Modell/xml-lesen/schreiben herum, welche gute Zeitpunkte zum validieren des Modells finden/wissen muss. Nicht zu oft sonst wird's zu langsam aber häufig genug um damit der User der Api schnell weiß wo er den Fehler gemacht hat. (das Beispiel mit Eclipse war echt gut )

Nun hab ich schon irgendwo Beispiele gefunden wie man die notifyChanged Methode überschreibt. Was mir noch fehlt (hab ich nirgends gefunden) ist Code wie man da die Klasse Diagnostician (oder so ähnlich) bzw. Validator verwendet. (die sind doch dafür Zuständig irgendwie oder?)


----------



## Wildcard (24. Sep 2010)

Für einfache Dinge: EMF Validation Overview
Bei komplexeren, flexibleren Validierungen benutz das EMF Validation Framework


----------



## dermoritz (5. Okt 2010)

ich hab mir das mal angeschaut, aber das hilft nichts bzw. soweit war ich schon. Ich habe bereits code der beim Lesen oder Schreiben der Datei das komplette Objekt validiert (beschrieben in "EMF Validation Overview").
Andererseits gibt es einen Haufen Beispiele wie man einen EConntent Adapter benutzt und notify changed überschreibt. Aber aus irgendeinem komischen Grund gibt es kein Beispiel das eine Objektvalidierung (am besten nur für den betroffenen Teilbaum) nach einem setter (notify changed) durchführt.
Ich hab keine Ahnung wie ich "Diagnostic" mit "EContentAdapter" kombiniere. Hat irgendwer sowas schonmal gemacht?


----------



## Wildcard (5. Okt 2010)

Wie gesagt, ich denke es ist keine gute Idee das direkt bei jedem set zu tun.
Schreib dir erstmal einen eigenen Validator der Diagnostics erzeugt. Wenn du dann immer noch den ContentAdapter benutzen willst musst du nur den Validator im notifyChanged laufen lassen.


----------



## dermoritz (6. Okt 2010)

rein aus Neugier werde ich da mal dran bleiben. Andererseits, falls ich die Setter nicht validiere dann bin ich exakt da wo ich mit jaxb auch war: ich hab Code mit dem ich xml schreiben und lesen kann und validieren kann. Warum bin ich nochmal auf emf ungestiegen? ;-)
Also ich bin nach wie vor interessiert wie man einen "eigenen Validator der Diagnostics erzeugt" bastelt - am besten einen der nur das validiert was geändert wurde (den entsprechenden Unterbaum). Dieser müsste dann in der notifyChanged methode untergebracht werden, oder?
Hat das noch nie jemand gebaut? Irgendwie müsste sowas doch auch im Editor-Code drinne sein?!


----------



## Wildcard (6. Okt 2010)

dermoritz hat gesagt.:


> Andererseits, falls ich die Setter nicht validiere dann bin ich exakt da wo ich mit jaxb auch war: ich hab Code mit dem ich xml schreiben und lesen kann und validieren kann. Warum bin ich nochmal auf emf ungestiegen? ;-)


Weil EMF viele Constraints der XSD schon automatisch übernehmen kann, weil man mit EMF wesentlich mehr anstellen kann als mit JaxB, weil das erzeugte Modell um Klassen besser ist,...



> Also ich bin nach wie vor interessiert wie man einen "eigenen Validator der Diagnostics erzeugt" bastelt - am besten einen der nur das validiert was geändert wurde (den entsprechenden Unterbaum). Dieser müsste dann in der notifyChanged methode untergebracht werden, oder?
> Hat das noch nie jemand gebaut? Irgendwie müsste sowas doch auch im Editor-Code drinne sein?!


Der Editor macht es einfach so: 
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
ist ja grundsätzlich kein Problem das in notifyChanged aufzurufen...

Für eigene Constraints kannst du AFAIK eigene Implementierungen für EValidator bereitstellen. 
In Ansätzen ist hier ja schon beschrieben wie man das einklinkt und verwendet, allerdings bin ich auf diesem Gebiet auch kein Experte du wirst also ins EMF Buch schauen, Google benutzen, oder in der EMF Newsgroup nachfragen müssen.
Help - Eclipse SDK

Das EMF Validation Framework bietet übrigens Dinge wie konfigurierbare Live Validation, also würde ich mir das mal anschauen.


----------

