/* * eXist Open Source Native XML Database * Copyright (C) 2001-04 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id$ */ package org.exist.xquery.value; import org.exist.xquery.XPathException; public class HexBinary extends BinaryValue { public HexBinary(byte[] data) { super(data); } public HexBinary(String in) throws XPathException { in = StringValue.trimWhitespace(in); if ((in.length() & 1) != 0) { throw new XPathException("FORG0001: A hexBinary value must contain an even " + "number of characters"); } data = new byte[in.length() / 2]; for (int i = 0; i < data.length; i++) { data[i] = (byte)((fromHex(in.charAt(2*i))<<4) + (fromHex(in.charAt(2*i+1)))); } } public int getType() { return Type.HEX_BINARY; } /** * Decode a single hex digit * @param c the hex digit * @return the numeric value of the hex digit * @throws XPathException if it isn't a hex digit */ private int fromHex(char c) throws XPathException { int d = "0123456789ABCDEFabcdef".indexOf(c); if (d > 15) { d = d - 6; } if (d < 0) { throw new XPathException("FORG0001: Invalid hexadecimal digit: " + c); } return d; } public AtomicValue convertTo(int requiredType) throws XPathException { switch (requiredType) { case Type.HEX_BINARY: return this; case Type.BASE64_BINARY: return new Base64Binary(data); case Type.UNTYPED_ATOMIC: //Added trim() since it looks like a new line character is added return new UntypedAtomicValue(getStringValue().trim()); case Type.STRING: return new StringValue(getStringValue()); default: throw new XPathException("cannot convert " + Type.getTypeName(getType()) + " to " + Type.getTypeName(requiredType)); } } public String getStringValue() throws XPathException { String digits = "0123456789ABCDEF"; StringBuilder sb = new StringBuilder(data.length * 2); for (int i=0; i<data.length; i++) { sb.append(digits.charAt((data[i]>>4)&0xf)); sb.append(digits.charAt(data[i]&0xf)); } return sb.toString(); } public Object toJavaObject(Class target) throws XPathException { if(target.isAssignableFrom(HexBinary.class)) return this; if (target.isArray() && target == Byte.class) return data; throw new XPathException("cannot convert value of type " + Type.getTypeName(getType()) + " to Java object of type " + target.getName()); } public boolean effectiveBooleanValue() throws XPathException { throw new XPathException("FORG0006: value of type " + Type.getTypeName(getType()) + " has no boolean value."); } }