今回は AbstractNamespaceContext の実装を考えます(一覧)。
AbstractNamespace は NamespaceContext の JavaDoc で規定された、「特別な引数」に対して「特別な返り値」を返す、という処理を行わせます。
getNamespaceURI(String) メソッドの実装
まず、AbstractNamespaceContext 以下の抽象メソッドを定義します:
protected abstract String getNamespaceURISimply(String uri);
このメソッドは、getNamespaceContext() メソッドと同様に、引数の接頭辞に対応する名前空間 URI を返します。 ただし、 固定された対応(null と接頭辞 "xml", "xmlns" に対するもの)を考慮する必要はありません(Simply)。
このメソッドを用いて getNamespaceURI(String) を以下のように実装します:
public String getNamespaceURI(String prefix) { if(prefix == null) throw new IllegalArgumentException("Prefix can't be null"); if(XML_NS_PREFIX.equals(prefix)) return XML_NS_URI; if(XMLNS_ATTRIBUTE.equals(prefix)) return XMLNS_ATTRIBUTE_NS_URI; return getNamespaceURISimply(prefix); }
getPrefix(String), getPrefixes(String) メソッドの実装
基本的には、これらも getNamespaceURI(String) メソッドと同様に、getXxxxSimply() メソッドを定義します。 ただし、getPrefixes(String) の返り値が Iterator で扱いにくいので、接頭辞のセット (Set
/** * 引数の名前空間 URI に対応する接頭辞のセットを返します。 * このメソッドの返り値の Set<String> に対して iterator() を呼び出すと、 * NamespaceContext#getPrefixes(String) * で規定されたイテレータが返されなければなりません。 */ private Set<String> getPrefixSet(String uri) { if(XML_NS_URI.equals(uri)) return Collections.singleton(XML_NS_PREFIX); if(XMLNS_ATTRIBUTE.equals(uri)) return Collections.singleton(XMLNS_ATTRIBUTE); return getPrefixSetSimply(uri); } protected abstract Set<String> getPrefixSetSimply(String uri);
この getPrefixSet(String) メソッドを用いて getPrefix(String), getPrefixes(String) を実装するのは以前の記事と同じなので省略。
定義された抽象メソッド
結局、定義された抽象メソッドは以下の2つです:
/** * 引数の接頭辞に対応する名前空間 URI を返します。 * ただし、 固定された対応(null と接頭辞 "xml", "xmlns" に対するもの)は * 考慮する必要はありません。 */ protected abstract String getNamespaceURISimply(String prefix); /** * 引数の名前空間 URI に対応する接頭辞のセットを返します。 * ただし、固定された対応(null と名前空間 URI "http://www.w3.org/XML/1998/namespace", * "http://www.w3.org/2000/xmlns/")は考慮する必要はありません。 */ protected abstract Set<String> getPrefixSetSimply(String uri);
Java コード
AbstractNamespaceContext の Java コードは以下のようになります(上記のコードから一部修正):
import java.util.*; import javax.xml.namespace.NamespaceContext; import static javax.xml.XMLConstants.*; /** @author waman */ public abstract class AbstractNamespaceContext implements NamespaceContext{ public String getNamespaceURI(String prefix) { if(prefix == null) throw new IllegalArgumentException("Prefix can't be null"); if(XML_NS_PREFIX.equals(prefix)) return XML_NS_URI; if(XMLNS_ATTRIBUTE.equals(prefix)) return XMLNS_ATTRIBUTE_NS_URI; return getNamespaceURISimply(prefix); } /** * 引数の接頭辞に対応する名前空間 URI を返します。 * ただし、 固定された対応(null と接頭辞 "xml", "xmlns" に対するもの)は * 考慮する必要はありません。 */ protected abstract String getNamespaceURISimply(String prefix); public String getPrefix(String uri) { Set<String> prefixes = getPrefixSet(uri); // unbound namespace uri if(prefixes.size() == 0) return null; // default namespace uri if(prefixes.contains(DEFAULT_NS_PREFIX)) return DEFAULT_NS_PREFIX; // bound namespace uri for(String prefix: prefixes) return prefix; throw new IllegalArgumentException(); } public Iterator<String> getPrefixes(String uri){ return getPrefixSet(uri).iterator(); } /** * 引数の名前空間 URI に対応する接頭辞のセットを返します。 * このメソッドの返り値の Set<String> に対して iterator() を呼び出すと、 * NamespaceContext#getPrefixes(String) * で規定されたイテレータが返されなければなりません。 */ private Set<String> getPrefixSet(String uri) { validateURI(uri); if(XML_NS_URI.equals(uri)) return Collections.singleton(XML_NS_PREFIX); if(XMLNS_ATTRIBUTE.equals(uri)) return Collections.singleton(XMLNS_ATTRIBUTE); return getPrefixSetSimply(uri); } private void validateURI(String uri){ if(uri == null || NULL_NS_URI.equals(uri)) throw new IllegalArgumentException("URI can't be null or empty String"); } /** * 引数の名前空間 URI に対応する接頭辞のセットを返します。 * ただし、固定された対応(null と名前空間 URI "http://www.w3.org/XML/1998/namespace", * "http://www.w3.org/2000/xmlns/")は考慮する必要はありません。 */ protected abstract Set<String> getPrefixSetSimply(String uri); }
*1:これは以前の記事で getPrefixList(String) としていたものです。 List