001: package com.completex.objective.components.persistency.type;
002:
003: import com.completex.objective.components.persistency.ColumnType;
004: import com.completex.objective.components.persistency.xml.XmlRuntimeException;
005: import com.completex.objective.util.XmlDomHelper;
006: import sun.misc.BASE64Encoder;
007: import sun.misc.BASE64Decoder;
008:
009: import java.io.ByteArrayInputStream;
010: import java.io.ByteArrayOutputStream;
011: import java.io.IOException;
012: import java.io.ObjectOutputStream;
013: import java.io.ObjectInputStream;
014: import java.io.InputStream;
015: import java.math.BigDecimal;
016: import java.math.BigInteger;
017: import java.sql.Blob;
018: import java.sql.Clob;
019: import java.sql.Time;
020: import java.sql.Timestamp;
021: import java.util.Date;
022: import java.util.HashMap;
023: import java.util.Map;
024:
025: /**
026: * @author Gennady Krizhevsky
027: */
028: public class ValueStreamHelper {
029:
030: public static final Map NUMERIC = new HashMap();
031: public static final LongFactory LONG_FACTORY = new LongFactory();
032: public static final IntegerFactory INTEGER_FACTORY = new IntegerFactory();
033: public static final ShortFactory SHORT_FACTORY = new ShortFactory();
034: public static final FloatFactory FLOAT_FACTORY = new FloatFactory();
035: public static final DoubleFactory DOUBLE_FACTORY = new DoubleFactory();
036: public static final ByteFactory BYTE_FACTORY = new ByteFactory();
037:
038: static {
039: NUMERIC.put(Long.class.getName(), LONG_FACTORY);
040: NUMERIC.put(Integer.class.getName(), INTEGER_FACTORY);
041: NUMERIC.put(Short.class.getName(), SHORT_FACTORY);
042: NUMERIC.put(Float.class.getName(), FLOAT_FACTORY);
043: NUMERIC.put(Double.class.getName(), DOUBLE_FACTORY);
044: NUMERIC.put(Byte.class.getName(), BYTE_FACTORY);
045: NUMERIC
046: .put(BigDecimal.class.getName(),
047: new BigDecimalFactory());
048: NUMERIC
049: .put(BigInteger.class.getName(),
050: new BigIntegerFactory());
051: //
052: // Primitives:
053: //
054: NUMERIC.put(long.class.getName(), LONG_FACTORY);
055: NUMERIC.put(int.class.getName(), INTEGER_FACTORY);
056: NUMERIC.put(short.class.getName(), SHORT_FACTORY);
057: NUMERIC.put(float.class.getName(), FLOAT_FACTORY);
058: NUMERIC.put(double.class.getName(), DOUBLE_FACTORY);
059: NUMERIC.put(byte.class.getName(), BYTE_FACTORY);
060: }
061:
062: public static final Map DATE = new HashMap();
063:
064: static {
065: DATE.put(Date.class.getName(), new DateFactory());
066: DATE.put(java.sql.Date.class.getName(), new SqlDateFactory());
067: DATE.put(Time.class.getName(), new SqlTimeFactory());
068: DATE.put(Timestamp.class.getName(), new SqlTimestampFactory());
069: }
070:
071: public static final Map BOOLEAN = new HashMap();
072:
073: public static final BooleanFactory BOOLEAN_FACTORY = new BooleanFactory();
074:
075: static {
076: BOOLEAN.put(Boolean.class.getName(), BOOLEAN_FACTORY);
077: //
078: // Primitives:
079: //
080: BOOLEAN.put(boolean.class.getName(), BOOLEAN_FACTORY);
081: }
082:
083: public static final Map VALUE_FACTORIES = new HashMap();
084: public static final ByteArrayInputStream NULL_BYTE_ARRAY_INPUT_STREAM = new ByteArrayInputStream(
085: new byte[0]);
086:
087: static {
088: VALUE_FACTORIES.putAll(NUMERIC);
089: VALUE_FACTORIES.putAll(DATE);
090: VALUE_FACTORIES.putAll(BOOLEAN);
091: }
092:
093: public static ValueStringResult value2string(ColumnType type,
094: Object value) {
095: ValueStringResult result = new ValueStringResult();
096: if (value == null) {
097: return result;
098: }
099: try {
100: if (ColumnType.isBinary(type)) {
101: if (value == ColumnType.NULL_BINARY_OBJECT) {
102: value = null;
103: }
104: BASE64Encoder encoder = new BASE64Encoder();
105: if (value instanceof Blob) {
106: Blob blob = (Blob) value;
107: long len = blob.length();
108: validateIntLen(len);
109: result.setValueString(encoder.encode(blob.getBytes(
110: 1, (int) len)));
111: } else if (value instanceof Clob) {
112: Clob clob = (Clob) value;
113: long len = clob.length();
114: validateIntLen(len);
115: result.setValueString(clob.getSubString(1,
116: (int) len));
117: } else if (value instanceof ByteArrayInputStream) {
118: ByteArrayInputStream bin = (ByteArrayInputStream) value;
119: ByteArrayOutputStream bout = new ByteArrayOutputStream(
120: bin.available());
121: BlobImpl.writeBlob(bin, bout);
122: result.setValueString(encoder.encode(bout
123: .toByteArray()));
124: } else {
125: result = value2string(value);
126: }
127: } else if (ColumnType.isDate(type)) {
128: Date date = (Date) value;
129: result.setValueString(XmlDomHelper.D2S(date));
130: } else if (ColumnType.isBoolean(type)) {
131: Boolean date = (Boolean) value;
132: result.setValueString(XmlDomHelper.B2S(date));
133: } else if (ColumnType.isObject(type)) {
134: result = value2string(value);
135: } else {
136: result.setValueString(String.valueOf(value));
137: }
138: } catch (Exception e) {
139: throw new XmlRuntimeException("Cannot convert value "
140: + "of type [" + type + "] to String", e);
141: }
142: return result;
143: }
144:
145: public static ValueStringResult value2string(Object value)
146: throws IOException {
147: ValueStringResult result = new ValueStringResult();
148: String valueString = null;
149: if (value instanceof String) {
150: valueString = ((String) value);
151: } else if (isNumericValue(value)) {
152: valueString = String.valueOf(value);
153: } else if (isDate(value)) {
154: valueString = XmlDomHelper.D2S(((Date) value));
155: } else if (isBoolean(value)) {
156: valueString = XmlDomHelper.B2S(((Boolean) value));
157: } else if (value != null) {
158: valueString = unknownBinary2string(value);
159: result.setBinary(true);
160: }
161: result.setValueString(valueString);
162: return result;
163: }
164:
165: protected static String unknownBinary2string(Object value)
166: throws IOException {
167: BASE64Encoder encoder = new BASE64Encoder();
168: ByteArrayOutputStream os = new ByteArrayOutputStream();
169: ObjectOutputStream out = new ObjectOutputStream(os);
170: out.writeObject(value);
171: out.flush();
172: out.close();
173: byte[] bytes = os.toByteArray();
174: return encoder.encode(bytes);
175: }
176:
177: protected static boolean isNumericValue(Object value) {
178: if (value == null) {
179: return false;
180: }
181: return isNumericClass(value.getClass().getName());
182: }
183:
184: protected static boolean isNumericClass(String className) {
185: return NUMERIC.containsKey(className);
186: }
187:
188: protected static boolean isDate(Object value) {
189: if (value == null) {
190: return false;
191: }
192: return isDateClass(value);
193: }
194:
195: protected static boolean isDateClass(Object className) {
196: return DATE.containsKey(className);
197: }
198:
199: protected static boolean isBoolean(Object value) {
200: if (value == null) {
201: return false;
202: }
203: return isBooleanClass(value.getClass().getName());
204: }
205:
206: protected static boolean isBooleanClass(String className) {
207: return BOOLEAN.containsKey(className);
208: }
209:
210: protected static void validateIntLen(long len) {
211: if (len > Integer.MAX_VALUE) {
212: throw new XmlRuntimeException("len > Integer.MAX_VALUE");
213: }
214: }
215:
216: /**
217: * Value factory
218: */
219: protected static interface ValueFactory {
220: Object newValueInstance(String valueString);
221: }
222:
223: /**
224: * Numeric:
225: */
226: protected static class LongFactory implements ValueFactory {
227: public Object newValueInstance(String valueString) {
228: return Long.valueOf(valueString);
229: }
230: }
231:
232: protected static class IntegerFactory implements ValueFactory {
233: public Object newValueInstance(String valueString) {
234: return Integer.valueOf(valueString);
235: }
236: }
237:
238: protected static class ShortFactory implements ValueFactory {
239: public Object newValueInstance(String valueString) {
240: return Short.valueOf(valueString);
241: }
242: }
243:
244: protected static class FloatFactory implements ValueFactory {
245: public Object newValueInstance(String valueString) {
246: return Float.valueOf(valueString);
247: }
248: }
249:
250: protected static class DoubleFactory implements ValueFactory {
251: public Object newValueInstance(String valueString) {
252: return Double.valueOf(valueString);
253: }
254: }
255:
256: protected static class ByteFactory implements ValueFactory {
257: public Object newValueInstance(String valueString) {
258: return Byte.valueOf(valueString);
259: }
260: }
261:
262: protected static class BigDecimalFactory implements ValueFactory {
263: public Object newValueInstance(String valueString) {
264: return new BigDecimal(valueString);
265: }
266: }
267:
268: protected static class BigIntegerFactory implements ValueFactory {
269: public Object newValueInstance(String valueString) {
270: return new BigInteger(valueString);
271: }
272: }
273:
274: /**
275: * Date
276: */
277: protected static class DateFactory implements ValueFactory {
278: public Object newValueInstance(String valueString) {
279: return XmlDomHelper.S2D(valueString);
280: }
281: }
282:
283: protected static class SqlDateFactory implements ValueFactory {
284: public Object newValueInstance(String valueString) {
285: Date date = XmlDomHelper.S2D(valueString);
286: return new java.sql.Date(date.getTime());
287: }
288: }
289:
290: protected static class SqlTimeFactory implements ValueFactory {
291: public Object newValueInstance(String valueString) {
292: Date date = XmlDomHelper.S2D(valueString);
293: return new java.sql.Time(date.getTime());
294: }
295: }
296:
297: protected static class SqlTimestampFactory implements ValueFactory {
298: public Object newValueInstance(String valueString) {
299: Date date = XmlDomHelper.S2D(valueString);
300: return new java.sql.Timestamp(date.getTime());
301: }
302: }
303:
304: /**
305: * Boolean
306: */
307: protected static class BooleanFactory implements ValueFactory {
308: public Object newValueInstance(String valueString) {
309: return XmlDomHelper.S2B(valueString);
310: }
311: }
312:
313: //
314: // Back:
315: //
316: public static Object string2value(boolean binary,
317: String valueString, boolean origValue, ColumnType type,
318: String columnName) {
319: Object value = null;
320: try {
321: if (binary) {
322: value = readUnknownBinary(valueString, origValue);
323: } else if (type.isString()) {
324: value = valueString;
325: } else if (type.isBoolean()) {
326: value = XmlDomHelper.S2B(valueString);
327: } else if (type.getValueClass() == Long.class) {
328: value = XmlDomHelper.S2L(valueString);
329: } else if (type.isNumeric()) {
330: value = XmlDomHelper.S2BigDecimal(valueString);
331: } else if (type.isBinary()) {
332: if (Blob.class.isAssignableFrom(type.getValueClass())) {
333: if (!origValue) {
334: BASE64Decoder decoder = new BASE64Decoder();
335: byte[] bytes = decoder
336: .decodeBuffer(valueString);
337: value = new DetachedBlobImpl(bytes);
338: } else {
339: value = DetachedBlobImpl.NULL_BLOB;
340: }
341:
342: } else if (Clob.class.isAssignableFrom(type
343: .getValueClass())) {
344: if (!origValue) {
345: value = new DetachedClobImpl(valueString);
346: } else {
347: value = DetachedClobImpl.NULL_CLOB;
348: }
349: } else if (InputStream.class.isAssignableFrom(type
350: .getValueClass())) {
351: if (!origValue) {
352: BASE64Decoder decoder = new BASE64Decoder();
353: byte[] bytes = decoder
354: .decodeBuffer(valueString);
355: value = new ByteArrayInputStream(bytes);
356: } else {
357: value = NULL_BYTE_ARRAY_INPUT_STREAM;
358: }
359: } else {
360: value = readUnknownBinary(valueString, origValue);
361: }
362: } else if (type.isDate()) {
363: value = XmlDomHelper.S2D(valueString);
364: } else if (type.isBoolean()) {
365: value = XmlDomHelper.S2B(valueString);
366: } else if (type.isObject()) {
367: value = readUnknownBinary(valueString, origValue);
368: } else {
369: System.err
370: .println("ERROR: XmlPersistentObjectInputStream::strings2values: Cannot handle type "
371: + type);
372: }
373: } catch (Exception e) {
374: throw new XmlRuntimeException(
375: "Cannot convert string of type [" + type
376: + "], column [" + columnName + "] to value",
377: e);
378: }
379: return value;
380: }
381:
382: public static Object string2value(String className,
383: String valueString, boolean binary) throws IOException,
384: ClassNotFoundException {
385: Object value = null;
386: if (valueString != null) {
387: if (binary) {
388: value = string2unknownBinary(valueString);
389: } else if (String.class.getName().equals(className)) {
390: value = valueString;
391: } else if (isNumericClass(className)
392: || isDateClass(className)
393: || isBooleanClass(className)) {
394: value = string2value0(className, valueString);
395: } else {
396: value = string2unknownBinary(valueString);
397: }
398: }
399: return value;
400: }
401:
402: protected static Object string2value0(String className,
403: String valueString) {
404: if (valueString == null) {
405: return null;
406: }
407:
408: ValueFactory valueFactory = (ValueFactory) VALUE_FACTORIES
409: .get(className);
410: if (valueFactory == null) {
411: throw new XmlRuntimeException(
412: "Cannot find valueFactory for className "
413: + className);
414: }
415: return valueFactory.newValueInstance(valueString);
416: }
417:
418: protected static Object readUnknownBinary(String valueString,
419: boolean origValue) throws IOException,
420: ClassNotFoundException {
421: Object value;
422: if (!origValue) {
423: value = string2unknownBinary(valueString);
424: } else {
425: value = ColumnType.NULL_BINARY_OBJECT;
426: }
427:
428: return value;
429: }
430:
431: protected static Object string2unknownBinary(String valueString)
432: throws IOException, ClassNotFoundException {
433: BASE64Decoder decoder = new BASE64Decoder();
434: byte[] bytes = decoder.decodeBuffer(valueString);
435: ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
436: ObjectInputStream in = new ObjectInputStream(bin);
437: return in.readObject();
438: }
439:
440: }
|