/* * eXist Open Source Native XML Database * Copyright (C) 2001-2007 The eXist Project * http://exist-db.org * * This program 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 * of the License, or (at your option) any later version. * * This program 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 program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ */ package org.exist.dom; import org.exist.numbering.NodeId; import org.exist.storage.Signatures; import org.exist.util.ByteConversion; import org.exist.util.pool.NodePool; import org.w3c.dom.Node; import org.w3c.dom.ProcessingInstruction; import java.io.UnsupportedEncodingException; /** * Persistent implementation of a DOM processing-instruction node. * * @author wolf */ public class ProcessingInstructionImpl extends StoredNode implements ProcessingInstruction { public static final int LENGTH_TARGET_DATA = 4; //Sizeof int; protected String target = null; protected String data = null; public ProcessingInstructionImpl() { super(Node.PROCESSING_INSTRUCTION_NODE); } public ProcessingInstructionImpl(NodeId nodeId, String target, String data) { super(Node.PROCESSING_INSTRUCTION_NODE, nodeId); this.target = target; this.data = data; } public ProcessingInstructionImpl(String target, String data) { this(null, target, data); } public void clear() { super.clear(); target = null; data = null; } /** * Gets the target attribute of the ProcessingInstructionImpl object * *@return The target value */ public String getTarget() { return target; } /** * Sets the target attribute of the ProcessingInstructionImpl object * *@param target The new target value */ public void setTarget(final String target) { this.target = target; } /* (non-Javadoc) * @see org.w3c.dom.Node#getNodeName() */ public String getNodeName() { return target; } public String getLocalName() { return target; } public String getNamespaceURI() { return ""; } /** * Gets the data attribute of the ProcessingInstructionImpl object * *@return The data value */ public String getData() { return data; } /** * Sets the data attribute of the ProcessingInstructionImpl object * *@param data The new data value */ public void setData(final String data) { this.data = data; } /** ? @see org.w3c.dom.Node#getBaseURI() */ public String getBaseURI() { String baseURI = ""; StoredNode parent = getParentStoredNode(); while (parent != null && parent.getBaseURI() != null) { if ("".equals(baseURI)) { baseURI = parent.getBaseURI(); } else { baseURI = parent.getBaseURI() + "/" + baseURI; } parent = parent.getParentStoredNode(); if (parent == null) return baseURI; } if ("".equals(baseURI)) { baseURI = getDocument().getBaseURI(); } return baseURI; } /** * Description of the Method * *@return Description of the Return Value */ public String toString() { StringBuilder buf = new StringBuilder(); buf.append( "<?" ); buf.append( target ); buf.append( " " ); buf.append( data ); buf.append( " ?>" ); return buf.toString(); } public byte[] serialize() { byte[] td; try { td = target.getBytes( "UTF-8" ); } catch ( UnsupportedEncodingException uee ) { LOG.warn(uee); td = target.getBytes(); } byte[] dd; try { dd = data.getBytes( "UTF-8" ); } catch ( UnsupportedEncodingException uee ) { LOG.warn(uee); dd = data.getBytes(); } int nodeIdLen = nodeId.size(); byte[] d = new byte[td.length + dd.length + nodeIdLen + 7]; int pos = 0; d[pos] = (byte) ( Signatures.Proc << 0x5 ); pos += LENGTH_SIGNATURE_LENGTH; ByteConversion.shortToByte((short) nodeId.units(), d, pos); pos += NodeId.LENGTH_NODE_ID_UNITS; nodeId.serialize(d, pos); pos += nodeIdLen; ByteConversion.intToByte(td.length, d, pos); pos += LENGTH_TARGET_DATA; System.arraycopy( td, 0, d, pos, td.length); pos += td.length; System.arraycopy( dd, 0, d, pos, dd.length); return d; } public static StoredNode deserialize(byte[] data, int start, int len, DocumentImpl doc, boolean pooled) { int pos = start; pos += LENGTH_SIGNATURE_LENGTH; int dlnLen = ByteConversion.byteToShort(data, pos); pos += NodeId.LENGTH_NODE_ID_UNITS; NodeId dln = doc.getBrokerPool().getNodeFactory().createFromData(dlnLen, data, pos); int nodeIdLen = dln.size(); pos += nodeIdLen; int l = ByteConversion.byteToInt(data, pos); pos += LENGTH_TARGET_DATA; String target; try { target = new String(data, pos, l, "UTF-8"); } catch (UnsupportedEncodingException uee) { LOG.warn(uee); target = new String(data, pos, l); } pos += l; String cdata; try { cdata = new String(data, pos, len - (pos - start), "UTF-8"); } catch (UnsupportedEncodingException uee) { LOG.warn(uee); cdata = new String(data, pos, len - (pos - start)); } //OK : we have the necessary material to build the processing instruction ProcessingInstructionImpl pi; if(pooled) pi = (ProcessingInstructionImpl) NodePool.getInstance().borrowNode(Node.PROCESSING_INSTRUCTION_NODE); // pi = (ProcessingInstructionImpl) // NodeObjectPool.getInstance().borrowNode(ProcessingInstructionImpl.class); else pi = new ProcessingInstructionImpl(); pi.setTarget(target); pi.data = cdata; pi.setNodeId(dln); return pi; } public boolean hasChildNodes() { return false; } public int getChildCount() { return 0; } public Node getFirstChild() { //bad implementations don't call hasChildNodes before return null; } }