001    
002    /*
003     * Copyright (C) 2012 Archie L. Cobbs. All rights reserved.
004     *
005     * $Id: UpdatesXMLEventReader.java 259 2012-01-30 19:47:58Z archie.cobbs $
006     */
007    
008    package org.dellroad.stuff.pobj;
009    
010    import java.util.ArrayList;
011    import java.util.List;
012    
013    import javax.xml.stream.XMLEventReader;
014    import javax.xml.stream.XMLStreamException;
015    import javax.xml.stream.events.StartElement;
016    import javax.xml.stream.events.XMLEvent;
017    
018    import org.dellroad.stuff.xml.AnnotatedXMLEventReader;
019    
020    /**
021     * {@link AnnotatedXMLEventReader} that reads the nested schema update list. Used by {@link PersistentObjectSchemaUpdater}.
022     */
023    public class UpdatesXMLEventReader extends AnnotatedXMLEventReader {
024    
025        private ArrayList<String> updates;
026    
027        public UpdatesXMLEventReader(XMLEventReader inner) {
028            super(inner);
029        }
030    
031        /**
032         * Get the updates gleaned from the scan.
033         *
034         * @return list of updates, or null if the document didn't contain an updates element
035         */
036        public List<String> getUpdates() {
037            return this.updates;
038        }
039    
040        @Override
041        protected boolean isAnnotationElement(StartElement event) {
042            return event.getName().equals(PersistentObjectSchemaUpdater.UPDATES_ELEMENT_NAME);
043        }
044    
045        @Override
046        protected void readAnnotationElement(StartElement startElement) throws XMLStreamException {
047            this.updates = new ArrayList<String>();
048            while (true) {
049    
050                // Skip to next event
051                XMLEvent event = this.advance();
052    
053                // Skip whitespace and comments
054                event = this.skipWhiteSpace(event, true);
055    
056                // Done with updates?
057                if (event.isEndElement()) {
058                    this.advance();
059                    return;
060                }
061    
062                // Get <update> start element event
063                if (!event.isStartElement()
064                  || !event.asStartElement().getName().equals(PersistentObjectSchemaUpdater.UPDATE_ELEMENT_NAME)) {
065                    throw new XMLStreamException("XML parse error: expected " + PersistentObjectSchemaUpdater.UPDATE_ELEMENT_NAME
066                      + " but got " + this.describe(event), event.getLocation());
067                }
068    
069                // Get update name
070                StringBuilder buf = new StringBuilder();
071                for (event = this.advance(); event.isCharacters(); event = this.advance())
072                    buf.append(event.asCharacters().getData());
073                this.updates.add(buf.toString());
074    
075                // Get <update> end element event
076                if (!event.isEndElement()) {
077                    throw new XMLStreamException("XML parse error: expected " + PersistentObjectSchemaUpdater.UPDATE_ELEMENT_NAME
078                      + " closing tag but got " + this.describe(event), event.getLocation());
079                }
080            }
081        }
082    
083        private String describe(XMLEvent event) {
084            return event.getClass().getSimpleName() + "[" + event + "]";
085        }
086    }
087