Wczytywanie listy obiektów tylko wybranej klasy(Polimorfizm) z XML'a uzywając JAX-B (JAVA)

0

Witam,
Stworzyłem listę polimorficznych obiektów. Mogę konwertować je do XMLa i vice versa (marshalling oraz unmarshaling używając JAXB). Chciałbym jednak odczytywać obiekty tylko wybranej klasy. Przeczytałem kilka tutoriali dotyczących konwersji listy obiektów używając JAXB, np http://memorynotfound.com/convert-xml-to-polymorphic-object-using-jax-b/ czy ten: http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-substitution.html

Posiadam listę Animal, oraz trzy klasy które rozszerzają abstrakcyjną klase Animal (Dog,Cat, Bird). Zapisuje tą listę i chciałbym odczytać z niej tylko psy. Używam tutorialu -> http://memorynotfound.com/convert-xml-to-polymorphic-object-using-jax-b/

Przykładowy output:
Root{animals=[com.memorynotfound.xml.jaxb.Dog@520a3426, com.memorynotfound.xml.jaxb.Cat@18eed359,com.memorynotfound.xml.jaxb.Bird@22agd431]}
Oczekiwany output: Root{animals=[com.memorynotfound.xml.jaxb.Dog@520a3426]}

Stworzyłem XMLEvent filtr, neistety znalazłem tylko wskazówki jak stworzyć filter na konkretną klasę. Natomiast potrzebuje czegoś co odfiltruje mi wszystkie INNE klasy i zwyczajnie nie mam już pojęcia jak to zrobić.

 public final class FilterDogXmlEventReader extends EventReaderDelegate {

    FilterDogXmlEventReader(XMLEventReader delegate) {
        super(delegate);
    }

    public XMLEvent nextEvent() throws XMLStreamException {
        // Read next event
        XMLEvent e = super.nextEvent();
        // If it's a start element for dog
        if (e.getEventType() == XMLEvent.START_ELEMENT && "Dog".equals(e.asStartElement().getName().getLocalPart())) {
            // Then run through events until a closing dog event
            do {
                e = super.nextEvent();
            } while (e.getEventType() != XMLEvent.END_ELEMENT || ! "Dog".equals(e.asEndElement().getName().getLocalPart()));
            // then read next event after the dog ends
            e = super.nextEvent();
        }
        return e;
    }
}

Tutaj unmarshaluje liste:

JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
XMLEventReader xmlReader = XMLInputFactory.newFactory().createXMLEventReader(new StringReader(xml));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new FilterDogXmlEventReader(xmlReader )); 

Elementy klasy Dog nie pojawią się w zwróconej liście. Natomiast czy ktoś mógłby doradzic jak zmodyfikować kod by tylko Psy pojawiły się na liście?

Zmiany które wdł mnie powinny działać:

public XMLEvent nextEvent() throws XMLStreamException {
        // Read next event
        XMLEvent e = super.nextEvent();
        // If it's a start element for dog
        if (e.getEventType() == XMLEvent.START_ELEMENT &&  ("Cat".equals(e.asStartElement().getName().getLocalPart()) ||
        		"Bird".equals(e.asStartElement().getName().getLocalPart()))
        		
        )
        
        
        {
        	
            // Then run through events until a closing dog event
            do {
                e = super.nextEvent();
            } while (e.getEventType() != XMLEvent.END_ELEMENT || ! ("Cat".equals(e.asStartElement().getName().getLocalPart()) ||
            		"Bird".equals(e.asStartElement().getName().getLocalPart()))
            		
            );
            // then read next event after the  ends
            e = super.nextEvent();
        }
        return e;
    }

Zwracają błędy. Już naprawde nie mam pomysłu jak to zrobić :(
Mogę oczywiście wypisać błędy, ale wydaje mi się, że po prostu mój tok rozumowania jest zły.

0

Problem rozwiązany.
Klasa filtrująca:

public final class FilteredXmlEventReader extends EventReaderDelegate {

    final Set<String> filteredElements;

    FilteredXmlEventReader(XMLEventReader delegate, String... filteredElements) {
        super(delegate);
        this.filteredElements = new HashSet<String>(Arrays.asList(filteredElements));
    }

    public XMLEvent nextEvent() throws XMLStreamException {
        // Read next event

        XMLEvent e = super.nextEvent();
        // If it's a start element for any filtered
        if (e.getEventType() == XMLEvent.START_ELEMENT && filteredElements.contains(e.asStartElement().getName().getLocalPart())) {
            String element = e.asStartElement().getName().getLocalPart();
            // Then run through events until a closing similar element
            do {
                e = super.nextEvent();
            } while (e.getEventType() != XMLEvent.END_ELEMENT || !element.equals(e.asEndElement().getName().getLocalPart()));
            // then read next tag after closing element
            e = super.nextEvent();
        }
        return e;
    }
} 

Unmarshalowanie XMLeventem:

JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
XMLEventReader xmlReader = XMLInputFactory.newFactory().createXMLEventReader(new StringReader(xml));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new FilteredXmlEventReader(xmlReader, "Dog", "Bird"));

1 użytkowników online, w tym zalogowanych: 0, gości: 1