/* Woodstox XML processor
 *
 * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi
 *
 * Licensed under the License specified in file LICENSE, included with
 * the source code.
 * You may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ctc.wstx.evt;

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

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;

import org.codehaus.stax2.XMLStreamWriter2;
import org.codehaus.stax2.ri.evt.BaseEventImpl;

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

Shared base class of StartElement implementations Wstx uses.
/** * Shared base class of {@link StartElement} implementations Wstx uses. */
abstract class BaseStartElement extends BaseEventImpl implements StartElement { protected final QName mName; protected final BaseNsContext mNsCtxt; /* ///////////////////////////////////////////// // Life cycle ///////////////////////////////////////////// */ protected BaseStartElement(Location loc, QName name, BaseNsContext nsCtxt) { super(loc); mName = name; mNsCtxt = nsCtxt; } /* ///////////////////////////////////////////// // StartElement API ///////////////////////////////////////////// */ @Override public abstract Attribute getAttributeByName(QName name); @Override public abstract Iterator<Attribute> getAttributes(); @Override public final QName getName() { return mName; } @Override public Iterator<Namespace> getNamespaces() { if (mNsCtxt == null) { return DataUtil.emptyIterator(); } /* !!! 28-Sep-2004: Should refactor, since now it's up to ns context * to construct namespace events... which adds unnecessary * up-dependency from stream level to event objects. */ return mNsCtxt.getNamespaces(); } @Override public NamespaceContext getNamespaceContext() { return mNsCtxt; } @Override public String getNamespaceURI(String prefix) { return (mNsCtxt == null) ? null : mNsCtxt.getNamespaceURI(prefix); } /* ///////////////////////////////////////////////////// // Implementation of abstract base methods, overrides ///////////////////////////////////////////////////// */ @Override public StartElement asStartElement() { // overriden to save a cast return this; } @Override public int getEventType() { return START_ELEMENT; } @Override public boolean isStartElement() { return true; } @Override public void writeAsEncodedUnicode(Writer w) throws XMLStreamException { try { w.write('<'); String prefix = mName.getPrefix(); if (prefix != null && prefix.length() > 0) { w.write(prefix); w.write(':'); } w.write(mName.getLocalPart()); // Base class can output namespaces and attributes: outputNsAndAttr(w); w.write('>'); } catch (IOException ie) { throw new WstxIOException(ie); } } @Override public void writeUsing(XMLStreamWriter2 w) throws XMLStreamException { QName n = mName; w.writeStartElement(n.getPrefix(), n.getLocalPart(), n.getNamespaceURI()); outputNsAndAttr(w); } protected abstract void outputNsAndAttr(Writer w) throws IOException; protected abstract void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException; /* /////////////////////////////////////////// // Standard method implementation // // note: copied from Stax2 RI's StartElementEventImpl /////////////////////////////////////////// */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (!(o instanceof StartElement)) return false; StartElement other = (StartElement) o; // First things first: names must match if (mName.equals(other.getName())) { /* Rest is much trickier. I guess the easiest way is to * just blindly iterate through ns decls and attributes. * The main issue is whether ordering should matter; it will, * if just iterating. Would need to sort to get canonical * comparison. */ if (iteratedEquals(getNamespaces(), other.getNamespaces())) { return iteratedEquals(getAttributes(), other.getAttributes()); } } return false; } @Override public int hashCode() { int hash = mName.hashCode(); hash = addHash(getNamespaces(), hash); hash = addHash(getAttributes(), hash); return hash; } }