1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.util;
23
24 import static com.entwinemedia.fn.Stream.$;
25 import static org.opencastproject.util.EqualsUtil.eq;
26 import static org.opencastproject.util.data.Option.option;
27
28 import org.opencastproject.util.data.Function0;
29
30 import com.entwinemedia.fn.Fn;
31 import com.entwinemedia.fn.Fn2;
32 import com.entwinemedia.fn.Stream;
33 import com.entwinemedia.fn.data.Opt;
34 import com.entwinemedia.fn.fns.Booleans;
35
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Map.Entry;
42
43 import javax.xml.XMLConstants;
44 import javax.xml.namespace.NamespaceContext;
45
46 public final class XmlNamespaceContext implements NamespaceContext {
47
48 private static final int DEFAULT_BINDINGS = 2;
49
50
51 private final Map<String, String> prefixToUri = new HashMap<String, String>();
52
53
54
55
56
57 public XmlNamespaceContext(Map<String, String> prefixToUri) {
58 this.prefixToUri.putAll(prefixToUri);
59 this.prefixToUri.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
60 this.prefixToUri.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
61 }
62
63 public static XmlNamespaceContext mk(Map<String, String> prefixToUri) {
64 return new XmlNamespaceContext(prefixToUri);
65 }
66
67 public static XmlNamespaceContext mk(XmlNamespaceBinding... bindings) {
68 return mk($(bindings));
69 }
70
71 public static XmlNamespaceContext mk(String prefix, String namespaceUri) {
72 return new XmlNamespaceContext(Collections.singletonMap(prefix, namespaceUri));
73 }
74
75 public static XmlNamespaceContext mk(List<XmlNamespaceBinding> bindings) {
76 return mk($(bindings));
77 }
78
79 public static XmlNamespaceContext mk(Stream<XmlNamespaceBinding> bindings) {
80 return new XmlNamespaceContext(
81 bindings.foldl(
82 new HashMap<String, String>(),
83 new Fn2<HashMap<String, String>, XmlNamespaceBinding, HashMap<String, String>>() {
84 @Override
85 public HashMap<String, String> apply(
86 HashMap<String, String> prefixToUri, XmlNamespaceBinding binding) {
87 prefixToUri.put(binding.getPrefix(), binding.getNamespaceURI());
88 return prefixToUri;
89 }
90 }));
91 }
92
93 @Override
94 public String getNamespaceURI(String prefix) {
95 return Opt.nul(prefixToUri.get(prefix)).getOr(XMLConstants.NULL_NS_URI);
96 }
97
98 @Override
99 public String getPrefix(String uri) {
100 return $(prefixToUri.entrySet()).find(Booleans.eq(RequireUtil.notNull(uri, "uri")).o(value)).map(key).orNull();
101 }
102
103 @Override
104 public Iterator getPrefixes(String uri) {
105 return $(prefixToUri.entrySet()).filter(Booleans.eq(uri).o(value)).map(key).iterator();
106 }
107
108 public List<XmlNamespaceBinding> getBindings() {
109 return $(prefixToUri.entrySet()).map(toBinding).toList();
110 }
111
112
113 public XmlNamespaceContext add(XmlNamespaceBinding... bindings) {
114 return add($(bindings));
115 }
116
117
118 public XmlNamespaceContext add(XmlNamespaceContext bindings) {
119 if (bindings.prefixToUri.size() == DEFAULT_BINDINGS) {
120
121 return this;
122 } else {
123 return add($(bindings.getBindings()));
124 }
125 }
126
127 private XmlNamespaceContext add(Stream<XmlNamespaceBinding> bindings) {
128 return mk(bindings.append(getBindings()));
129 }
130
131 private static final Fn<Entry<String, String>, String> key = new Fn<Entry<String, String>, String>() {
132 @Override public String apply(Entry<String, String> e) {
133 return e.getKey();
134 }
135 };
136
137 private static final Fn<Entry<String, String>, String> value = new Fn<Entry<String, String>, String>() {
138 @Override public String apply(Entry<String, String> e) {
139 return e.getValue();
140 }
141 };
142
143 private static final Fn<Entry<String, String>, XmlNamespaceBinding> toBinding = new Fn<Entry<String, String>, XmlNamespaceBinding>() {
144 @Override public XmlNamespaceBinding apply(Entry<String, String> e) {
145 return new XmlNamespaceBinding(e.getKey(), e.getValue());
146 }
147 };
148
149 public NamespaceContext merge(final NamespaceContext precedence) {
150 return merge(this, precedence);
151 }
152
153
154 public static NamespaceContext merge(final NamespaceContext a, final NamespaceContext b) {
155 return new NamespaceContext() {
156 @Override public String getNamespaceURI(String prefix) {
157 final String uri = b.getNamespaceURI(prefix);
158 if (eq(XMLConstants.DEFAULT_NS_PREFIX, prefix) && eq(XMLConstants.NULL_NS_URI, uri)) {
159 return a.getNamespaceURI(prefix);
160 } else {
161 return uri;
162 }
163 }
164
165 @Override public String getPrefix(final String uri) {
166 return option(b.getPrefix(uri)).getOrElse(new Function0<String>() {
167 @Override public String apply() {
168 return a.getPrefix(uri);
169 }
170 });
171 }
172
173 @Override public Iterator getPrefixes(String uri) {
174 final Iterator prefixes = b.getPrefixes(uri);
175 if (prefixes.hasNext()) {
176 return prefixes;
177 } else {
178 return a.getPrefixes(uri);
179 }
180 }
181 };
182 }
183 }