1 package net.sf.saxon.value; 2 import net.sf.saxon.expr.XPathContext; 3 import net.sf.saxon.om.FastStringBuffer; 4 import net.sf.saxon.trans.DynamicError; 5 import net.sf.saxon.trans.XPathException; 6 import net.sf.saxon.type.BuiltInAtomicType; 7 import net.sf.saxon.type.ItemType; 8 import net.sf.saxon.type.Type; 9 import net.sf.saxon.type.ValidationException; 10 import net.sf.saxon.ConversionContext; 11 12 15 16 public class HexBinaryValue extends AtomicValue { 17 18 private byte[] binaryValue; 19 20 21 25 26 public HexBinaryValue(CharSequence s) throws XPathException { 27 if ((s.length() & 1) != 0) { 28 DynamicError err = new DynamicError( 29 "A hexBinary value must contain an even number of characters"); 30 err.setErrorCode("FORG0001"); 31 throw err; 32 } 33 binaryValue = new byte[s.length() / 2]; 34 for (int i=0; i<binaryValue.length; i++) { 35 binaryValue[i] = (byte)((fromHex(s.charAt(2*i))<<4) + 36 (fromHex(s.charAt(2*i+1)))); 37 } 38 } 39 40 43 44 public HexBinaryValue(byte[] value) { 45 this.binaryValue = value; 46 } 47 48 51 52 public byte[] getBinaryValue() { 53 return binaryValue; 54 } 55 56 62 63 private int fromHex(char c) throws XPathException { 64 int d = "0123456789ABCDEFabcdef".indexOf(c); 65 if (d > 15) { 66 d = d - 6; 67 } 68 if (d < 0) { 69 DynamicError err = new DynamicError("Invalid hexadecimal digit"); 70 err.setErrorCode("FORG0001"); 71 throw err; 72 } 73 return d; 74 } 75 76 82 83 public AtomicValue convertPrimitive(BuiltInAtomicType requiredType, boolean validate, ConversionContext conversion) { 84 switch(requiredType.getPrimitiveType()) { 85 case Type.HEX_BINARY: 86 case Type.ATOMIC: 87 case Type.ITEM: 88 return this; 89 case Type.STRING: 90 return new StringValue(getStringValueCS()); 91 case Type.UNTYPED_ATOMIC: 92 return new UntypedAtomicValue(getStringValueCS()); 93 case Type.BASE64_BINARY: 94 return new Base64BinaryValue(binaryValue); 95 96 default: 97 ValidationException err = new ValidationException("Cannot convert hexBinarry to " + 98 requiredType.getDisplayName()); 99 err.setErrorCode("FORG0001"); 101 return new ValidationErrorValue(err); 102 } 103 } 104 105 109 110 public String getStringValue() { 111 String digits = "0123456789ABCDEF"; 112 FastStringBuffer sb = new FastStringBuffer(binaryValue.length * 2); 113 for (int i=0; i<binaryValue.length; i++) { 114 sb.append(digits.charAt((binaryValue[i]>>4)&0xf)); 115 sb.append(digits.charAt(binaryValue[i]&0xf)); 116 } 117 return sb.toString(); 118 } 119 120 121 125 126 public ItemType getItemType() { 127 return Type.HEX_BINARY_TYPE; 128 } 129 130 133 134 public int getLengthInOctets() { 135 return binaryValue.length; 136 } 137 138 141 142 public Object convertToJava(Class target, XPathContext context) throws XPathException { 143 144 if (target.isAssignableFrom(HexBinaryValue.class)) { 145 return this; 146 } else if (target.isAssignableFrom(String .class)) { 147 return getStringValue(); 148 } else { 149 Object o = super.convertToJava(target, context); 150 if (o == null) { 151 throw new DynamicError("Conversion of hexBinary to " + target.getName() + 152 " is not supported"); 153 } 154 return o; 155 } 156 } 157 158 159 162 163 public boolean equals(Object other) { 164 HexBinaryValue v2; 165 if (other instanceof HexBinaryValue) { 166 v2 = (HexBinaryValue)other; 167 } else if (other instanceof AtomicValue) { 168 try { 169 v2 = (HexBinaryValue)((AtomicValue)other).convert(Type.HEX_BINARY, null); 170 } catch (XPathException err) { 171 return false; 172 } 173 } else { 174 return false; 175 } 176 if (binaryValue.length != v2.binaryValue.length) { 177 return false; 178 }; 179 for (int i = 0; i < binaryValue.length; i++) { 180 if (binaryValue[i] != v2.binaryValue[i]) { 181 return false; 182 }; 183 } 184 return true; 185 } 186 187 public int hashCode() { 188 return Base64BinaryValue.byteArrayHashCode(binaryValue); 189 } 190 191 } 192 193 211 | Popular Tags |