# EMF Model auf xsd Element mit eIsSet prüfen



## greeni (17. Sep 2010)

Hallo Zusammen,

nach dem ich mit dem generierten EMF Editor eine Datenstruktur (Baumstruktur) erstellt habe, möchte ich nun diese Struktur durchlaufen und jeden Knoten in diesem Baum darauf überprüfen ob es sich in XML um ein Element oder ein Attribut handelt und falls es sich um ein Element handelt, ob für dieses Element ein Wert gesetzt wurde. Wenn ich das richtig verstanden habe, so realisiere ich das irgendwie mit der Methode eIsSet.... aber da hört es bei mir schon auf. Ich finde leider auch nirgendwo beispiele dazu. Währe froh wenn mir jemand helfen könnte.


```
Testcase testcase = documentRoot.getTestcase();
	TreeIterator<EObject> iter = testcase.eAllContents();
	while (iter.hasNext())
	{
		EObject obj = iter.next();
	
		obj.eIsSet(............);
			
	}
```


----------



## Wildcard (17. Sep 2010)

Du denkst zu sehr in XML, Ecore ist ein Modelling Tool, XML Binding ist nur ein winziger Teilaspekt. Dein Modell kann mit EMF auf eine XML Darstellung gemappt werden genau, wie eine XSD auf ein Ecore gemappt wird. Was du also validierst ist dein Modell und nicht eine XML, oder ein DOM-Tree.
Welche Rolle spielt es also ob du ein Feature einer Klasse in XML als Element, oder Attribut repräsentierst?

Zu eIsSet, eIsSet antwortet auf die Frage ob ein Feature (Features sind etwas Attribute, also einfache Datentypen, oder Referenzen auf andere EObject) gesetzt wurde oder nicht. Um diese Frage beantworten zu können musst du übergeben um welches Feature es dir geht. Die Liste welche Features in ein Objekt hat sind in der EClass gespeichert. An die EClass eines Objekts kommst du mit yourObject#eClass()
Help - Eclipse SDK

Zusätzlich enthält dein generiertes EPackage Informationen über alle Klassen und Features deines Modells.

```
EStructuralFeature feature = YourPackage.Literals.YourClass1_Your_Whatever_Feature;
```


----------



## greeni (18. Sep 2010)

Vielen Dank Wildcard,
deine Antworten helfen mir sehr mein Verständnis für EMF zu verbessern. 

Zu deiner Frage wieso es für mich wichtig ist, ob es ein Element oder Attribut ist... Na ja, die XML Datei die ich erzeuge wird von einem anderen Programm eingelesen. Sie dient also zum Datenaustausch. Dieses anderen Programm nutzt einen Parser, der eben darauf achtet ob es sich bei einem Wert in der xml Datei und eine Elemet oder Attribut handelt. 

Aber das löst EMF ganz gut... also emf serialisiert mir meine Objekte schon richtig. 
Mein Problem ist nur, das mir in der PropertyView bei Elementwerten bei denen ich über enums nur bestimmte werte zulasse, immer der erste Wert angezeigt wird obwohl ich ihn gar nicht ausgewählt habe. Das ist sehr verwirrent (... das Problem habe ich in den letzten Tagen hier schon in ein paar anderen Beiträgen geschildert) und da ich es nicht schaffe die PropertyView so zu ändern, das mir dieser Erste Wert nicht mehr angezeigt wird, suche ich nach ner anderen lösung.
Eine Idee war halt durch meinen Baum zu gehen und immer nachzuschauen ob der Wert gesetzt wurde oder nicht und dem Benutzer dann wenigstens eine entsprechende Meldung aus zu geben.


----------



## Wildcard (18. Sep 2010)

Ein Enum wird immer mit einem Default initialisiert, deine Property View zeigt das also ganz korrekt an.
Wenn du diesen Default nicht möchtest pass es in der generierten Klasse an.


----------



## greeni (18. Sep 2010)

Hm.... also wenn das funktionieren würde, währen alle meine Probleme gelöst.
Aber leider funktioniert das auch nicht... jedenfalls wüßte ich nicht wie?

Ich kann den default Datentyp in meiner generierten Klasse nur ein Typ von meinem Enumn zuweisen.
Ideal währe es natürlich wenn ich als default Wert einen leeren String setzen könnte. Aber wie gesagt, funktioniert das nicht, da Enums inter als int dargestellt werden.

Und das Problem habe ich ja nicht nur bei enums, sondern auch bei Zahlen werten. diese werden mit per default auf 0 bzw. 0.0 gesetzt. 

Wenn du eine Möglichkei kennst wie ich diesen Defaultwerten einen leeren String zuweisen könnte, währe ich überglücklich und mein Problem endlich gelöst.


----------



## Wildcard (18. Sep 2010)

Für ein Enum kannst du null setzen.
Primitive Werte haben natürlich immer einen Wert und daher ist es auch korrekt das dort 0 angezeigt wird. Wenn du das nicht willst musst die wie gesagt die Property View customizen.


