# Ajax DOM speichern



## ifconfig (18. Aug 2009)

Hallo,
ich arbeite mich gerade ins Ajax ein und wenn ich das bisher richtig verstehe, ändert Ajax ja den DOM des aktuell im Browser betrachteten Bildes. Dieser DOM befindet sich ja im Hauptspeicher, oder? Kann ich diesen aktuellen DOM aus dem Hauptspeicher irgendwie in ein xml-File abspeichern?
Ich hab es schon geschafft, mit dem Transformer ein von einem festen xml-File erzeugten DOM in ein xml-Dokument zu schreiben, aber ich habe noch keine Möglichkeit gefunden, den aktuell geänderten DOM des Arbeitsspeichers zu bekommen, um ihn als Parameter für den Transformer zu übergeben. Könnt ihr mir da helfen?

Hier mein geglückter Versuch, aber halt nur mit einem statischen xml-File als Quelle fürs DOM.

Grüße,
ifconfig

```
public void doAfterCompose(Component win) throws Exception {
		
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//configure factory as you want
		SAXParser parser = factory.newSAXParser();
		SAXBuilder builder = new SAXBuilder(parser);
		Document dom = builder.build(new File("/home/user1/workspace/zk_11_08_2009/WebContent/tree_dragdrop.zul"));
		
		new Transformer().transform(dom, new StreamResult(new File("/home/user1/domxml")));
```


----------



## FatFire (19. Aug 2009)

> ich arbeite mich gerade ins Ajax ein und wenn ich das bisher richtig verstehe, ändert Ajax ja den DOM des aktuell im Browser betrachteten Bildes.


Es heißt DAS DOM, weil DAS Document Object Model. DEN Dom in Köln ändert Ajax nicht.


> Dieser DOM befindet sich ja im Hauptspeicher, oder?


Japp.


> Kann ich diesen aktuellen DOM aus dem Hauptspeicher irgendwie in ein xml-File abspeichern?


Jein. Wenn Du damit meinst, Du hast den Firefox auf und weil der die Daten im Hauptspeicher liegen hat, kannst Du ja darauf zugreifen, dann ein sowas von klares NEIN.
Wenn Du damit meinst, dir einen kleinen (Pseudo?)-Browser in Java zu bauen, damit das DOM in Java zu haben und das dann in ein XML-File zu speichern, dann ein klares JA.
Vielleicht wäre da HtmlUnit was für Dich. Aber versucht habe ich es noch nicht, deshalb sage ich mal: auf eigene Gefahr!


----------



## ifconfig (19. Aug 2009)

Hallo FatTire,
ich arbeite mit dem ZK Ajax-Framework und habe einen Tree erstellt, den ich mit drag and drop Funktion ausgestattet habe. Und wenn ich was verschiebe im Baum, dann soll dieser Zustand auch nach einem Server-Neustart wieder hergestellt werden. Darum versuche ich, den geänderten, neuen Zustand des Baumes, der ja im DOM im Arbeitsspeicher ist, in ein xml-File zu speichern.
Hier ein Bild davon:

Grüße,
ifconfig


----------



## FatFire (19. Aug 2009)

Hm, da muss ich jetzt leider gänzlich passen. Ich kenne das Framework nur vom Hörensagen, mein Wissen darüber beschränkt sich darauf, dass die Applikationslogik eben Java ist :bahnhof:

Kann da wer was zu sagen, der das Framework kennt?

Gruß FatFire


----------



## ifconfig (20. Aug 2009)

Es muß ja nicht unbedingt mit dem zk gelöst werden, eine andere API oder FRamework ginge ja auch. JDOM oder was es da noch so alles gibt...


----------



## robertpic71 (21. Aug 2009)

Damit wir uns richtig verstehen: 

Der Tree wurde vom User im Browser "bearbeitet" und du meinst nicht den Ausgangszustand, welcher mit dem ZK Studio zusammengeklickt wurde? Bzw. du willst auch keinen Browser nachbauen?

Mit dem XML-Baum (DOM) im Browser hast du überhaupt nichts am Hut. ZK verfolgt einen serverlastige Ansatz: D.h. es gibt am Server eine GUI (in Form von Javaobjekten wie z.B. in Swing) welche vom Framework an den Browser gesynct werden.

D.h. der Lösungsansatz ist dem Speichern aus einem Swing/SWT Tree sehr ähnlich. Theoretisch müsste man auch die Javaklassen serialisieren können - aber neben dem Overhead (man wird vieles davon nicht brauchen) kann es da auch Probleme mit der eindeutigen Id geben.

Daher ist wahrscheinlich am einfachsten (ausgehend vom Tree Object):

for(Treeitem item : tree.getItems()) {
    out.value = out.value + item.getLabel() + " Ebene: " + item.getLevel() +  "\n";
}

Liefert sowas wie (Bezeichnung + Ebene):
Item 1 Ebene: 0
Item 2 Ebene: 0
Item 2.1 Ebene: 1
Item 2.1.1 Ebene: 2
Item 2.1.2 Ebene: 2
Item 2.2 Ebene: 1
Item 2.2.1 Ebene: 2
Item 3 Ebene: 0

Erfordert zwar etwas Logik, aber damit kann man einen XML-Baum machen. Wenn du einedeutige ID's hast, kannst auch getParentItem() (null=root) je Item machen und die (gleichnamige) XML-Node damit laden und dort hinzufügen.  

Alternativ könntest du versuchen überhaupt von einem Model auszugehen dieses mit dem den Drag and Drop Event's laufend zu aktualisieren bzw. auch das Treemodel bietet Listener für Veränderungen.

/Robert


----------



## ifconfig (21. Aug 2009)

robertpic71 hat gesagt.:


> Damit wir uns richtig verstehen:
> 
> Der Tree wurde vom User im Browser "bearbeitet" und du meinst nicht den Ausgangszustand, welcher mit dem ZK Studio zusammengeklickt wurde?
> /Robert



