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.Collection;
020    import java.util.HashMap;
021    import java.util.HashSet;
022    import java.util.Iterator;
023    import java.util.Map;
024    
025    import javax.xml.namespace.NamespaceContext;
026    import javax.xml.stream.XMLStreamConstants;
027    import javax.xml.stream.XMLStreamException;
028    import javax.xml.stream.XMLStreamReader;
029    import javax.xml.stream.util.StreamReaderDelegate;
030    
031    public class ExtendedXMLStreamReader extends StreamReaderDelegate {
032    
033            private SimpleNamespaceContext context = new SimpleNamespaceContext();
034            
035            public ExtendedXMLStreamReader(XMLStreamReader delegate) {
036                    super(delegate);
037            }
038    
039            public NamespaceContext getNamespaceContext() {
040                    return context;
041            }
042            
043        public int nextTag() throws XMLStreamException {
044            int eventType = next();
045             while((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace
046                     || (eventType == XMLStreamConstants.CDATA && isWhiteSpace()) 
047                     // skip whitespace
048                     || eventType == XMLStreamConstants.SPACE
049                     || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
050                     || eventType == XMLStreamConstants.COMMENT
051                     ) {
052                     eventType = next();
053             }
054             if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
055                    throw new XMLStreamException("expected start or end tag", getLocation());
056             }
057             return eventType;
058        }
059    
060            public int next() throws XMLStreamException {
061                    int next = super.next();
062                    if (next == START_ELEMENT) {
063                            context = new SimpleNamespaceContext(context, getNamespaces());
064                    } else if (next == END_ELEMENT) {
065                            context = context.getParent();
066                    }
067                    return next;
068            }
069    
070            private Map<String, String> getNamespaces() {
071                    Map<String,String> ns = new HashMap<String,String>();
072                    for (int i = 0; i < getNamespaceCount(); i++) {
073                            ns.put(getNamespacePrefix(i), getNamespaceURI(i));
074                    }
075                    return ns;
076            }
077            
078            public static class SimpleNamespaceContext implements ExtendedNamespaceContext {
079    
080                    private SimpleNamespaceContext parent;
081                    private Map<String,String> namespaces;
082                    
083                    public SimpleNamespaceContext() {
084                            namespaces = new HashMap<String,String>();
085                    }
086    
087                    public SimpleNamespaceContext(SimpleNamespaceContext parent, Map<String,String> namespaces) {
088                            this.parent = parent;
089                            this.namespaces = namespaces;
090                    }
091    
092                    public SimpleNamespaceContext getParent() {
093                            return parent;
094                    }
095                    
096                    public Collection<String> getPrefixes() {
097                            HashSet<String> prefixes = new HashSet<String>();
098                            for (SimpleNamespaceContext context = this; context != null; context = context.parent) {
099                                    prefixes.addAll(context.namespaces.keySet());
100                            }
101                            return prefixes;
102                    }
103    
104                    public String getNamespaceURI(String prefix) {
105                            String uri = namespaces.get(prefix);
106                            if (uri == null && parent != null) {
107                                    uri = parent.getNamespaceURI(prefix);
108                            }
109                            return uri;
110                    }
111    
112                    public String getPrefix(String namespaceURI) {
113                            for (SimpleNamespaceContext context = this; context != null; context = context.parent) {
114                    for (Map.Entry<String, String> entry : context.namespaces.entrySet()) {
115                                            if (entry.getValue().equals(namespaceURI)) {
116                                                    return entry.getKey();
117                                            }
118                                    }
119                            }
120                            return null;
121                    }
122    
123                    public Iterator<String> getPrefixes(String namespaceURI) {
124                            HashSet<String> prefixes = new HashSet<String>();
125                for (SimpleNamespaceContext context = this; context != null; context = context.parent) {
126                    for (Map.Entry<String, String> entry : context.namespaces.entrySet()) {
127                        if (entry.getValue().equals(namespaceURI)) {
128                                                    prefixes.add(entry.getKey());
129                                            }
130                                    }
131                            }
132                            return prefixes.iterator();
133                    }
134                    
135            }
136    
137    
138    }