[Japi-cvs] SF.net SVN: japi:[1277] libs/xml/trunk/src
Status: Beta
Brought to you by:
christianhujer
From: <chr...@us...> - 2009-05-09 18:30:50
|
Revision: 1277 http://japi.svn.sourceforge.net/japi/?rev=1277&view=rev Author: christianhujer Date: 2009-05-09 18:30:43 +0000 (Sat, 09 May 2009) Log Message: ----------- Added SimpleNamespaceContext. Added Paths: ----------- libs/xml/trunk/src/prj/net/sf/japi/xml/SimpleNamespaceContext.java libs/xml/trunk/src/tst/test/net/sf/japi/xml/SimpleNamespaceContextTest.java Added: libs/xml/trunk/src/prj/net/sf/japi/xml/SimpleNamespaceContext.java =================================================================== --- libs/xml/trunk/src/prj/net/sf/japi/xml/SimpleNamespaceContext.java (rev 0) +++ libs/xml/trunk/src/prj/net/sf/japi/xml/SimpleNamespaceContext.java 2009-05-09 18:30:43 UTC (rev 1277) @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2009 Christian Hujer. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package net.sf.japi.xml; + +import org.jetbrains.annotations.NotNull; + +import javax.xml.namespace.NamespaceContext; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** Configurable namespace context. + * @author <a href="mailto:ch...@ri...">Christian Hujer</a> + */ +public class SimpleNamespaceContext implements NamespaceContext { + + /** Default prefix to namespace mapping. */ + private static final Map<String, String> DEFAULT_PREFIX_TO_NAMESPACE; + + /** Default namespace to prefix mapping. */ + private static final Map<String, List<String>> DEFAULT_NAMESPACE_TO_PREFIX; + + /** Prefix to namespace mapping (unique). */ + private final Map<String, String> prefixToNamespace = new HashMap<String, String>(); + + /** Namespace to prefix mapping (not unique). */ + private final Map<String, List<String>> namespaceToPrefix = new HashMap<String, List<String>>(); + + static { + // Create the default mappings which are always required. + final Map<String, String> defaultPrefixToNamespace = new HashMap<String, String>(); + final Map<String, List<String>> defaultNamespaceToPrefix = new HashMap<String, List<String>>(); + mapImpl(defaultPrefixToNamespace, defaultNamespaceToPrefix, "", ""); + mapImpl(defaultPrefixToNamespace, defaultNamespaceToPrefix, "xml", "http://www.w3.org/XML/1998/namespace"); + mapImpl(defaultPrefixToNamespace, defaultNamespaceToPrefix, "xmlns", "http://www.w3.org/2000/xmlns/"); + for (final Map.Entry<String, List<String>> entry : defaultNamespaceToPrefix.entrySet()) { + entry.setValue(Collections.unmodifiableList(entry.getValue())); + } + DEFAULT_NAMESPACE_TO_PREFIX = Collections.unmodifiableMap(defaultNamespaceToPrefix); + DEFAULT_PREFIX_TO_NAMESPACE = Collections.unmodifiableMap((defaultPrefixToNamespace)); + } + + { + // Copy the default mappings which are always required. + prefixToNamespace.putAll(DEFAULT_PREFIX_TO_NAMESPACE); + namespaceToPrefix.putAll(DEFAULT_NAMESPACE_TO_PREFIX); + // The mappings stay unmodifiable except the default namespace / prefix "". + namespaceToPrefix.put("", new ArrayList<String>(namespaceToPrefix.get(""))); + } + + /** Create a simple Namespace context. + * @param mapping Strings which are pairs of prefix and namespace. + */ + public SimpleNamespaceContext(@NotNull final String... mapping) { + for (int i = 0; i < mapping.length; i += 2) { + map(mapping[i], mapping[i + 1]); + } + } + + /** Adds a new mapping to this namespace context. + * @param prefix Prefix to map. any previous mapping of <var>prefix</var> will be replaced. + * @param namespaceURI Namespace to map. Any previous mapping of namespaceURI will be extended. + */ + public void map(@NotNull final String prefix, @NotNull final String namespaceURI) { + map(prefixToNamespace, namespaceToPrefix, prefix, namespaceURI); + } + + /** Adds a new mapping to this namespace context. + * @param prefixToNamespace Prefix to namespace mapping to extend. + * @param namespaceToPrefix Namespace to prefix mapping to extend. + * @param prefix Prefix to map. any previous mapping of <var>prefix</var> will be replaced. + * @param namespaceURI Namespace to map. Any previous mapping of namespaceURI will be extended. + */ + private static void map(@NotNull final Map<String, String> prefixToNamespace, @NotNull final Map<String, List<String>> namespaceToPrefix, @NotNull final String prefix, @NotNull final String namespaceURI) { + if (!"".equals(prefix) && DEFAULT_PREFIX_TO_NAMESPACE.containsKey(prefix)) { + if (DEFAULT_PREFIX_TO_NAMESPACE.get(prefix).equals(namespaceURI)) { + return; + } + throw new IllegalArgumentException("Prefix " + prefix + " is fixed to namespace " + DEFAULT_PREFIX_TO_NAMESPACE.get(prefix) + " and MUST NOT be remapped."); + } + if (!"".equals(namespaceURI) && DEFAULT_NAMESPACE_TO_PREFIX.containsKey(namespaceURI)) { + if (DEFAULT_NAMESPACE_TO_PREFIX.get(namespaceURI).get(0).equals(prefix)) { + return; + } + throw new IllegalArgumentException("Namespace " + namespaceURI + " is fixed to prefix " + DEFAULT_NAMESPACE_TO_PREFIX.get(prefix).get(0) + " and MUST NOT be remapped."); + } + mapImpl(prefixToNamespace, namespaceToPrefix, prefix, namespaceURI); + } + + /** Adds a new mapping to this namespace context. + * @param prefixToNamespace Prefix to namespace mapping to extend. + * @param namespaceToPrefix Namespace to prefix mapping to extend. + * @param prefix Prefix to map. any previous mapping of <var>prefix</var> will be replaced. + * @param namespaceURI Namespace to map. Any previous mapping of namespaceURI will be extended. + */ + private static void mapImpl(@NotNull final Map<String, String> prefixToNamespace, @NotNull final Map<String, List<String>> namespaceToPrefix, @NotNull final String prefix, @NotNull final String namespaceURI) { + if (prefixToNamespace.containsKey(prefix)) { + namespaceToPrefix.get(prefixToNamespace.get(prefix)).remove(prefix); + } + prefixToNamespace.put(prefix, namespaceURI); + if (!namespaceToPrefix.containsKey(namespaceURI)) { + namespaceToPrefix.put(namespaceURI, new ArrayList<String>()); + } + namespaceToPrefix.get(namespaceURI).add(prefix); + } + + /** {@inheritDoc} */ + public String getNamespaceURI(@NotNull final String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Namespace prefix MUST NOT be null."); + } + final String namespaceURI = prefixToNamespace.get(prefix); + return namespaceURI != null ? namespaceURI : ""; + } + + /** {@inheritDoc} */ + public String getPrefix(@NotNull final String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace prefix MUST NOT be null."); + } + final List<String> namespaces = namespaceToPrefix.get(namespaceURI); + assert namespaces == null || namespaces.size() > 0; + return namespaces == null ? null : namespaces.get(0); + } + + /** {@inheritDoc} */ + public Iterator getPrefixes(@NotNull final String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace prefix MUST NOT be null."); + } + final List<String> namespaces = namespaceToPrefix.get(namespaceURI); + return (namespaces == null ? Collections.EMPTY_SET : Collections.unmodifiableCollection(namespaces)).iterator(); + } +} Property changes on: libs/xml/trunk/src/prj/net/sf/japi/xml/SimpleNamespaceContext.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + LF Added: libs/xml/trunk/src/tst/test/net/sf/japi/xml/SimpleNamespaceContextTest.java =================================================================== --- libs/xml/trunk/src/tst/test/net/sf/japi/xml/SimpleNamespaceContextTest.java (rev 0) +++ libs/xml/trunk/src/tst/test/net/sf/japi/xml/SimpleNamespaceContextTest.java 2009-05-09 18:30:43 UTC (rev 1277) @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2009 Christian Hujer. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package test.net.sf.japi.xml; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import net.sf.japi.xml.SimpleNamespaceContext; +import org.junit.Test; +import org.junit.Assert; + +/** UnitTest for {@link SimpleNamespaceContext}. + * @author <a href="mailto:ch...@ri...">Christian Hujer</a> + */ +public class SimpleNamespaceContextTest { + + /** Tests that {@link SimpleNamespaceContext#getNamespaceURI(String)} returns correct defaults. + * @see javax.xml.namespace.NamespaceContext#getNamespaceURI(String) + */ + @Test public void testDefaultGetNamespaceURI() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + Assert.assertEquals("The empty prefix \"\" must be initially mapped to the default namespace \"\".", "", testling.getNamespaceURI("")); + Assert.assertEquals("The prefix \"xml\" must be mapped to the namespace \"http://www.w3.org/XML/1998/namespace\".", "http://www.w3.org/XML/1998/namespace", testling.getNamespaceURI("xml")); + Assert.assertEquals("The prefix \"xmlns\" must be mapped to the namespace \"http://www.w3.org/2000/xmlns/\".", "http://www.w3.org/2000/xmlns/", testling.getNamespaceURI("xmlns")); + } + + /** Tests that {@link SimpleNamespaceContext#getNamespaceURI(String)} with null throws IllegalArgumentException. + * @see javax.xml.namespace.NamespaceContext#getNamespaceURI(String) + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testDefaultGetNamespaceURINull() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.getNamespaceURI(null); + } + + /** Tests that {@link net.sf.japi.xml.SimpleNamespaceContext#getPrefix(String)} returns correct defaults. + * @see javax.xml.namespace.NamespaceContext#getPrefix(String) + */ + @Test public void testDefaultGetPrefix() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + Assert.assertEquals("The default namespace \"\" must be initially mapped to the empty prefix \"\".", "", testling.getPrefix("")); + Assert.assertEquals("The namespace \"http://www.w3.org/XML/1998/namespace\" must be mapped to the prefix \"xml\".", "xml", testling.getPrefix("http://www.w3.org/XML/1998/namespace")); + Assert.assertEquals("The namespace \"http://www.w3.org/2000/xmlns/\" must be mapped to the prefix \"xmlns\".", "xmlns", testling.getPrefix("http://www.w3.org/2000/xmlns/")); + } + + /** Tests that {@link SimpleNamespaceContext#getPrefix(String)} with null throws IllegalArgumentException. + * @see javax.xml.namespace.NamespaceContext#getPrefix(String) + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testDefaultGetPrefixNull() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.getPrefix(null); + } + + /** Tests that legal remappings of the default namespaces are accepted. */ + @Test public void testLegalRemap() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.map("xml", "http://www.w3.org/XML/1998/namespace"); + testling.map("xmlns", "http://www.w3.org/2000/xmlns/"); + } + + /** Tests that illegally remapping the prefix "xml" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testRemapXmlPrefixImpossible() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.map("xml", ""); + } + + /** Tests that illegally remapping the prefix "xmlns" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testRemapXmlnsPrefixImpossible() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.map("xmlns", ""); + } + + /** Tests that illegally remapping the namespace of "xml" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testRemapXmlNamespaceImpossible() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.map("", "http://www.w3.org/XML/1998/namespace"); + } + + /** Tests that illegally remapping the namespace of "xmlns" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testRemapXmlnsNamespaceImpossible() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + testling.map("", "http://www.w3.org/2000/xmlns/"); + } + + /** Tests that illegally mapping the prefix "xml" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testMapXmlPrefixImpossible() { + new SimpleNamespaceContext("xml", ""); + } + + /** Tests that illegally mapping the prefix "xmlns" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testMapXmlnsPrefixImpossible() { + new SimpleNamespaceContext("xmlns", ""); + } + + /** Tests that illegally mapping the namespace of "xml" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testMapXmlNamespaceImpossible() { + new SimpleNamespaceContext("", "http://www.w3.org/XML/1998/namespace"); + } + + /** Tests that illegally mapping the namespace of "xmlns" is not possible. + * @throws IllegalArgumentException (expected). + */ + @Test(expected = IllegalArgumentException.class) + public void testMapXmlnsNamespaceImpossible() { + new SimpleNamespaceContext("", "http://www.w3.org/2000/xmlns/"); + } + + + /** Tests that mapping a new prefix works. */ + @Test + public void testSimpleMap() { + final SimpleNamespaceContext testling = new SimpleNamespaceContext(); + + testling.map("", "http://www.w3.org/1999/xhtml"); + testling.map("html", "http://www.w3.org/1999/xhtml"); + + final Set<String> expectedPrefixes = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("", "html"))); + + Assert.assertEquals("http://www.w3.org/1999/xhtml", testling.getNamespaceURI("")); + Assert.assertEquals("http://www.w3.org/1999/xhtml", testling.getNamespaceURI("html")); + + Assert.assertTrue(expectedPrefixes.contains(testling.getPrefix("http://www.w3.org/1999/xhtml"))); + + Assert.assertEquals(expectedPrefixes, collect(new HashSet<String>(), testling.getPrefixes("http://www.w3.org/1999/xhtml"))); + } + + /** Collects items from an Iterator into a Collection. + * @param c Collection to which the items shall be collected. + * @param iterator Iterator from which to collect items. + * @return <var>c</var> after the items from <var>iterator</var> have been added to it. + */ + private static <T, C extends Collection<T>> C collect(final C c, final Iterator<T> iterator) { + while (iterator.hasNext()) { + c.add(iterator.next()); + } + return c; + } + +} Property changes on: libs/xml/trunk/src/tst/test/net/sf/japi/xml/SimpleNamespaceContextTest.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + LF This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |