1 22 23 package org.xquark.schema.datatypes; 24 25 import java.text.ParseException ; 26 27 import org.xquark.schema.SchemaException; 28 import org.xquark.schema.validation.ValidationContextProvider; 29 30 31 class HexBinaryType extends MesureableType { 32 private static final String RCSRevision = "$Revision: 1.5 $"; 33 private static final String RCSName = "$Name: $"; 34 private static byte[] decodeMap = new byte[256]; 35 private static byte[] encodeMap = new byte[16]; 36 37 static { 38 for (int i = 0; i < 256; i++) { 39 decodeMap[i] = -1; 40 } 41 42 for (int i = '0'; i <= '9'; i++) 43 decodeMap[i] = (byte)(i-'0'); 44 for (int i = 'A'; i <= 'F'; i++) 45 decodeMap[i] = (byte)(i-'A'+10); 46 for (int i = 'a'; i <= 'f'; i++) 47 decodeMap[i] = (byte)(i-'a'+10); 48 49 for (int i = 0; i < 10; i++) 50 encodeMap[i] = (byte)('0'+i); 51 for (int i = 10; i < 16; i++) 52 encodeMap[i] = (byte)('A'+i-10); 53 } 54 55 HexBinaryType() { 56 super("hexBinary", PrimitiveType.HEX_BINARY); 57 } 58 59 protected Object toValidType(Object data) { 60 if (data instanceof byte[]) { 61 return new Value((byte[])data); 62 } else { 63 return (ByteArray) data; 64 } 65 } 66 67 public void checkFacets(Object valueSpace) throws SchemaException { 68 super.checkFacets(valueSpace); 69 super.checkLength(((ByteArray) valueSpace).getLength(), valueSpace); 70 } 71 72 protected Object toValueSpace(String value, ValidationContextProvider context) throws SchemaException { 73 try { 74 return new Value(decode(value)); 75 } catch (ParseException ee) { 76 super.invalidValue(value.toString()); 77 return null; 78 } 79 } 80 81 private boolean isHexChar(char c) { 82 return (decodeMap[c] != -1); 83 } 84 85 private int computeSize(String value) throws ParseException { 86 int count = 0; 87 int charLen = value.length(); 88 for (int i = 0; i < charLen; i++) { 89 char c = value.charAt(i); 90 if (!Character.isWhitespace(c)) { 91 if (!isHexChar(c)) { 92 throw new ParseException ("Invalid characted in hexadeciaml encoded string", i); 93 } 94 count++; 95 } 96 } 97 if (count % 2 > 0) 98 throw new ParseException ("Hexadecimal encoded string has invalid length", charLen); 99 return count/2; 100 } 101 102 public byte[] decode(String value) throws ParseException { 103 int decLen = computeSize(value); 104 byte[] decodedData = new byte[decLen]; 105 int charIndex = 0; 106 for (int i = 0; i < decLen; i++) { 107 int tmp = 0; 108 for (int j = 0; j < 2; j++) { 109 char c = value.charAt(charIndex++); 110 while (Character.isWhitespace(c)) 111 c = value.charAt(charIndex++); 112 tmp |= (decodeMap[c] << (4*(1-j))); 113 } 114 decodedData[i] = (byte)(tmp & 0xFF); 115 } 116 return decodedData; 117 } 118 119 public String encode(byte[] data) { 120 int decLen = data.length; 121 int encLen = 2*decLen; 122 encLen += (encLen-1)/76; 124 byte[] encodedData = new byte[encLen]; 125 int nLines = 0; 126 for (int i = 0; i < decLen; i++) { 127 int encIndex = 2*i+nLines; 128 encodedData[encIndex] = encodeMap[(byte)((data[i] >> 4) & 0xF)]; 129 encodedData[encIndex+1] = encodeMap[(byte)(data[i] & 0xF)]; 130 if ((i+1) % 38 == 0 && encIndex + 2 < encLen) { 131 encodedData[encIndex+2] = (byte)0xA; 132 nLines++; 133 } 134 } 135 return new String (encodedData); 136 } 137 138 public String toXMLString(Object data, ValidationContextProvider context) { 139 if (data instanceof ByteArray) { 140 return encode(((ByteArray)data).getData()); 141 } else if (data instanceof byte[]) { 142 return encode((byte[])data); 143 } else { 144 throw new IllegalArgumentException ("Not a byte array"); 145 } 146 } 147 148 class Value extends ByteArray { 149 150 Value(byte[] value) { 151 super(value); 152 } 153 154 protected boolean checkClass(Object obj) { 155 return obj instanceof Value; 156 } 157 158 public String toString() { 159 return encode(getData()); 160 } 161 162 } 163 } 164 | Popular Tags |