001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.soap.util.stax;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import javax.xml.namespace.NamespaceContext;
023    import javax.xml.stream.XMLStreamConstants;
024    import javax.xml.stream.XMLStreamException;
025    import javax.xml.stream.XMLStreamReader;
026    import javax.xml.stream.util.StreamReaderDelegate;
027    
028    public class FragmentStreamReader extends StreamReaderDelegate implements XMLStreamReader {
029    
030            protected static final int STATE_START_DOC = 0;
031            protected static final int STATE_FIRST_ELEM = 1;
032            protected static final int STATE_FIRST_RUN = 2;
033            protected static final int STATE_RUN = 3;
034            protected static final int STATE_END_DOC = 4;
035            
036            protected int depth;
037            protected int state = STATE_START_DOC;
038            protected int event = START_DOCUMENT;
039        protected List<String> rootPrefixes;
040            
041        public FragmentStreamReader(XMLStreamReader parent) {
042            super(parent);
043            NamespaceContext ctx = getParent().getNamespaceContext();
044            if (ctx instanceof ExtendedNamespaceContext) {
045                rootPrefixes = new ArrayList<String>(((ExtendedNamespaceContext) ctx).getPrefixes());
046            }
047        }
048    
049            public int getEventType() {
050                    return event;
051            }
052    
053            public int next() throws XMLStreamException {
054                    switch (state) {
055                    case STATE_START_DOC:
056                            state = STATE_FIRST_ELEM;
057                            event = START_DOCUMENT;
058                            break;
059                    case STATE_FIRST_ELEM:
060                            state = STATE_FIRST_RUN;
061                            depth++;
062                            event = START_ELEMENT;
063                            break;
064                    case STATE_FIRST_RUN:
065                            state = STATE_RUN;
066                            // do not break
067                    case STATE_RUN:
068                            event = getParent().next();
069                            if (event == START_ELEMENT) {
070                                    depth++;
071                            } else if (event == END_ELEMENT) {
072                                    depth--;
073                                    if (depth == 0) {
074                                            state = STATE_END_DOC;
075                                    }
076                            }
077                            break;
078                    case STATE_END_DOC:
079                            event = END_DOCUMENT;
080                            break;
081                    default:
082                            throw new IllegalStateException();
083                    }
084                    return event;
085            }
086    
087        public int nextTag() throws XMLStreamException {
088            int eventType = next();
089            while((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace
090                || (eventType == XMLStreamConstants.CDATA && isWhiteSpace()) // skip whitespace
091                || eventType == XMLStreamConstants.SPACE
092                || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
093                || eventType == XMLStreamConstants.COMMENT) {
094                eventType = next();
095             }
096             if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
097                 throw new XMLStreamException("expected start or end tag", getLocation());
098             }
099             return eventType;    
100        }
101        
102        public int getNamespaceCount() {
103            if (state == STATE_FIRST_RUN && rootPrefixes != null) {
104                return rootPrefixes.size();
105            } else {
106                return getParent().getNamespaceCount();
107            }
108        }
109        
110        public String getNamespacePrefix(int i) {
111            if (state == STATE_FIRST_RUN && rootPrefixes != null) {
112                return (String) rootPrefixes.get(i);
113            } else {
114                return getParent().getNamespacePrefix(i);
115            }
116        }
117        
118        public String getNamespaceURI(int i) {
119            if (state == STATE_FIRST_RUN && rootPrefixes != null) {
120                return getParent().getNamespaceContext().getNamespaceURI(rootPrefixes.get(i));
121            } else {
122                return getParent().getNamespaceURI(i);
123            }
124        }
125        
126        public String getNamespaceURI(String prefix) {
127            if (state == STATE_FIRST_RUN) {
128                return getParent().getNamespaceContext().getNamespaceURI(prefix);
129            } else {
130                return getParent().getNamespaceURI(prefix);
131            }
132        }
133    
134        public boolean isStartElement() {
135            return event == START_ELEMENT;
136        }
137    
138        public boolean isEndElement() {
139            return event == END_ELEMENT;
140        }
141    
142        public boolean isCharacters() {
143            return event == CHARACTERS;
144        }
145    
146        public boolean isWhiteSpace() {
147            return event == SPACE;
148        }
149    
150        public boolean hasName() {
151            return (event == START_ELEMENT || event == END_ELEMENT);
152        }
153    
154        public boolean hasText() {
155            return (event == CHARACTERS || event == DTD || event == ENTITY_REFERENCE
156                            || event == COMMENT || event == SPACE);
157        }
158    
159    }