All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ctc.wstx.sr.CompactNsContext Maven / Gradle / Ivy

The newest version!
package com.ctc.wstx.sr;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;

import javax.xml.XMLConstants;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.Namespace;

// This is unfortunate dependency, but...
import org.codehaus.stax2.ri.evt.NamespaceEventImpl;

import com.ctc.wstx.util.BaseNsContext;
import com.ctc.wstx.util.DataUtil;

/**
 * Simple implementation of separate non-transient namespace context
 * object. Created for start-element event by transient namespace
 * instance updated by stream reader.
 *

* Note about implementation: Location information is only needed (and * only needs to passed) if access is made via extended interface; one * that can return information about actual Namespace event objects. */ public final class CompactNsContext extends BaseNsContext { final Location mLocation; /** * Array that contains 2 Strings for each declared default namespace * (including default namespace declarations); first is the prefix, * second URI. */ final String[] mNamespaces; /** * Number of entries in {@link #mNamespaces} (which is twice the number * of bindings) */ final int mNsLength; /** * Index of first namespace pair in mNamespaces that is declared * in scope of element for which this context was constructed. May be * equal to {@link #mNsLength} (which indicates there are no local * bindings). */ final int mFirstLocalNs; /** * List only needed to support List accessor from start-element event; * created lazily if/as needed. */ transient ArrayList mNsList; public CompactNsContext(Location loc, String[] namespaces, int nsLen, int firstLocal) { mLocation = loc; mNamespaces = namespaces; mNsLength = nsLen; mFirstLocalNs = firstLocal; } /** * @param prefix Non-null, non-empty prefix (base-class verifies these * constraints) to find namespace URI for. */ @Override public String doGetNamespaceURI(String prefix) { /* Let's search from beginning towards end; this way we'll first * find the innermost (or, in case of same-level declaration, last) * declaration for prefix. */ // (note: default namespace will be there too) String[] ns = mNamespaces; if (prefix.length() == 0) { for (int i = mNsLength-2; i >= 0; i -= 2) { if (ns[i] == null) { return ns[i+1]; } } return null; // default ns not bound } for (int i = mNsLength-2; i >= 0; i -= 2) { if (prefix.equals(ns[i])) { return ns[i+1]; } } return null; } @Override public String doGetPrefix(String nsURI) { // Note: base class checks for 'known' problems and prefixes: String[] ns = mNamespaces; int len = mNsLength; main_loop: for (int i = len-1; i > 0; i -= 2) { if (nsURI.equals(ns[i])) { /* 29-Sep-2004, TSa: Actually, need to make sure that this * declaration is not masked by a later declaration. * This happens when same prefix is declared on a later * entry (ie. for child element) */ String prefix = ns[i-1]; for (int j = i+1; j < len; j += 2) { // Prefixes are interned, can do straight equality check if (ns[j] == prefix) { continue main_loop; // was masked! } } String uri = ns[i-1]; /* 19-Mar-2006, TSa: Empty namespaces are represented by * null prefixes; but need to be represented as empty * strings (to distinguish from unbound URIs). */ return (uri == null) ? "" : uri; } } return null; } @Override public Iterator doGetPrefixes(String nsURI) { // Note: base class checks for 'known' problems and prefixes: String[] ns = mNamespaces; int len = mNsLength; String first = null; ArrayList all = null; main_loop: for (int i = len-1; i > 0; i -= 2) { String currNS = ns[i]; if (currNS == nsURI || currNS.equals(nsURI)) { /* 29-Sep-2004, TSa: Need to ensure it's not masked by * a later ns declaration in a child element. */ String prefix = ns[i-1]; for (int j = i+1; j < len; j += 2) { // Prefixes are interned, can do straight equality check if (ns[j] == prefix) { continue main_loop; // was masked, need to ignore } } /* 19-Mar-2006, TSa: Empty namespaces are represented by * null prefixes; but need to be represented as empty * strings (to distinguish from unbound URIs). */ if (prefix == null) { prefix = ""; } if (first == null) { first = prefix; } else { if (all == null) { all = new ArrayList(); all.add(first); } all.add(prefix); } } } if (all != null) { return all.iterator(); } if (first != null) { return DataUtil.singletonIterator(first); } return DataUtil.emptyIterator(); } /* /////////////////////////////////////////////////////// // Extended API, needed by Wstx classes /////////////////////////////////////////////////////// */ @Override public Iterator getNamespaces() { if (mNsList == null) { int firstLocal = mFirstLocalNs; int len = mNsLength - firstLocal; if (len == 0) { // can this happen? return DataUtil.emptyIterator(); } if (len == 2) { // only one NS return DataUtil.singletonIterator(NamespaceEventImpl.constructNamespace (mLocation, mNamespaces[firstLocal], mNamespaces[firstLocal+1])); } ArrayList l = new ArrayList(len >> 1); String[] ns = mNamespaces; for (len = mNsLength; firstLocal < len; firstLocal += 2) { l.add(NamespaceEventImpl.constructNamespace(mLocation, ns[firstLocal], ns[firstLocal+1])); } mNsList = l; } return mNsList.iterator(); } /** * Method called by {@link com.ctc.wstx.evt.CompactStartElement} * to output all 'local' namespace declarations active in current * namespace scope, if any. Local means that declaration was done in * scope of current element, not in a parent element. */ @Override public void outputNamespaceDeclarations(Writer w) throws IOException { String[] ns = mNamespaces; for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { w.write(' '); w.write(XMLConstants.XMLNS_ATTRIBUTE); String prefix = ns[i]; if (prefix != null && prefix.length() > 0) { w.write(':'); w.write(prefix); } w.write("=\""); w.write(ns[i+1]); w.write('"'); } } @Override public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException { String[] ns = mNamespaces; for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { String nsURI = ns[i+1]; String prefix = ns[i]; if (prefix != null && prefix.length() > 0) { w.writeNamespace(prefix, nsURI); } else { w.writeDefaultNamespace(nsURI); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy