/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.cxf.helpers; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class NSStack { private static final String NS_PREFIX_PREFIX = "ns"; private final List<List<NSDecl>> stack = new ArrayList<List<NSDecl>>(); private List<NSDecl> top; private int size; private int nsPrefixCount = 1; public synchronized void push() { top = new ArrayList<>(); stack.add(top); size++; } /** * Leave a scope: this removes any NS declarations that were added * in the last scope. Note that I don't bother to validate that you * don't call popScope too many times; that's your problem. */ public synchronized void pop() { stack.remove(--size); top = null; if (size != 0) { top = stack.get(size - 1); } } /** * Add a new declaration to the current scope. This is visible within * the current scope as well as from any nested scopes. * * @param prefix the prefix to be used for this namespace * @param uri the namespace name of this namespace. */ public synchronized void add(String prefix, String uri) { top.add(new NSDecl(prefix, uri)); } /** * Add a new declaration to the current scope using a unique prefix * and return the prefix. This is useful when one just wants to add a * decl and doesn't want to have to deal with creating unique prefixes. * If the namespace name is already declared and in scope, then the * previously declared prefix is returned. * * @param uri the namespace name of this namespace * @return the unique prefix created or previously declared * for this namespace */ public synchronized String add(String uri) { String uniquePrefix = getPrefix(uri); if (uniquePrefix == null) { do { uniquePrefix = NS_PREFIX_PREFIX + nsPrefixCount++; } while (getURI(uniquePrefix) != null); add(uniquePrefix, uri); } return uniquePrefix; } /** * Return the prefix associated with the given namespace name by * looking thru all the namespace declarations that are in scope. * * @param uri the namespace name for whom a declared prefix is desired * @return the prefix or null if namespace name not found */ public synchronized String getPrefix(String uri) { for (int i = size - 1; i >= 0; i--) { List<NSDecl> scope = stack.get(i); ListIterator<NSDecl> lsIterator = scope.listIterator(); while (lsIterator.hasNext()) { NSDecl nsd = lsIterator.next(); if (nsd.getUri().equals(uri)) { return nsd.getPrefix(); } } } return null; } /** * Return the namespace name associated with the given prefix by * looking thru all the namespace declarations that are in scope. * * @param prefix the prefix for whom a declared namespace name is desired * @return the namespace name or null if prefix not found */ public synchronized String getURI(String prefix) { for (int i = size - 1; i >= 0; i--) { List<NSDecl> scope = stack.get(i); ListIterator<NSDecl> lsIterator = scope.listIterator(); while (lsIterator.hasNext()) { NSDecl nsd = lsIterator.next(); if (nsd.getPrefix().equals(prefix)) { return nsd.getUri(); } } } return null; } }