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 */ 017package org.apache.camel.builder.xml; 018 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.Iterator; 022import java.util.Map; 023import java.util.Map.Entry; 024import java.util.Set; 025import javax.xml.namespace.NamespaceContext; 026import javax.xml.xpath.XPathFactory; 027 028import org.apache.camel.spi.NamespaceAware; 029import org.apache.camel.util.CastUtils; 030 031/** 032 * An implementation of {@link NamespaceContext} which uses a simple Map where 033 * the keys are the prefixes and the values are the URIs 034 */ 035public class DefaultNamespaceContext implements NamespaceContext, NamespaceAware { 036 037 private final Map<String, String> map; 038 private final NamespaceContext parent; 039 040 public DefaultNamespaceContext() { 041 this(XPathFactory.newInstance()); 042 } 043 044 public DefaultNamespaceContext(XPathFactory factory) { 045 this.parent = factory.newXPath().getNamespaceContext(); 046 this.map = new HashMap<String, String>(); 047 } 048 049 public DefaultNamespaceContext(NamespaceContext parent, Map<String, String> map) { 050 this.parent = parent; 051 this.map = map; 052 } 053 054 /** 055 * A helper method to make it easy to create newly populated instances 056 */ 057 public DefaultNamespaceContext add(String prefix, String uri) { 058 map.put(prefix, uri); 059 return this; 060 } 061 062 public String getNamespaceURI(String prefix) { 063 String answer = map.get(prefix); 064 if (answer == null && parent != null) { 065 return parent.getNamespaceURI(prefix); 066 } 067 return answer; 068 } 069 070 public String getPrefix(String namespaceURI) { 071 for (Entry<String, String> entry : map.entrySet()) { 072 if (namespaceURI.equals(entry.getValue())) { 073 return entry.getKey(); 074 } 075 } 076 if (parent != null) { 077 return parent.getPrefix(namespaceURI); 078 } 079 return null; 080 } 081 082 public Iterator<String> getPrefixes(String namespaceURI) { 083 Set<String> set = new HashSet<String>(); 084 for (Entry<String, String> entry : map.entrySet()) { 085 if (namespaceURI.equals(entry.getValue())) { 086 set.add(entry.getKey()); 087 } 088 } 089 if (parent != null) { 090 Iterator<String> iter = CastUtils.cast(parent.getPrefixes(namespaceURI)); 091 while (iter.hasNext()) { 092 set.add(iter.next()); 093 } 094 } 095 return set.iterator(); 096 } 097 098 public void setNamespaces(Map<String, String> namespaces) { 099 map.putAll(namespaces); 100 } 101 102 public Map<String, String> getNamespaces() { 103 return map; 104 } 105 106 /** 107 * toString() implementation that outputs the namespace mappings with the following format: "[me: {prefix -> value}, {prefix -> value}], [parent: {prefix -> value}, {prefix -> value}]. 108 * Recurses up the parent's chain. 109 */ 110 @Override 111 public String toString() { 112 StringBuilder sb = new StringBuilder("[me: "); 113 for (Entry<String, String> nsEntry : map.entrySet()) { 114 sb.append("{" + nsEntry.getKey() + " -> " + nsEntry.getValue() + "},"); 115 } 116 if (!map.isEmpty()) { 117 // remove the last comma 118 sb.deleteCharAt(sb.length() - 1); 119 } 120 sb.append("]"); 121 122 // Get the parent's namespace mappings 123 if (parent != null) { 124 sb.append(", [parent: "); 125 sb.append(parent.toString()); 126 sb.append("]"); 127 } 128 return sb.toString(); 129 } 130 131}