Announcement

Collapse
No announcement yet.

[JAXB] Referenzen?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • [JAXB] Referenzen?

    Hallo,

    ich bin grade dabei eine Konsolenspiel zu erstellen, das ein Labyrinth von Räumen darstellen soll und man soll ebend auch per XML eine Karte / Level, wie auch immer erstellen können. Bis jetzt habe ich die einzelnen Räume, Gegenstände usw. alle im Spiel "hardcoded" aber ich würde das gerne Level per XML erstellen können. Da bin ich dann auch JAXB gestoßen und das einlesen etc. funktioniert auch schon aber ich komme nicht weiter, weil ich ja bei einem Raum dann bspw. eine Referenz auf einen anderen brauche, also wie kriege ich das hin?

    Hier mal eine XML Datei als Beispiel:
    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <karte>
    	<raueme>
    		<raum>
    			<eingang>
    				<name>eingang</name>
    				<beschreibung>Der Eingang des Labyrinths</beschreibung>
    				<gaenge>
    					<gang>
    						<richtung>norden</richtung>
    						<nachbar>raum2</nachbar>
    					</gang>
    				</gaenge>
    			</eingang>
    		</raum>
    		<raum>
    			<name>raum2</name>
    			<beschreibung>Ein etwas größerer Raum</beschreibung>
    			<gaenge>
    				<gang>
    					<richtung>norden</richtung>
    					<nachbar>raum3</nachbar>
    				</gang>
    			</gaenge>
    		</raum>
    		<raum>
    			<ausgang>
    				<name>raum3</name>
    				<beschreibung>Ein etwas größerer Raum 2</beschreibung>
    				<gaenge>
    					<gang>
    						<richtung>westen</richtung>
    						<nachbar>raum4</nachbar>
    					</gang>
    				</gaenge>
    				<monster>
    					<name>Oger</name>
    					<leben>100</leben>
    					<schaden>15</schaden>				
    				</monster>
    			</ausgang>
    		</raum>
    	</raueme>
    </karte>
    Da wird ja bspw. bei dem Eingangsraum schon ein nächster Raum (Raum2) genannt aber kann man das so überhaupt umsetzen oder müsste man das dann irgendwie so abändern, das dann erst die Räume erstellt werden und dann die gaenge / Verbindungen, wie auch immer geschaffen werden oder geht das auch wie oben beschrieben oder ähnlich?
    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <karte>
    	<raueme>
    		<raum>
    			<eingang>
    				<name>eingang</name>
    				<beschreibung>Der Eingang des Labyrinths</beschreibung>
    			</eingang>
    		</raum>
    		<raum>
    			<name>raum2</name>
    			<beschreibung>Ein etwas größerer Raum</beschreibung>
    		</raum>
    		<raum>
    			<ausgang>
    				<name>raum3</name>
    				<beschreibung>Ein etwas größerer Raum 2</beschreibung>
    				<monster>
    					<name>Oger</name>
    					<leben>100</leben>
    					<schaden>15</schaden>				
    				</monster>
    			</ausgang>
    		</raum>
    	</raueme>
    	<gaenge>
    		<gang>
    			<raum>eingang</raum>
    			<richtung>norden</richtung>
    			<nachbar>raum2</nachbar>
    		</gang>
    		<gang>
    			<raum>raum2</raum>
    			<richtung>norden</richtung>
    			<nachbar>raum3</nachbar>
    		</gang>
    		<gang>
    			<raum>raum3</raum>
    			<richtung>westen</richtung>
    			<nachbar>raum4</nachbar>
    		</gang>
    	</gaenge>	
    </karte>
    Ich habe da auch noch ein kleines Problem mit den setzen der Gänge bzw. der Verbindungen zwischen den Räumen. Vorher habe ich das so gemacht:
    Code:
    private Raum[] gaenge;
    
    public void setGang(Richtung richtung, Raum nachbar) 
    {
        gaenge[richtung.ordinal()] = nachbar;
    }
    aber das geht ja dann jetzt mit JAXB so nicht mehr? Bräuchte ich dann für den Gang eine eigene Klasse? Das Problem ist ja, das ich das auch weiter mit dem ordinal() haben will und die ausgaenge sind natürlich in einem Raum Array gespeichert aber wie speichere ich dann die Wert trotzdem in dem Array ab?

    So sieht die Raum Klasse übrigens komplett aus:
    Code:
    @XmlRootElement(name = "raum")@XmlAccessorType(XmlAccessType.NONE)
    public class Raum 
    {    
        private String beschreibung;
        
        private Monster monster; 
        private Gegenstaende gegenstaende;  
        private Raum[] gaenge;
        
        private static final int anzahlRichtungen = Richtung.values().length;
        
        public Raum() 
        {
    
        }
        
        public Raum(String beschreibung) 
        {
            this.beschreibung = beschreibung;
            
            gaenge = new Raum[anzahlRichtungen];
            gegenstaende = new Gegenstaende();
        }
        
        @XmlElement(name = "beschreibung")
        public void setBeschreibung(String beschreibung)
        {
            this.beschreibung = beschreibung;
        }
        
        public void setzeAusgang(Richtung richtung, Raum nachbar) 
        {
            gaenge[richtung.ordinal()] = nachbar;
        }    
        
    
        public Raum getGang(Richtung richtung) 
        {
            return gaenge[richtung.ordinal()];
        }    
    
        public String gibGaenge()
        {
            Richtung[] richtung = Richtung.values();
            String gaenge = "";
            
            for(int i = 0; i < ausgaenge.length; i++)
            {
                if(ausgaenge[i] != null)
                    gaenge += " " + richtung[i].name().toLowerCase();
            }
            
            return gaenge;
        }  
    
        public void setMonster(Monster monster)
        {
            this.monster = monster;
        }
        
    }
    So könnte dann ja warscheinlich der "Gang" aussehen:
    Code:
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name = "gang")@XmlAccessorType(XmlAccessType.NONE)
    public class Gang
    {
        private Richtung richtung;
        private Raum nachbar;
        
        public Gang()
        {      
    
        }
        
        public Gang(Richtung richtung, Raum nachbar)
        {
            this.richtung = richtung;
            this.nachbar = nachbar;
        }
        
        @XmlElement(name = "richtung")
        public void setRichtung(Richtung richtung)
        {
            this.richtung = richtung;
        }
        
        @XmlElement(name = "nachbar")
        public void setNachbar(Raum nachbar)
        {
            this.nachbar = nachbar;
        }    
    }
    Oben in der Raum Klasse sieht man ja auch noch das mit der setMonster Methode. Das würde dann ja auch so nicht mehr funktionieren oder? Da kann man dann ja nicht hinschreiben:
    Code:
    @XmlElement(name = "monster")
    public void setMonster(Monster monster)
    {
        this.monster = monster;
    }
    also wie bringt man dann nachher den Raum dazu, das auch das Monster in den Raum aufgenommen wird?

    Ich würde auch noch gerne den Eingang und evtl. die "Ausgänge" in einer Klasse "Level" oder ähnlich speichern. Dafür habe ich auch das XML Attribut "eingang" und "ausgang" erstellt. Da bräuchte ich dann ja auch wieder die Raum Referenz oder nicht?
    Code:
    import java.util.Arrays;
    
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name = "level")@XmlAccessorType(XmlAccessType.NONE)
    public class Level
    {
        private Raum eingang;    
        private Raum[] ausgaenge;
        
        public Level()
        {
        	
        }
          
        public Level(Raum eingang, Raum[] ausgaenge)
        {
            this.eingang = eingang;
            this.ausgaenge = ausgaenge;
        }
        
        public Raum getEingang()
        {
            return eingang;
        }
        
        @XmlElement(name = "eingang")
        public void setEingang(Raum eingang)
        {
        	this.eingang = eingang; 
        }
        
        @XmlElement(name = "ausgang")
        public void setAusgang(Raum ausgang)
        {
        	ausgaenge[0] = ausgang; // vielleicht auch mehrere Ausgänge
        }
        
        public boolean istAusgang(Raum raum)
        {
            return Arrays.asList(ausgaenge).contains(raum);
        }
    }
    An den Stellen komme ich grad einfach nicht mehr voran.
    Ich würde mich sehr über Hilfe freuen und danke schon einmal im voraus!
    Zuletzt editiert von Threin; 27.09.2015, 03:30.

  • #2
    http://entwickler-forum.de/showthrea...spiele-zu-JAXB
    Solange die Klassen serialisierbar sind, kannst du diese verschachtelt aufnehmen. Es sind keine Annotationen notwendig. Verwende statt der Arrays -> ArrayList.
    Um die Referenzen brauchst du dich nicht kümmern. Die ordnet JAXB selbstständig zu.
    Allerdings sollten deine Klassen


    implements Serializable

    implementieren
    Christian

    Comment


    • #3
      Wäre das denn da so sinnvoll, die Daten so verschachtelt nach meiner ersten "Variante" in der XML Datei zu schreiben? Würde das so in der Variante also nur funktionieren, wenn ich das Interface Serializable zu meinen ganzen Klassen hinzufüge? Also zu allen Klassen, die ich auch in meiner Datei benutze (Raum, Spieler, Gegenstand. Gang, Monster)?

      Woher soll denn dann aber JAXB nachher wissen, wozu die einzelnen XML Attribute gehören, selbst wenn es dann ein Unterpunkt der Räume ist? Wird dann denn auch automatisch für die setMonster Methode des Raums aufgerufen? Wenn ein Monster erstellt wird, dann gebe ich ja auch im Konstruktor mit, welcher der "Startraum" ist und das wird dann auch automatisch mitgegeben?
      Brauch man dann also nur noch die XML Root Element Annotation oder braucht man dann komplett keine mehr? Muss man dann also nur das Interface implementieren und die private static final long serialVersionUID vergeben und das war's dann schon oder braucht man da noch was? Ich will die XML Datei ja nur einlesen, also kein speichern der Daten. Ich habe mich fast noch gar nicht mit Serialisierung beschäftigt.

      Würde das denn dann auch weiterhin mit der setGang() Methode funktionieren oder müsste man da dann auch eine eigene Klasse für erstellen? Nur wie oben schon gesagt, würde ich das gerne mit dem ordinal() beibehalten, allerdings weiß ich nicht wie.

      Wieso denn anstatt der Arrays die Arraylisten? Meinst du das so allgemein mit der Liste?
      Code:
      List <Raum> gaenge = new ArrayList<>();
      Zuletzt editiert von Threin; 25.09.2015, 16:07.

      Comment


      • #4
        Dein ganzes Post besteht nur aus Fragen.
        Wäre das denn da so sinnvoll, die Daten so verschachtelt nach meiner ersten "Variante" in der XML Datei zu schreiben?
        Wenn du keine Trennung zwischen den Daten hast...
        Würde das so in der Variante also nur funktionieren, wenn ich das Interface Serializable zu meinen ganzen Klassen hinzufüge?
        Nein, Klassen die mit JAXB bearbeitet werden sollen, sollten diese Implementierung haben
        Also zu allen Klassen, die ich auch in meiner Datei benutze (Raum, Spieler, Gegenstand. Gang, Monster)?
        Wenn du die speichern willst
        Woher soll denn dann aber JAXB nachher wissen, wozu die einzelnen XML Attribute gehören, selbst wenn es dann ein Unterpunkt der Räume ist?
        JAXB kennt die Klassen und deren Attribute
        Wird dann denn auch automatisch für die setMonster Methode des Raums aufgerufen?
        Wozu sollte das erforderlich sein?
        Wenn ein Monster erstellt wird, dann gebe ich ja auch im Konstruktor mit, welcher der "Startraum" ist und das wird dann auch automatisch mitgegeben?
        Die Klasse wird so geladen, wie sie gespeichert wurde.
        Brauch man dann also nur noch die XML Root Element Annotation oder braucht man dann komplett keine mehr?
        Wenn nix besonderes ist
        Muss man dann also nur das Interface implementieren und die private static final long serialVersionUID vergeben und das war's dann schon oder braucht man da noch was?
        Lies in der Doku nach :-(
        Ich will die XML Datei ja nur einlesen, also kein speichern der Daten. Ich habe mich fast noch gar nicht mit Serialisierung beschäftigt.
        Irgendwas muss ja das gespeicherte erzeugt haben. Wenn das nicht mit JAXB passiert, musst du die Referenzen natürlich selbst setzen.
        Würde das denn dann auch weiterhin mit der setGang() Methode funktionieren oder müsste man da dann auch eine eigene Klasse für erstellen?
        Verstehe ich nicht
        Wieso denn anstatt der Arrays die Arraylisten? Meinst du das so allgemein mit der Liste?
        Ja. Listen sind flexibler und einfacher zu handhaben
        Zuletzt editiert von Christian Marquardt; 26.09.2015, 09:22.
        Christian

        Comment

        Working...
        X