Ja, genau. Also der User soll die Files in andere Folder verschieben können, und genau diese Änderungen sollen erhalten bleiben, im xml-Format gesichert werden, und nach einem Server-Neustart wiederhergestellt werden. Die GUI hab ich auf dem vorigen Bild noch mit der zuml-Sprache zusammengebastelt, also wie es mir das zk Studio halt liefert. zuml ist ja auch xml, darum wäre es halt praktisch gewesen, einfach den Arbeitsspeicher-DOM in ein xml zu speichern, und dann dieses vom Browser beim Server-Neustart wieder aufzurufen. Aber anscheinend muß ich die ganze Arbeit was AJAX mit dem DOM macht, alles selber nochmal extra parallel dazu machen, also ein eigenes xml der aktuellen Tree-Struktur verwalten und zum Wiederherstellen des Baumes beim Neustart, dieses xml dann auslesen und daraus dann den Baum neu erstellen, verstehe ich das richtig so?

Und zu deinem Vorschlag mit dem TreeModel: Ja, daran hab ich gestern auch schon gedacht, in der Richtung weiterzumachen. Also komplett dieses zuml-Klick-Studio-Zeugs aufzugeben, und alles in Java zu coden. Was meinst du, soll ich alles komplett in Java coden oder weiterhin diese Hilfskonstruktion aus zuml und Java beibehalten? Es wird ja immer gesagt, daß man die GUI in zuml erstellen soll und die Logik mit Java erstellen soll. Nur bereitet mir dieses Brückenbauen andauernd Schwierigkeiten. Aber mit reinem Java-GUI-Basteln hab ich noch genausowenig Erfahrung. Hab bisher vorwiegend Konsolen-Java-Anwendungen programmiert. Ich habs gestern aber dann schon geschafft, den zuml-dragdrop-Tree auch als zk-Richlet komplett in Java zu schreiben, und er funktioniert.

Grüße,
ifconfig


----------



## robertpic71 (21. Aug 2009)

Bei pure Java vs. XML-Gui scheiden sich die Geister. Ich bin auch ein Verfechter der XML-GUI, im Falle von ZK produziert der GUI-Paint auch noch XML, also noch ein Grund.

Bei mehrschichtigen Daten wie z.B. dem Tree wird das Designen/Zeichnen von dynamischen Daten schwierig. Ich löse eigentlich die meisten Anwendung mit Zul-GUI und Databinding, aber einigen wenigen Componenten funktioniert das nicht, dazu gehört auch der Tree.



> einfach den Arbeitsspeicher-DOM in ein xml zu speichern


