001: package snow.utils.storage;
002:
003: import java.io.*;
004: import java.util.*;
005:
006: @SuppressWarnings("unchecked")
007: public class VectorUtils {
008:
009: // NEVER CHANGE !
010: public static final int IsVectorContent = 1;
011: public static final int IsIntegerContent = 2;
012: public static final int IsBooleanContent = 3;
013: public static final int IsDoubleContent = 4;
014: public static final int IsStringContent = 5;
015: public static final int IsbyteArrayContent = 10;
016: public static final int IsintArrayContent = 11;
017: public static final int IsfloatArrayContent = 12;
018: public static final int IsdoubleArrayContent = 13;
019: public static final int IsStringArrayContent = 14;
020:
021: public static final int IsLongStringContent = 20;
022: public static final int IsLongContent = 21;
023: public static final int IsCharContent = 30;
024:
025: /**
026: * Writes the vector (consisting of elementary types)
027: * inverse method is streamToVector.
028: * CAUTION: all lists appears in the form of StorageVector ! <pre>(List<Object>)</pre>
029: */
030: @SuppressWarnings("unchecked")
031: public static void vectorToStream(final DataOutputStream out,
032: final List<Object> theVector) throws Exception {
033: vectorToStreamRecurse(out, theVector);
034: }
035:
036: /**
037: * Writes the vector (consisting of elementary types)
038: * inverse method is streamToVector
039: * CAUTION: all Lists are converted to StorageVector !!
040: */
041: @SuppressWarnings("unchecked")
042: private static void vectorToStreamRecurse(
043: final DataOutputStream out, final List<Object> theVector)
044: throws Exception {
045: if (theVector == null) {
046: System.out
047: .println("VectorUtils vectorToStream: null vector received!");
048: out.writeInt(IsVectorContent);
049: // and send its size right after this :
050: //Vector thisVector = new Vector(0);
051: //int thisSize = thisVector.size();
052: out.writeInt(0); //thisSize);
053: } else {
054: out.writeInt(IsVectorContent);
055: // and send its size right after this :
056: int this Size = theVector.size();
057: out.writeInt(this Size);
058:
059: for (int i = 0; i < this Size; i++) {
060: Object this Content = theVector.get(i);
061: if (this Content instanceof Integer) {
062: out.writeInt(IsIntegerContent);
063: out.writeInt((Integer) this Content);
064: } else if (this Content instanceof Double) {
065: out.writeInt(IsDoubleContent);
066: out.writeDouble((Double) this Content);
067: } else if (this Content instanceof Long) {
068: out.writeInt(IsLongContent);
069: out.writeLong((Long) this Content);
070: } else if (this Content instanceof String) {
071: // UTF is limited to 65535 bytes !, we must check
072: //
073: String str = (String) this Content;
074: int len = calculateUTFLength(str);
075: //System.out.println("len="+len);
076: if (len < 65535) {
077: //if(len>10000) System.out.println("Writing a "+len+" String in utf-8");
078: out.writeInt(IsStringContent);
079: out.writeUTF(str);
080: } else {
081: //System.out.println("Writing a "+len+" String in utf-16");
082: out.writeInt(IsLongStringContent);
083: byte[] theArray = str.getBytes("UTF-16");
084: out.writeInt(theArray.length);
085: for (int index = 0; index < theArray.length; index++) {
086: out.writeByte(theArray[index]);
087: }
088: }
089: } else if (this Content instanceof Boolean) {
090: out.writeInt(IsBooleanContent);
091: out.writeBoolean((Boolean) this Content);
092: } else if (this Content instanceof Character) {
093: out.writeInt(IsCharContent);
094: out.writeChar((Character) this Content);
095: } else if (this Content instanceof byte[]) {
096: byte[] theArray = (byte[]) this Content;
097: out.writeInt(IsbyteArrayContent);
098: out.writeInt(theArray.length);
099: for (int index = 0; index < theArray.length; index++) {
100: out.writeByte(theArray[index]); //SLOW !!!
101: }
102: } else if (this Content instanceof int[]) {
103: int[] theArray = (int[]) this Content;
104: out.writeInt(IsintArrayContent);
105: out.writeInt(theArray.length);
106: for (int index = 0; index < theArray.length; index++) {
107: out.writeInt(theArray[index]);
108: }
109: } else if (this Content instanceof double[]) {
110: double[] theArray = (double[]) this Content;
111: out.writeInt(IsdoubleArrayContent);
112: out.writeInt(theArray.length);
113: for (int index = 0; index < theArray.length; index++) {
114: out.writeDouble(theArray[index]);
115: }
116: } else if (this Content instanceof float[]) {
117: float[] theArray = (float[]) this Content;
118: out.writeInt(IsfloatArrayContent);
119: out.writeInt(theArray.length);
120: for (int index = 0; index < theArray.length; index++) {
121: out.writeFloat(theArray[index]);
122: }
123: } else if (this Content instanceof String[]) {
124: String[] theArray = (String[]) this Content;
125: out.writeInt(IsStringArrayContent);
126: out.writeInt(theArray.length);
127: for (int index = 0; index < theArray.length; index++) {
128: out.writeUTF(theArray[index]);
129: }
130: } else if (this Content instanceof List) {
131: // now dive one recursion level deeper and sent its elements :
132: vectorToStream(out, (List) this Content);
133: }
134: /*else if( thisContent instanceof Vector )
135: {
136: // now dive one recursion level deeper and sent its elements :
137: vectorToStream( out , (Vector)thisContent );
138: }*/
139:
140: else if (this Content == null) {
141: // caution : this will be processed, if there are
142: // null values in the frontend database. But this
143: // can give troubles, when the same mechanism is
144: // reversed and tries to write back a String, where
145: // in the database there isnt defined anything.
146: // One has to correct the database in this case.
147: out.writeInt(IsStringContent);
148: out.writeUTF("<null value!>");
149: } else {
150: System.out
151: .println("**vectorToStream error: Only Integer, Double, Character, Boolean, String, byte[], int[], double[], float[] and Vector types supported.");
152: System.out.println("**The data had value :"
153: + this Content.toString());
154: System.out.println("**The data had class : "
155: + this Content.getClass().toString());
156: }
157: } // for
158: }
159: } // vectorToStream
160:
161: /**
162: * Reads the stream, which originates from a vectorToStream process
163: * and rebuilds theVector. theVector has initially to be a vector with zero length.
164: * Inverse method is vectorToStream.
165: * CAUTION: all lists are converted to StorageVector !
166: */
167: @SuppressWarnings("unchecked")
168: public static void streamToVector(final DataInputStream in,
169: final StorageVector theVector) throws Exception {
170: streamToVector(in, theVector, true);
171: }
172:
173: /**
174: * Reads the stream, which originates from a vectorToStream process
175: * and rebuilds theVector. theVector has initially to be a vector with zero length.
176: * This method uses recursion.
177: */
178: @SuppressWarnings("unchecked")
179: private static void streamToVector(final DataInputStream in,
180: final StorageVector theVector, final boolean recursionStart)
181: throws Exception {
182: // Do NOT catch exceptions here. They must be propagated back to the callers,
183: // for giving them a chance to react on error situations.
184:
185: // At the first run, we have to read the string "vector once",
186: // but not in recursion :
187: if (recursionStart) // read the keynumber for "vector" only on the first call
188: {
189: int dummy = in.readInt();
190: }
191: // read the size :
192: int numberOfElements = in.readInt();
193: // System.out.println("Vector contains "+numberOfElements+" elements");
194:
195: for (int elementIndex = 0; elementIndex < numberOfElements; elementIndex++) {
196: final int this ClassIndex = in.readInt(); // the data type keyword string
197: if (this ClassIndex == IsIntegerContent) {
198: int this Value = in.readInt();
199: theVector.add(this Value);
200: } else if (this ClassIndex == IsDoubleContent) {
201: double this Value = in.readDouble();
202: theVector.add(this Value);
203: }
204: /* else if( thisClassIndex == IsFloatContent )
205: {
206: double thisValue = in.readDouble();
207: theVector.addElement( new Double(thisValue) );
208: }*/
209: else if (this ClassIndex == IsLongContent) {
210: long this Value = in.readLong();
211: theVector.add(this Value);
212: } else if (this ClassIndex == IsStringContent) {
213: String this Value = in.readUTF();
214: theVector.add(this Value);
215: } else if (this ClassIndex == IsBooleanContent) {
216: boolean this Value = in.readBoolean();
217: theVector.add(this Value);
218: } else if (this ClassIndex == IsbyteArrayContent) {
219: int arraySize = in.readInt();
220: byte[] this Value = new byte[arraySize];
221: for (int index = 0; index < arraySize; index++) {
222: this Value[index] = in.readByte();
223: }
224: theVector.add(this Value);
225: } else if (this ClassIndex == IsLongStringContent) {
226: int arraySize = in.readInt();
227: //System.out.println("Reading a "+arraySize+" String in utf-16");
228: byte[] this Value = new byte[arraySize];
229: for (int index = 0; index < arraySize; index++) {
230: this Value[index] = in.readByte();
231: }
232: theVector.add(new String(this Value, "UTF-16"));
233: } else if (this ClassIndex == IsintArrayContent) {
234: int arraySize = in.readInt();
235: int[] this Value = new int[arraySize];
236: for (int index = 0; index < arraySize; index++) {
237: this Value[index] = in.readInt();
238: }
239: theVector.add(this Value);
240: } else if (this ClassIndex == IsdoubleArrayContent) {
241: int arraySize = in.readInt();
242: double[] this Value = new double[arraySize];
243: for (int index = 0; index < arraySize; index++) {
244: this Value[index] = in.readDouble();
245: }
246: theVector.add(this Value);
247: } else if (this ClassIndex == IsfloatArrayContent) {
248: int arraySize = in.readInt();
249: float[] this Value = new float[arraySize];
250: for (int index = 0; index < arraySize; index++) {
251: this Value[index] = in.readFloat();
252: }
253: theVector.add(this Value);
254: } else if (this ClassIndex == IsStringArrayContent) {
255: int arraySize = in.readInt();
256: String[] this Value = new String[arraySize];
257: for (int index = 0; index < arraySize; index++) {
258: this Value[index] = in.readUTF();
259: }
260: theVector.add(this Value);
261: } else if (this ClassIndex == IsCharContent) {
262: char this Value = in.readChar();
263: theVector.add(this Value);
264: } else if (this ClassIndex == IsVectorContent) {
265: // generate a new Vector and add it :
266: StorageVector this SubVector = new StorageVector();
267: theVector.add(this SubVector);
268: // dive one recursion level deeper :
269: streamToVector(in, this SubVector, false);
270: } else {
271: System.out
272: .println("streamToVector error: Only Integer, Double Boolean and String types supported.");
273: System.out.println("This class identifier index was : "
274: + this ClassIndex);
275: new Throwable().printStackTrace();
276: return;
277: }
278: } // for
279: } // streamToVector
280:
281: /** An utf string has a 65535 bytes limited length.
282: chars < 127 take one byte, greater chars take 2 or 3 bytes
283: this routine returns the exact bytes that the string will take
284: */
285: public static int calculateUTFLength(String str) {
286: int strlen = str.length();
287: int utflen = 0;
288: char[] charr = new char[strlen];
289: int c, count = 0;
290:
291: str.getChars(0, strlen, charr, 0);
292:
293: for (int i = 0; i < strlen; i++) {
294: c = charr[i];
295: if ((c >= 0x0001) && (c <= 0x007F)) {
296: utflen++;
297: } else if (c > 0x07FF) {
298: utflen += 3;
299: } else {
300: utflen += 2;
301: }
302: }
303: return utflen;
304: }
305:
306: }
|