----------



## greeni (18. Sep 2010)

Und wenn ich dich richtig verstanden habe, kann ich muss ich dazu eine tapped Proprty verwenden, weil ich die normlae Proprerty View nicht anpassen kann.... Oh man, das wird ne heiden Arbeit... Mein Model besteht aus ca. 900 generierten Klassen. 
Wenn ich das in dem Artikel über die TappedPropertyView richtig verstanden habe, so muss ich für jede dieser Klassen eine eigene seite für die View erstellen. Das gefällt mir ganz und gar nicht ... Aber trotzdem sehr vielen Dank für deine Hilfe. 

Falls dir vieleicht zufällig noch etwas einfallen sollte, wie man die normale PropertyView einfach anpassen kann um bestimmte Werte auszublenden oder zumindest die Schriftfarbe Weis zu färben so lange da der defaultWert drin steht, würde ich mich natürlich um weitere Antworten froh. 

Aber wie gesagt, Danke nochmals für deine bisherige Mühe!!!


----------



## Wildcard (18. Sep 2010)

Du kannst die Properties View anpassen und du kannst. Ob du die Schriftfarbe anpassen kannst, keine Ahnung. Wenn du unbedingt einen leeren String für Default Werte haben willst lässt sich das mit ziemlicher Sicherheit auch tun, aber ich kann dir ohne eigene Nachforschungen auch nicht sagen wo du den Hebel dafür am besten ansetzen musst, also wirst du dich wohl oder übel selbst einarbeiten müssen.


----------



## Wildcard (18. Sep 2010)

Also, ich habe es kurz ausprobiert:

Geh in den XYItemProvider. Dort überschreibst du die Methode createItemPropertyDescriptor.
Anstatt einen ItemPropertyDescriptor zu instanzieren erstellst du eine Subclass von ItemPropertyDescriptor bei der getValue folgendermaßen überschrieben ist:

```
@Override
protected Object getValue(EObject object, EStructuralFeature feature) {
	if(!object.eIsSet(feature))
		return "";
	return super.getValue(object, feature);
}
```


----------



## greeni (19. Sep 2010)

Hallo Wildcard,

leider versteh ich nicht ganz wier du das meinst mit dem erstellen einer Subklasse von ItemPropertyDescriptor.

Wenn ich die createItemPropertyDescriptor Methode überschreibe sieht das so aus...

```
@Override
	protected ItemPropertyDescriptor createItemPropertyDescriptor(
			AdapterFactory adapterFactory, ResourceLocator resourceLocator,
			String displayName, String description, EStructuralFeature feature,
			boolean isSettable, Object staticImage, String category,
			String[] filterFlags) 
	
	{

		

		return super.createItemPropertyDescriptor(adapterFactory, resourceLocator,
			displayName, description, feature, isSettable, staticImage,     
                                      category,filterFlags);
	}
```

Wie soll ich hier drin eine neue Instanz von ItemPropertyDescriptor erzeugen?


----------



## Wildcard (19. Sep 2010)

```
new YourSubclassItemPropertyDescriptor();
```


----------



## greeni (19. Sep 2010)

Hm... leider ist dann das komplette Element nicht mehr sichtbar und man kann gar nichts mehr eingeben... schade... ein Versuch wars wert.


----------



## Wildcard (19. Sep 2010)

Ich habe es gestern selbst implementiert und es funktioniert. Zeig mal Code.


----------



## greeni (19. Sep 2010)

Die Überschriebene Methode:


```
@Override
protected ItemPropertyDescriptor createItemPropertyDescriptor(
	AdapterFactory adapterFactory, ResourceLocator resourceLocator,
	String displayName, String description, EStructuralFeature feature,
	boolean isSettable, boolean multiLine, boolean sortChoices,
	Object staticImage, String category, String[] filterFlags) 
             {	
	        return new MyDescriptor(adapterFactory, resourceLocator, category, category, null);
	}
```

Und dies ist die neue Descriptorklasse:


```
class MyDescriptor extends ItemPropertyDescriptor
{

	public MyDescriptor(AdapterFactory adapterFactory, ResourceLocator resourceLocator,
			String displayName, String description,
			EReference[] parentReferences) 
	{
		super(adapterFactory, resourceLocator, displayName, description,
				parentReferences);
	}
	
	@Override
	protected Object getValue(EObject object, EStructuralFeature feature) 
	{
		if(!object.eIsSet(feature))
			return "";
	    return super.getValue(object, feature);
	}	
}
```


----------



## Wildcard (19. Sep 2010)

Die geschätzt 300 Parameter der Methode musst du an den Konstruktor von ItemPropertyDescriptor durchreichen.


----------



## greeni (20. Sep 2010)

Vielen Dank Wildcard. So funktioniert es. Genau so habe ich mir das vorgestellt!!


----------