Wie gesagt, der Domainbaum aus dem Browser, steht gar nicht zur Verfügung. Aber es ist prinzipiell auch möglich.
Es gab für ZK einen Onlinedesigner (ZeroKode), dieser wandelt die GUI-Elemente in XML und zurück um. Du kannst die Sourcen ja im SVN ( [LINK "http://zerokode.svn.sourceforge.net/viewvc/zerokode/"] etwas studieren.

Allerdings ist vom Design her unschön eine GUI-Kopie als Model herzunehmen und wenn man den Source anschaut auch nicht ganz unaufwendig.

Ich würde das Rahmenwerk mit dem GUI-Painter machen und den Tree-Inhalt dem Javaprogramm überlassen.
Wenn ich Zeit finde, poste ich ein Beispiel.

/Robert


----------



## ifconfig (21. Aug 2009)

robertpic71 hat gesagt.:


> Wenn ich Zeit finde, poste ich ein Beispiel.


Ja, das wäre super.

Und danke für die Tips soweit und den svn-Link, da werd ich mal reinschauen.

Grüße,
ifconfig


----------



## robertpic71 (22. Aug 2009)

Noch eine andere Frage: 
Verändert der Benutzer wirklich irgendwelche Daten? In dem Beispiel geht es ja um Files. 
In solchen Fällen müsste der Baum ja sowieso von den Daten (Filesystem) aufgebaut werden.


----------



## robertpic71 (22. Aug 2009)

Hier noch ein Beispiel:

Der zul-Code:

```
<?page title="Tree" contentType="text/html;charset=UTF-8"?>
<zk>
	<window id="win" title="Tree" border="normal" apply="com.at.od.controller.TreeController">
		<vbox>
			<button id="save" label="Save" />
			<tree id="tree">
				<treecols>
					<treecol label="Name" />
					<treecol label="Größe" />
				</treecols>
			</tree>
		</vbox>
	</window>
</zk>
```

Die Verbindung zu einer Javaklasse ist das apply="com.at.od.controller.TreeController". Hier der Controller:


```
package com.at.od.controller;

// import ...

public class TreeController extends GenericForwardComposer {
	
	Tree tree;    // autowired
	
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		System.out.println("Init");
		fillTree();
	}
	public void fillTree() {
		System.out.println("Baum füllen");
		Treechildren child = new Treechildren();
		Treeitem item = new Treeitem("Test");
		child.appendChild(item);
		tree.appendChild(child);
	}
        public void onClick$save() {  // autowired
		System.out.println("Speichern");
	}
}
```

In diesem Fall erbt man schon von einem "schlauen" Composer/Controller:

- gleichnamige UI-Objekte werden automatisch geladen 
   in diesem Fall tree

- mit dem Syntax Eventname $ UI-Name kann man Events ohne Listener verheiraten
  in diesem Fall das Klicken auf den Speicherbutton onClick$save, wenn man mehr Infos zu Event braucht
  auch: public void onClick$save(FowardEvent event) oder ..(MouseEvent event)..

Wenn du mit einem Model arbeiten willst, gibt es viele Möglichkeiten für das Binding, hier eine einfache:


```
<tree id="tree" model="${win.composer.deinModel">
```

Für das "deinModel" mußt du einen getter (in Javabean-Style) anbieten:


```
public TreeModel getDeinModel() {
   ...
```

Beim Tree muss er leider wählerisch (nur Interface TreeModel) sein, bei Listboxen, Comboboxen usw. reicht jede Art von Collection.

Es sollte jetzt kein Problem sein, deine Javalösung zu integrieren. Den Tree hast du ja im Zugriff.

Alles drumeherum kannst du mit dem GUI-Painter machen, den Treeinhalt in Java (direkt oder mit Model). Für fast alle anderen UI-Componenten (Listbox, Grid, Comboboxen.....) kann man die UI komplett "zeichnen" und via Databinding befüllen lassen.

/Robert


----------



## ifconfig (23. Aug 2009)

Hallo Robert,
danke für deinen Beispielcode.



robertpic71 hat gesagt.:


> Noch eine andere Frage:
> Verändert der Benutzer wirklich irgendwelche Daten? In dem Beispiel geht es ja um Files.
> In solchen Fällen müsste der Baum ja sowieso von den Daten (Filesystem) aufgebaut werden.



Ich habe das mit den Files und Folders nur als allgemeines Beispiel benutzt um es anschaulich zu halten. In Wirklichkeit brauche ich den Baum für was Anderes, und zwar will ich damit eine Jalousien-Zeitschaltuhr zur Gebäudeautomatisierung erstellen. Und zwar habe ich verschiedene Ein- und Ausschaltzeiten gruppiert. Diesen Gruppen(Folder) werden dann verschiedene Räume(Files) zugeordnet. Ich werde eine Javaklasse "Gruppe", und eine Javaklasse "Raum" erstellen.
Die beiden sollen dann nach in etwa so nach dem Observer-Pattern zusammenarbeiten: Also ich schiebe im Baum einen Raum in eine Gruppe, dadurch wird dann der Raum bei der Gruppe registriert. Wenn ich dann für die Gruppe sage, daß die Jalousien hochfahren sollen, werden alle hier registrierten Räume darüber informiert, und führen dann die Aktion aus. 
Wenn ich einen Raum in eine andere Gruppe verschiebe, dann wird er von der aktuellen Gruppe abgemeldet und in der neuen Gruppe registriert.

Also ich werde es dann so wie du vorgeschlagen hast, mit Javabean für dasTreeModel versuchen, weil da hab ich grade wo gelesen, daß sich JavaBeans zur Datenhaltung gut ins XML-Format wandeln lassen und daraus wiederherstellen lassen. Hab dafür auch gerade eine API entdeckt: JOX - Java Objects in XML
Genau sowas brauche ich.
Oder geht sowas auch irgendwie mit ZK- oder Java-Bordmitteln?

Sehe ich das richtig, daß du in dem Beispiel hier das Model-View-Controller-Pattern benutzt hast? 
Also die View ist das zul-File, das Model ist dann das TreeModel/JavaBean und der Controller ist der "TreeController extends GenericForwardComposer"?

Aber warum soll ich denn die View extra in ein zul-File packen, wenn ich eh den ganzen Rest auch schon in Java code? Wenn ich den View auch in Java, also als Richlet code, dann müßte ich dann dem View das Model und dem Controller übergeben/bekanntmachen, oder? Ich hab schon vor langer Zeit mal ein MVC in Java gecoded, ich muß mir die Codes mal wieder hersuchen, hoffentlich finde ich die noch...

Kannst du mir bitte zeigen, wie hier der View und Javabean in Java aussehen würden?
Ich werd mich da jetzt mal versuchen reinzulesen in diese neuen Themen.

Grüße,
ifconfig


----------



## ifconfig (23. Aug 2009)

Hier noch der Code meines Richlets:

```
package mytest;

import java.util.List;

import org.zkoss.zk.ui.AbstractComponent;
import org.zkoss.zk.ui.GenericRichlet;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Button;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;

public class ComposeGroups extends GenericRichlet {

	@Override
	public void service(Page page) {
		// button(page);

		Tree t = new Tree();
		t.setPage(page);		
		Treechildren tch = new Treechildren();
		t.appendChild(tch);
		
		Treeitem gruppeOhneZuordnung= createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum= createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum= createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");
		
		
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));
		
	

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}
	
	

	public Treeitem createFolder(String foldername) {

		Treeitem ti = new Treeitem();

		Treerow tr = new Treerow();
		Treechildren tch = new Treechildren();
		tr.setDroppable("true");
		addFolderDropEventListener(tr);
		Treecell tc = new Treecell(foldername);
		tr.appendChild(tc);
		ti.appendChild(tr);
		ti.appendChild(tch);
		return ti;
	}

	public Treeitem createFile(String filename) {
		Treeitem ti = new Treeitem();
		Treerow tr = new Treerow();
		tr.setDraggable("true");
		Treecell tc = new Treecell(filename);
		tr.appendChild(tc);
		ti.appendChild(tr);
		return ti;

	}

	private void addFolderDropEventListener(Treerow tr) {
		tr.addEventListener("onDrop", new EventListener() {

			@Override
			public void onEvent(Event event) throws Exception {
				DropEvent dropevent = ((DropEvent) event);
				List list = dropevent.getTarget().getParent().getChildren();

				for (Object element : list) {
					if (element instanceof Treechildren) {
						((Treechildren) element).appendChild((dropevent
								.getDragged().getParent()));

					}

				}

			}
		});

	}

	private void button(Page page) {
		// TODO Auto-generated method stub
		Button b = new Button();
		b.setHref("Richlet2");
		b.setLabel("Hallo");
		b.setVisible(true);
		b.setPage(page);
	}

}
```


und hier noch ein Screenshot davon:


----------



## robertpic71 (24. Aug 2009)

Wie schon gesagt, jetzt wäre es ein Leichtes den Javacode einzubauen:

Die Zeilen 

```
Tree t = new Tree();
t.setPage(page);
```
kannst du entfernen.

Den Teil service() kannst du nach fillTree() übernehmen. Entweder die benennst die Tree-Komponenten auf "t" um oder du ändern dein Java von t.append.. auf tree.append...

Den Rest (alle UI-Elemente außerhalb des Tree's) und Data- und Eventbinding kannst die zul-File zeichnen bzw. die Bindings onClick$button durch Namensvergabe steuern.

Auch für den Javateil gibt es Hilfsfunktionen für Events:
Statt dem Listener mit der anonymer Klasse kannst du:
item.addForward("onDrop", win, "onZiel");

mach. Damit wird das Drop-Event an den Controller/Composer an die Methoder deiner Wahl "umgeleitet" in diesem Fall 

```
public void onZiel(ForwardEvent fevent) {
..
```
Das Orignalevent bekommt du mit fevent.getOrign() - möglicherweie funktioniert auch ..onZiel(DropEvent event) - bin mir da nicht sicher. 

Anmerkung: Damit er win kennt, musst "Window win;" deklarieren --> autowired UI-Element.

/Robert


----------



## ifconfig (26. Aug 2009)

Hallo Robert,
danke für deine weiteren Tipps, ich habe sie gerade eben erfolgreich umgesetzt. 
Hier meine Codes dazu:
[XML]
<?page title="Tree" contentType="text/html;charset=UTF-8"?>
<zk>
	<window id="win" title="Tree" border="normal" apply="mytest.TreeController">
		<vbox>
			<button id="save" label="Save" />

			<tree id="tree">
				<treecols>
					<treecol label="Name" />
					<treecol label="Größe" />
				</treecols>
			</tree>
		</vbox>
	</window>
</zk>
[/XML]


```
package mytest;

import java.util.List;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Window;

public class TreeController extends GenericForwardComposer {

	private static final long serialVersionUID = -6315303870414522261L;
	Tree tree; // autowired
	Window win;// autowired

	public void doAfterCompose(Component win) throws Exception {
		super.doAfterCompose(win);
		System.out.println("Init");
		fillTree();
	}

	public void fillTree() {

		Treechildren tch = new Treechildren();
		tree.appendChild(tch);

		Treeitem gruppeOhneZuordnung = createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum = createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum = createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");

		gruppeOhneZuordnung.getLastChild()
				.appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}

	public void onZiel(DropEvent dropevent) {
		List list = dropevent.getTarget().getParent().getChildren();

		for (Object element : list) {
			if (element instanceof Treechildren) {
				((Treechildren) element).appendChild((dropevent.getDragged()
						.getParent()));

			}

		}
	}

	public Treeitem createFolder(String foldername) {

		Treeitem ti = new Treeitem();

		Treerow tr = new Treerow();
		Treechildren tch = new Treechildren();
		tr.setDroppable("true");
		addFolderDropEventListener(tr);
		Treecell tc = new Treecell(foldername);
		tr.appendChild(tc);
		ti.appendChild(tr);
		ti.appendChild(tch);
		return ti;
	}

	public Treeitem createFile(String filename) {
		Treeitem ti = new Treeitem();
		Treerow tr = new Treerow();
		tr.setDraggable("true");
		Treecell tc = new Treecell(filename);
		tr.appendChild(tc);
		ti.appendChild(tr);
		return ti;

	}

	private void addFolderDropEventListener(Treerow tr) {
		/*
		 * zk Hilfsfunktion Auch für den Javateil gibt es Hilfsfunktionen für
		 * Events: Statt dem Listener mit der anonymer Klasse kannst du:
		 * item.addForward("onDrop", win, "onZiel");
		 */

		tr.addForward("onDrop", win, "onZiel");

	}

	public void onClick$save() { // autowired
		System.out.println("Speichern");
	}
}
```


----------



## robertpic71 (26. Aug 2009)

Ich habe erst jetzt gesehen, dass ich das erste deines 2-fach Postings nicht gesehen habe.



ifconfig hat gesagt.:


> ...Hab dafür auch gerade eine API entdeckt: JOX - Java Objects in XML
> Genau sowas brauche ich.Oder geht sowas auch irgendwie mit ZK- oder Java-Bordmitteln?


Mit JDom (ist auch im ZK Paket) geht das auch, nachdem JDOM nachgesagt wird obsolet zu sein, müsste es dafür auch Javabordmittel geben - allerdings habe ich die noch nie gesucht/verwendet. Aber die spezialisierten API's haben oft noch extra Steuerungsmöglichkeiten - also wenn die Doku passt spricht nichts gegen JOX.



ifconfig hat gesagt.:


> Sehe ich das richtig, daß du in dem Beispiel hier das Model-View-Controller-Pattern benutzt hast?
> Also die View ist das zul-File, das Model ist dann das TreeModel/JavaBean und der Controller ist der "TreeController extends GenericForwardComposer"?


Ja, ich verwende weitgehend MVC. Hautsächlich mit dem Ziel das Logik frei von UI-Abhängigkeiten zu halten. Für den Composer gäbe es auch ein Interface, wenn der Controller von irgendwo anders vererbt werden muss. Allerdings hat der GenericForwardComposer eben diese "auotwired" Extras.



ifconfig hat gesagt.:


> Ich hab schon vor langer Zeit mal ein MVC in Java gecoded, ich muß mir die Codes mal wieder hersuchen, hoffentlich finde ich die noch...


Das ZK Framework zwingt einen den MVC-Pattern nicht auf. Aber wenn man die View mit Painter macht, hat man schon mal eine Trennung. Ich finde der MVC-Zwang schießt etwas über das Ziel - wiederverwertbare Businesslogik - hinaus. Aber das ist ein ganz anderes Kapitel.



ifconfig hat gesagt.:


> Aber warum soll ich denn die View extra in ein zul-File packen, wenn ich eh den ganzen Rest auch schon in Java code?


Wie schon gesagt, du kannst den Rest "designen". Du kannst z.B. auch ein Contextmenü (für die rechte Maustaste) mit zul zeichnen und deinen Java Treeitems zuordnen. Der Tree ist da wirklich eine Ausnahme, alle anderen Componenten z.B. direkt mit dem Hibernate-Output.

/Robert


----------



## ifconfig (27. Aug 2009)

Warum bekomme ich da jetzt so eine komische Fehlermeldung? Ich habe hier gerade versucht, das Wohnzimmer zu den Wohnräumen zu ziehen, dann beim Droppen kam dieses Fehlerfenster.




Aber das Laden des Baumes aus einem XML-File funktioniert schonmal, weil ich den ursprünglichen Baum vorher in dieses XML-File abgespeichert habe, mit diesem Code und der XStream API von Codehaus:

```
new XStream().toXML(((Tree) tree), new FileOutputStream(
				"/home/user1/tree.xml"));
```

EDIT: Und wenn ich das gleiche in der Version mit zul-File und autowired TreeController versuche, dann kommt zwar kein Fehlerfenster beim Droppen, aber wenn ich dann den geänderten, Baum aus dem XML-File wiederherstellen will, bekomm ich nur den nackten View als Baum, also ohne den Inhalt, nur das zul-Grundgerüst. Wie löse ich dieses neue Problem?

```
package mytest;

import java.awt.Point;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.List;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Window;
import com.thoughtworks.xstream.XStream;

public class TreeController extends GenericForwardComposer {

	Tree tree; // autowired
	/*
	 * Anmerkung: Damit er win kennt, musst "Window win;" deklarieren -->
	 * autowired UI-Element.
	 */
	Window win;// autowired

	public void doAfterCompose(Component win) throws Exception {
		super.doAfterCompose(win);
		System.out.println("Init");
		//fillTree();
		
		getSerializedXMLTree();
	}

	private void getSerializedXMLTree() throws FileNotFoundException {
		tree= (Tree) new XStream().fromXML(new FileInputStream("/home/user1/tree.xml"));
		
	}

	private void serializeToXML(Tree tree) throws FileNotFoundException {
		new XStream().toXML(tree, new FileOutputStream("/home/user1/tree.xml"));

	}

	public void fillTree() {

		Treechildren tch = new Treechildren();
		tree.appendChild(tch);

		Treeitem gruppeOhneZuordnung = createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum = createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum = createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");

		gruppeOhneZuordnung.getLastChild()
				.appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}

	public Treeitem createFolder(String foldername) {

		Treeitem ti = new Treeitem();

		Treerow tr = new Treerow();
		Treechildren tch = new Treechildren();
		tr.setDroppable("true");
		addFolderDropEventListener(tr);
		Treecell tc = new Treecell(foldername);
		tr.appendChild(tc);
		ti.appendChild(tr);
		ti.appendChild(tch);
		return ti;
	}

	public Treeitem createFile(String filename) {
		Treeitem ti = new Treeitem();
		Treerow tr = new Treerow();
		tr.setDraggable("true");
		Treecell tc = new Treecell(filename);
		tr.appendChild(tc);
		ti.appendChild(tr);
		return ti;

	}

	private void addFolderDropEventListener(Treerow tr) {
		/*
		 * zk Hilfsfunktion Auch für den Javateil gibt es Hilfsfunktionen für
		 * Events: Statt dem Listener mit der anonymer Klasse kannst du:
		 * item.addForward("onDrop", win, "onZiel");
		 */

		tr.addForward("onDrop", win, "onZiel");

	}

	public void onZiel(DropEvent dropevent) throws FileNotFoundException {
		List list = dropevent.getTarget().getParent().getChildren();

		for (Object element : list) {
			if (element instanceof Treechildren) {
				((Treechildren) element).appendChild((dropevent.getDragged()
						.getParent()));

			}

		}
		
		serializeToXML(tree);
	}

	public void onClick$save() { // autowired
		System.out.println("Speichern");
	}
}
```

EDIT2:
Komisch, im autowired TreeController hat er nach dem Droppen den neuen Zustand korrekt ins xml gespeichert, aber das Wiederherstellen dieses neuen xml-tree funktioniert nur in meinem Richlet-Code, also im ComposeGroups.java.


----------



## robertpic71 (27. Aug 2009)

Ohne jetzt ins Detail gegangen zu sein:
Das verdrehen einer aktiven GUI-Komponente (andere ID, neues Objekt) wird er nicht mitmachen. Probiere daher:

```
tree.detach();
tree = aus XML..
vbox.append(tree);
```

Die Vbox muss du dafür mit ID versehen und definieren. 

Beim Richlet erzeugst du sowieso eine neue Tree Componente, da stellt sich das Problem erst gar nicht. Alternativ könntest du den Tree nicht im ZUL definieren oder erst ab TreeChildren serialisieren.

Aber Achtung! Die GUI-Komponenten benötigen eine eindeutige ID. Theoretisch könnte man in Probleme laufen, wenn im UI-Tree schon eine vergebene ID vorkommt. Abhilfe: selber eindeutige ID's vergeben oder mit Model arbeiten.

/Robert


----------



## ifconfig (27. Aug 2009)

Ich habs gerade so versucht, hab ich das so richtig eingebaut? Geht leider nicht, er lädt weiterhin den leeren Tree, das Grundgerüst.


```
package mytest;

import java.awt.Point;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.List;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.Window;
import com.thoughtworks.xstream.XStream;

public class TreeController extends GenericForwardComposer {

	Tree tree; // autowired
	/*
	 * Anmerkung: Damit er win kennt, musst "Window win;" deklarieren -->
	 * autowired UI-Element.
	 */
	Window win;// autowired
	Vbox vbox= new Vbox();
	
	

	public void doAfterCompose(Component win) throws Exception {
		super.doAfterCompose(win);
		System.out.println("Init");
		//fillTree();
		
		getSerializedXMLTree();
	}

	private void getSerializedXMLTree() throws FileNotFoundException {
		
		tree.detach();
		tree= (Tree) new XStream().fromXML(new FileInputStream("/home/user1/tree.xml"));
		vbox.setId("vbox");
		vbox.appendChild(tree);
		
		//tree.setId("tree");
		
	}

	private void serializeToXML(Tree tree) throws FileNotFoundException {
		new XStream().toXML(tree, new FileOutputStream("/home/user1/tree.xml"));

	}

	public void fillTree() {

		Treechildren tch = new Treechildren();
		tree.appendChild(tch);

		Treeitem gruppeOhneZuordnung = createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum = createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum = createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");

		gruppeOhneZuordnung.getLastChild()
				.appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}

	public Treeitem createFolder(String foldername) {

		Treeitem ti = new Treeitem();

		Treerow tr = new Treerow();
		Treechildren tch = new Treechildren();
		tr.setDroppable("true");
		addFolderDropEventListener(tr);
		Treecell tc = new Treecell(foldername);
		tr.appendChild(tc);
		ti.appendChild(tr);
		ti.appendChild(tch);
		return ti;
	}

	public Treeitem createFile(String filename) {
		Treeitem ti = new Treeitem();
		Treerow tr = new Treerow();
		tr.setDraggable("true");
		Treecell tc = new Treecell(filename);
		tr.appendChild(tc);
		ti.appendChild(tr);
		return ti;

	}

	private void addFolderDropEventListener(Treerow tr) {
		/*
		 * zk Hilfsfunktion Auch für den Javateil gibt es Hilfsfunktionen für
		 * Events: Statt dem Listener mit der anonymer Klasse kannst du:
		 * item.addForward("onDrop", win, "onZiel");
		 */

		tr.addForward("onDrop", win, "onZiel");

	}

	public void onZiel(DropEvent dropevent) throws FileNotFoundException {
		List list = dropevent.getTarget().getParent().getChildren();

		for (Object element : list) {
			if (element instanceof Treechildren) {
				((Treechildren) element).appendChild((dropevent.getDragged()
						.getParent()));

			}

		}
		
		serializeToXML(tree);
	}

	public void onClick$save() { // autowired
		System.out.println("Speichern");
	}
}
```





Ich werd jetzt versuchen, wie du vorgeschlagen hast, ein Model zu benutzen und mit Javabean-Style es zu serialisieren.
Alles was ich momentan darüber weiß, ist, daß Javabean bedeutet, daß alle Variablen der Klasse mit getXXX und setXXX angeschlossen werden müssen. Zum Model weiß ich noch weniger...

EDIT: Was ist eigentlich der Vorteil/Sinn des Models im Vergleich zum direkten Benutzen des Trees? Der Tree bietet doch die gleichen Funktionen/Möglichkeiten wie das TreeModel, oder?


----------



## robertpic71 (27. Aug 2009)

Du musst den neuen Tree bei einer aktiven Componente anhängen, nicht bei einer neuen (nicht eingehängten):

Also im zul-File:

<vbox *id="vbox"*>
   <button id="save" label="Save" />
  <tree id="tree">
..

Im Javateil, dann die gleichnamige Vbox definieren:

Window win;  // autowired
Vbox vbox;

Und den neuen Tree an die angehängte vbox hängen.


Alternativ wäre auch:
Component parent = tree.getParent();
tree.detach();
// neuer tree
parent.appendChild(tree);

Damit hängt man das an die gleiche Componente, wo er vorher war.

Zu GUI vs. Model-Beans:
Für diesen Fall hast du praktisch nur kleine Nachteile. Man darf nicht vergessen, dass MVC auch einen gewissen Overhead mit sich bringt. Du hast "nur" in eine gewissen Abhängigkeit von den GUI-Objekten und keine sauberen Beans. Das kann sich für Erweiterungen aller Art negativ auswirken:

z.B. Du willst eine Fernsteuerung für JavaME (Handy) bauen. Die Definitionen (den Tree) kann man nicht ohne Web/ZK-Lib verarbeiten - reine Javabeans geht überall.

z.B. Wenn du die Daten (strukturiert) in eine Datenbank speichern willst, sind die GUI-Objekte auch nicht sehr hilfreich.

z.B. Wenn du daraus eine Desktopapplikation machen willst...

/Robert


----------



## ifconfig (27. Aug 2009)

Vielen Dank mal wieder, jetzt hab ich mit deinem letzten Tipp endlich den letzten entscheidenden Schritt zum Erreichen eines wirklichen Fortschritts(Meilenstein) meines Projektes geschafft, also die Datenhaltung/ -wiederherstellung mit XML funktioniert jetzt endlich!  
Aber das erzeugte XML enthält die gesamte GUI-Struktur, was dieses xml-File dann wieder sehr überladen/unleserlich macht. Das xml-File für diesen Minibaum hat nämlich 900 Zeilen!!!
Also hiermit hab ich jetzt endlich grundlegend die Persistenz gesichert, aber ich glaube, daß die Aufgabe eher dahin geht, daß das xml nur die Namen der Gruppen und Räume und die Ein- und Ausschaltzeiten enthalten soll. Also es soll auch beim direkten Lesen im xml gleich die Information erkennbar sein. 
Dazu werde ich als nächstes jetzt endlich mal meine Klassen Raum und Gruppe richtig ausdefinieren und sie als Javabean-Style gestalten. Ich frage mich momentan halt noch, wie ich diese beiden Klassen dann in den Baum einbinden soll. Also die Gruppe ist halt ein Folder(innerer Knoten) und der Raum ist ein File(Blattknoten). Aber wie übertrage ich die jetzt zwei Klassen auf den Treeitem des vorhandenen Baums?

Hier noch mein aktueller funktionierender dragdrop-Persistenz-Tree mit zul-View:

[XML]<?page title="Tree" contentType="text/html;charset=UTF-8"?>
<zk>
	<window id="win" title="Tree" border="normal" apply="mytest.TreeController">
		<vbox>
			<button id="save" label="Save" />

			<tree id="tree">
				<treecols>
					<treecol label="Name" />
					<treecol label="Größe" />
				</treecols>
			</tree>
		</vbox>
	</window>
</zk>[/XML]


```
package mytest;

import java.awt.Point;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.List;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.Window;
import com.thoughtworks.xstream.XStream;

public class TreeController extends GenericForwardComposer {

	Tree tree; // autowired
	/*
	 * Anmerkung: Damit er win kennt, musst "Window win;" deklarieren -->
	 * autowired UI-Element.
	 */
	Window win;// autowired
	//Vbox vbox; // autowired
	
	

	public void doAfterCompose(Component win) throws Exception {
		super.doAfterCompose(win);
		//System.out.println("Init");
		//fillTree();
		
		getSerializedXMLTree();
	}

	private void getSerializedXMLTree() throws FileNotFoundException {
		
		Component parent = tree.getParent();
		 tree.detach();
		 // neuer tree
			tree= (Tree) new XStream().fromXML(new FileInputStream("/home/user1/tree.xml"));
		 parent.appendChild(tree);
		 

		
	}

	private void serializeToXML(Tree tree) throws FileNotFoundException {
		new XStream().toXML(tree, new FileOutputStream("/home/user1/tree.xml"));

	}

	public void fillTree() {

		Treechildren tch = new Treechildren();
		tree.appendChild(tch);

		Treeitem gruppeOhneZuordnung = createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum = createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum = createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");

		gruppeOhneZuordnung.getLastChild()
				.appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}

	public Treeitem createFolder(String foldername) {

		Treeitem ti = new Treeitem();

		Treerow tr = new Treerow();
		Treechildren tch = new Treechildren();
		tr.setDroppable("true");
		addFolderDropEventListener(tr);
		Treecell tc = new Treecell(foldername);
		tr.appendChild(tc);
		ti.appendChild(tr);
		ti.appendChild(tch);
		return ti;
	}

	public Treeitem createFile(String filename) {
		Treeitem ti = new Treeitem();
		Treerow tr = new Treerow();
		tr.setDraggable("true");
		Treecell tc = new Treecell(filename);
		tr.appendChild(tc);
		ti.appendChild(tr);
		return ti;

	}

	private void addFolderDropEventListener(Treerow tr) {
		/*
		 * zk Hilfsfunktion Auch für den Javateil gibt es Hilfsfunktionen für
		 * Events: Statt dem Listener mit der anonymer Klasse kannst du:
		 * item.addForward("onDrop", win, "onZiel");
		 */

		tr.addForward("onDrop", win, "onZiel");

	}

	public void onZiel(DropEvent dropevent) throws FileNotFoundException {
		List list = dropevent.getTarget().getParent().getChildren();

		for (Object element : list) {
			if (element instanceof Treechildren) {
				((Treechildren) element).appendChild((dropevent.getDragged()
						.getParent()));

			}

		}
		
		serializeToXML(tree);
	}

	public void onClick$save() { // autowired
		System.out.println("Speichern");
	}
}
```

Und hier noch der aktuelle, geänderte Zustand des Baumes nach drei Server-Neustarts, also ursprünglich waren alle Zimmer in GruppeOhneZuordnung, dann nach und nach richtig eingeordnet. Und der Server hat sich die Änderungen gemerkt und beim Neustart wiederhergestellt.


----------



## ifconfig (28. Aug 2009)

Jetzt hab ich hoffentlich einen guten Weg gefunden, um meine Anforderungen zu einem runden, kompakten Gesamtpaket zu schnüren:
ZK - Data binding - Documentation

Mit dem in diesem Beispiel angewendeten Databinding mit Bean könnte ich mein Problem lösen, wie ich nun den Raum und Gruppe in meinen Tree integriere:  Meine Nutzdaten, also die Ein- und Ausschaltzeiten, könnte ich dann in so etwas wie hier der Person-Bean ablegen. Die dragdrop-geänderte Baumstruktur mache ich weiterhin so, wie ich sie jetzt habe, da ist es dann auch egal daß dieses tree.xml 900 Zeilen hat. Leserlich sollen ja nur die Nutzdaten sein, und die werden es ja wahrscheinlich dank Bean-Struktur. Die Bean ist ja gut xml-serialisierbar und -wiederherstellbar als Java-Objekt.
Jetzt muß ich also nur irgendwie dieses Beispiel databinding auf meinen vorhandenen serializable-xml-dragdrop-Tree übertragen, also im nackten View, also im zul-File des Trees diese binding-Attribute und das init in der page einbauen.

@Robert: Was hältst du von dieser Idee?


----------



## robertpic71 (28. Aug 2009)

ifconfig hat gesagt.:


> ..die Datenhaltung/ -wiederherstellung mit XML funktioniert jetzt endlich!
> Aber das erzeugte XML enthält die gesamte GUI-Struktur, was dieses xml-File dann wieder sehr überladen/unleserlich macht. Das xml-File für diesen Minibaum hat nämlich 900 Zeilen!!!


Wie schon im 1. oder 2. Posting von mir erwähnt: Die GUI-Struktur hat natürlich einen Overhead.



ifconfig hat gesagt.:


> Dazu werde ich als nächstes jetzt endlich mal meine Klassen Raum und Gruppe richtig ausdefinieren und sie als Javabean-Style gestalten. Ich frage mich momentan halt noch, wie ich diese beiden Klassen dann in den Baum einbinden soll. Also die Gruppe ist halt ein Folder(innerer Knoten) und der Raum ist ein File(Blattknoten). Aber wie übertrage ich die jetzt zwei Klassen auf den Treeitem des vorhandenen Baums?



Also ich sehe da ingesamt 3 Möglichkeiten:
1.) Jedes Treeitem kann auch einen Value und weitere Attribute speichern. D.h. du könntest den entsprechenden Bean in diesem Item speichern. Das erfordert aber Logik beim Lesen und beim Speichern des Baumes: GUI-Struktur auslesen, XML daraus ableiten bzw. umgekehrt.

2.) Du baust dein komplett selbständiges Model (Javabeans's inkl. Struktur) und implemtierst dann das Interface Treemodel. Dein Treemodel kann auch einfach den reinen Datenbaum halten und die GUI-Anforderungen abwickeln.

3.) Du nimmst einen fertiges Treemodel von ZK und fütterst es mit deinen Beans. 

