2016-05-18 18 views
0

Ich habe Klassen, die von einem XSD mit JAXB generiert werden. Eine der Optionen für JAXB-benutzerdefinierte Bindungen ist die Angabe der Implementierungsklasse java.util.List. Zum Beispiel kann ich angeben JAXB die Klasse verwendet java.util.LinkedList, und der generierte Code würden folgende gehören:JavaFX ObservableList konkrete Implementierung

if (myList == null) 
    myList = new java.util.LinkedList(); 

ich die Implementierung möchte eine javafx.collections.ObservableList zurück, aber keine konkreten Klassen nicht finden können, die diese Schnittstelle implementieren und haben einen Standardkonstruktor. Kennt jemand eine konkrete Implementierung von javafx.collections.ObservableList mit einem Standardkonstruktor?

+0

Haben Sie versucht FXCollections.observableArrayList(); Erzeugt eine neue leere beobachtbare Liste, die von einer Arraylist unterstützt wird. –

+0

Das Problem ist, dass ich nicht den Code schreibe ... es wird von JAXB generiert. Ich kann dem Code nur den zu instantiierenden Typ mitteilen, und dieser Typ muss einen Standardkonstruktor bereitstellen. –

+0

Können Sie Ihre eigenen erstellen? Erweitern Sie eine der vorhandenen, die Sie gefunden haben, und stellen Sie einen Standardkonstruktor in Ihrer neuen Klasse bereit. – mascoj

Antwort

0

In Ordnung, es gibt zwei Möglichkeiten, dies zu tun. Die erste ist, Ihre eigene javafx.utils.ObservableList zu implementieren. Die folgende Implementierung wird in der Dokumentation für ModifiableObservableListBase (leicht modifiziert) zur Verfügung gestellt:

public class ObservableArrayList<T> extends ModifiableObservableListBase<T> { 
    private final List<E> delegate = new ArrayList<>(); 

    @Override 
    public E get(final int index) { 
     return delegate.get(index); 
    } 

    @Override 
    public int size() { 
     return delegate.size(); 
    } 

    @Override 
    protected void doAdd(final int index, final E element) { 
     delegate.add(index, element); 
    } 

    @Override 
    protected E doSet(final int index, final E element) { 
     return delegate.set(index, element); 
    } 

    @Override 
    protected E doRemove(final int index) { 
     return delegate.remove(index); 
    } 
} 

JAXB kann dann diese Klasse als Implementierung Listentyp verwenden, um zu den Bindungen des folgenden Zugabe-Datei:

<bindings node="//xsd:element[@name='Item']"> 
    <property name="Items" collectionType="myNamespace.ObservableArrayList"> 
    <baseType name="myNamespace.Item" /> 
    </property> 
</bindings> 

Die zweite Option, und die, die ich gewählt habe, besteht darin, den JAXB Marshaller/Unmarshaller so zu konfigurieren, dass er benutzerdefinierte Implementierungsklassen verwendet, die von den generierten Klassen erben. Nehmen wir an, dass die XSD einen komplexen Typ mit dem Namen "ItemCollectionType" definiert, der eine Elementdefinition mit dem Namen "Item" und mit unbegrenztem maxOccurs enthält. Dann füge ich einfach die folgenden auf die JAXB Bindungsdatei:

<bindings node="./xsd:complexType[@name='ItemCollectionType']"> 
    <class implClass="myNamespace.ItemCollection" /> 
</bindings> 

<bindings node="//xsd:element[@name='Item']"> 
    <property name="Items"> 
    <baseType name="myNamespace.Item" /> 
    </property> 
</bindings> 

Die oben genannten Kräfte jedes Auftreten von ItemCollectionType im generierten Code mit myNamespace.ItemCollection Typ sein zu ersetzen. Dann schließt die erzeugte Implementierung von ItemCollectionType den folgenden Code:

@XmlElement(name = "Item", required = true, type = myNamespace.Item.class) 
protected List<myNamespace.Item> items; 

public List<myNamespace.Item> getItems() { 
    if (items == null) { 
     items = new ArrayList<myNamespace.Item>(); 
    } 
    return this.items; 
} 

Dann überschreiben ich diese Methode in myNamespace.ItemCollection:

@Override 
public ObservableList<Item> getItems() { 
    if (!(super.getItems() instanceof ObservableList)) { 
     items = FXCollections.observableList(items); 
    } 
    return (ObservableList<Item>)items; 
} 

Natürlich sind diese beiden Optionen sind nicht gegenseitig ausschließen. Ich könnte sie beide einfach implementieren, was die Implementierung von myNamespace.ItemCollection.getItems zu einem einfachen Cast vereinfachen würde.