Bei 2. und 3. kannst du das Model serialisieren und deserialisieren.

Mit dem Treemodel habe ich allerdings überhaupt keine Erfahrung. Ich habe zwar vor 3-4 Jahren eine Tree-Anwendung gemacht, da gab es das Treemodel aber noch nicht. Obwohl ich Web- und ZK-Anfänger war, stand der Prototyp nach einer Woche. Der Katalog ( http://online.odoerfer.com/OdKatalog/ ) bekommt demnächst ein Facelift, der XP-Look ist auch nicht mehr ganz taufrisch bzw. die neueren GUI-Elemente der neuen ZK-Versionen (ca. 10 Versionen dazwischen) sind wesentlich "durchgestylter".


/Robert


----------



## robertpic71 (28. Aug 2009)

ifconfig hat gesagt.:


> Jetzt muß ich also nur irgendwie dieses Beispiel databinding auf meinen vorhandenen serializable-xml-dragdrop-Tree übertragen, also im nackten View, also im zul-File des Trees diese binding-Attribute und das init in der page einbauen.
> 
> @Robert: Was hältst du von dieser Idee?



Zuerst, ich arbeite hauptsächlich mit dieser Art von Databinding, also die GUI-Komponenten direkt mit den Javabeans zu verdrahten - am besten in beide Richtungen. Auf diese Weise habe ich verschiedenste Daten (Bilder, boolean true --> grüner Pfeil, false=rotes X, Listbox, Combobox...) ausgetauscht wie z.B. hier: Tandemboxen planen (Anoynm klicken , Produkt Tandembox intivo, Farbe weiss, Zeile unten ausfüllen oder Neue Box klicken).

Wie schon in den ersten Posts geschrieben, hilft dir diese Art von Databinding nicht für den Tree! Das oben beschriebene Databinding hilft dir z.B. wenn du ein Eigenschaftsfenster hast und die Eingaben direkt in den Bean mappen willst. Das Treemodel ist etwas zu komplex um es mit einer Template-GUI vorzeichnen zu können.

Deshalb bleibt für den Tree nur der Weg über das Model. Für alle anderen Anwendungen kann ich dir das gefunden Databinding nur empfehlen. Vor allem zusammen mit einer ORM Lösung bekommt das ganze Flügel.

/Robert


----------



## ifconfig (29. Aug 2009)

Gut, danke für die Tipps soweit, ich muß mich da jetzt also erstmal richtig in dieses Javabean- und Modeltree-Thema reinlernen, hab immernoch keinen Plan, wie ich die Beans richtig gestalten soll, geschweige denn, wie ich das Treemodel dann damit füttern und das Ganze dann als xml serialisieren soll...ich steh momentan voll aufm Schlauch. 
Ich muß bald fertig sein, insofern bin ich mächtig im Stress damit...


----------



## robertpic71 (31. Aug 2009)

ifconfig hat gesagt.:


> hab immernoch keinen Plan, wie ich die Beans richtig gestalten soll,


Beim Design deiner Bean's sollte die Technik (hier UI Modelle, sonst auch Persitenceschicht) nur im Hinterkopf sein. Praktisch fängt man beim optimalen OO-Modell und macht dann Kompromisse damit man das leichter verarbeiten kann. [1]

In deinem wird es wohl die Klassen Stockwerk und Zimmer (ev. noch Haus/Einheit) geben. Wobei dann immer die Frage ist, ob man die Beziehung zwischen den beiden Seiten speichert. Also Stockwerk je Zimmer und/oder eine Collection (z.B. ArrayList) im  Stockwerk, wo alle Zimmer gespeichert werden. Eventuell kannst du ja das "Default Zimmer" ohne Zuordnung auch kennzeichnen.



ifconfig hat gesagt.:


> ...geschweige denn, wie ich das Treemodel dann damit füttern und das Ganze dann als xml serialisieren soll...ich steh momentan voll aufm Schlauch.



Wenn du dein Model fertig hast, kannst du dazu übergehen die Interfaces aus dem Model (Treemodel) zu implementieren. Wobei hier eine Rootklasse ala Haus oder Wohneinheit (mit Liste der Zimmer) kein Nachteil ist. Wenn du die Treeinterfaces in dein Model implementiert hast, kannst du einfach dein Model serialisieren. Beim Laden deserialisiert es und verkaufst es als Model für den Tree.

/Robert

[1] Das ist jetzt die Ultrakurzversion inkl. meiner Meinung. Das Thema OO ist bücherfüllend...


----------



## ifconfig (11. Sep 2009)

Hallo Robert,
danke wieder für die Tips, aber ich werde es nun ohne Beans und TreeModel lösen.
Ich baue mir einfach ein xml-File, wo ich alle Informationen zusammenfasse. Also mehrere Raumgruppen sind die Elemente des xml-Baumes. Und in die Raumgruppen fülle ich dann alle spezifischen Informationen wie Ein- und Ausschaltzeiten und die zugrordneten Räume und deren Namen. Also beispielsweise so:
[XML]<?xml version="1.0" encoding="UTF-8"?>
<model>
	<gruppe>
		<gruppenname>
			Ohne Zuordnung
		</gruppenname>
	</gruppe>
	<gruppe>
		<gruppenname>
			Wohnräume
		</gruppenname>
		<rolladensteuerung>
			<zeit auf="8:00" ab="20:00" von="Mo" bis="So" />
		</rolladensteuerung>
		<raum name="Kinderzimmer" stockwerk="OG1" />
		<raum name="Wohnzimmer" stockwerk="EG" />
		<raum name="Esszimmer" stockwerk="EG" />
	</gruppe>
	<gruppe>
		<gruppenname>
			<rolladensteuerung>
				<zeit auf="6:00" ab="22:00" von="Mo" bis="Fr" />
				<zeit auf="8:00" ab="22:00" von="Sa" bis="So" />
			</rolladensteuerung>
			<raum name="Schlafzimmer" stockwerk="EG" />
			<raum name="Schlafzimmer" stockwerk="OG1" />
		</gruppenname>
	</gruppe>
</model>[/XML]


```
public void fillTree() {

		Treechildren tch = new Treechildren();
		tree.appendChild(tch);

		Treeitem gruppeOhneZuordnung = createFolder("OhneZuordnung");
		gruppeOhneZuordnung.setId("OhneZuordnung");
		Treeitem gruppeWohnraum = createFolder("GruppeWohnraum");
		gruppeWohnraum.setId("GruppeWohnraum");
		Treeitem gruppeSchlafraum = createFolder("GruppeSchlafraum");
		gruppeSchlafraum.setId("GruppeSchlafraum");

		gruppeOhneZuordnung.getLastChild()
				.appendChild(createFile("Wohnzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Schlafzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(
				createFile("Kinderzimmer"));
		gruppeOhneZuordnung.getLastChild().appendChild(createFile("Esszimmer"));

		tch.appendChild(gruppeOhneZuordnung);
		tch.appendChild(gruppeWohnraum);
		tch.appendChild(gruppeSchlafraum);

	}
```

EDIT:
Diesen xml-Baum lade ich mir erstmal als iDOM-Objekt, den parse ich dann, und baue mir abhängig von den gelieferten Informationen die Java-GUI auf. Also was ich bisher hardcoded gemacht habe in der Methode filltree(), werde ich jetzt dynamisch, also abhängig vom xml-Inhalt als Java-GUI rekonstruieren. Jedesmal, wenn ein Drag&Drop-Event entsteht, wird die Änderung zusätzlich zur GUI-Änderung, auch im iDOM-Objekt durchgeführt und das iDOM wird dann immer gleich wieder ins xml transformiert, also der aktuelle Baumzustand wird immer synchron persistent gehalten, ein Backup quasi, das dann beim nächsten Server-Neustart wiederhergestellt wird.


----------



## ifconfig (12. Sep 2009)

Ich hätte da noch ein anderes ZK-Problem, das mich im Einsatz dieses ZK-Frameworks erheblich einschränkt, und zwar kann das ZK-Studio das implizite self-Objekt nicht erkennen. Ich habe einfach mal das Codebeispiel von ZK - Developer reference The ZK User Interface Markup Language Implicit Objects self - Documentation
mit Copypaste in ein von ZK-Studio erstelltes neues zul-file eingefügt, aber es erscheint folgendes Eclipse-Warning "self cannot be resolved", wie löse ich das?
[XML]<?page title="new page title" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="new page title" border="normal">
<listbox  >
   <zscript>  self.getItems(); </zscript><!-- self is listbox -->
   <listitem value="ab" label="${self.value}"/><!-- self is listitem -->
   <zscript>self.getSelectedIndex();</zscript><!-- self is listbox -->
 </listbox>
</window>
</zk>[/XML]


----------

