50965ba3b0aed78c29eee897fdc601c9b5b5ddf9
[iot2.git] / iotjava / iotrmi / Java / IoTRMIUtil.java
1 package iotrmi.Java;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.ObjectInputStream;
7 import java.io.ObjectOutputStream;
8 import java.nio.ByteBuffer;
9 import java.util.Arrays;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import iotrmi.IoTRMITypes;
20
21 /** Class IoTRMI provides utility services.
22  *  <p>
23  *  It provides miscellaneous (data type/value) translations.
24  *
25  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
26  * @version     1.0
27  * @since       2016-10-04
28  */
29 public class IoTRMIUtil {
30
31         /**
32          * Class Properties
33          */
34         private Map<String,String> mapPrimitives;
35         private Map<String,Integer> mapPrimitiveSizesJava;
36         private Map<String,Integer> mapPrimitiveSizesCplus;
37         private Map<String,String> mapNonPrimitives;
38
39         /**
40          * Class Constants
41          */
42         public final static int METHOD_ID_LEN = 4;      // 4 bytes = 32 bits
43         public final static int PARAM_LEN = 4;          // 4 bytes = 32 bits (4-byte field that stores the length of the param)
44
45         public final static int SHT_LEN = 2;
46         public final static int INT_LEN = 4;
47         public final static int LNG_LEN = 8;
48         public final static int FLT_LEN = 4;
49         public final static int DBL_LEN = 8;
50         public final static int CHR_LEN = 2;
51         public final static int BYT_LEN = 1;
52         public final static int BOL_LEN = 1;
53
54         /**
55          * Constructors
56          */
57         public IoTRMIUtil() {
58
59                 mapPrimitives = new HashMap<String,String>();
60                         IoTRMITypes.arraysToMap(mapPrimitives, 
61                                 IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
62                 mapPrimitiveSizesJava = new HashMap<String,Integer>();
63                         IoTRMITypes.arraysToMap(mapPrimitiveSizesJava, 
64                                 IoTRMITypes.primitivesJava, IoTRMITypes.primitivesJavaSizes);
65                 mapPrimitiveSizesCplus = new HashMap<String,Integer>();
66                         IoTRMITypes.arraysToMap(mapPrimitiveSizesCplus, 
67                                 IoTRMITypes.primitivesCplus, IoTRMITypes.primitivesCplusSizes);
68                 mapNonPrimitives = new HashMap<String,String>();
69                         IoTRMITypes.arraysToMap(mapNonPrimitives, 
70                                 IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
71         }
72
73
74         /**
75          * getHashCodeBytes() gets hash value (in bytes) from method name
76          */
77         public static byte[] getHashCodeBytes(String string) {
78
79                 int hash = string.hashCode();
80                 byte[] hashBytes = ByteBuffer.allocate(4).putInt(hash).array();
81                 return hashBytes;
82         }
83
84
85         /**================
86          * Helper methods
87          **================
88          */
89         /**
90          * translateType() try to translate a type
91          * <p>
92          * It returns the original type when fails.
93          */
94         public String translateType(String type) {
95
96                 if (mapPrimitives.containsKey(type))
97                         return mapPrimitives.get(type);
98                 else if (mapNonPrimitives.containsKey(type))
99                         return mapNonPrimitives.get(type);
100                 else
101                         return type;
102         }
103
104
105         /**
106          * getTypeSize() gets the size of a type
107          *
108          */
109         public int getTypeSize(String type) {
110
111                 if (mapPrimitiveSizesJava.containsKey(type))
112                         return mapPrimitiveSizesJava.get(type);
113                 else if (mapPrimitiveSizesCplus.containsKey(type))
114                         return mapPrimitiveSizesCplus.get(type);
115                 else
116                         return -1; // Size is unknown
117         }
118         
119
120         /**
121          * getTypeSize() gets the size of a type
122          *
123          */
124         public static int getTypeSize(Class<?> type) {
125
126                 int size = 0;
127                 if (type == byte.class) {
128                         size = BYT_LEN;
129                 } else if (type == Byte.class) {
130                         size = BYT_LEN;
131                 } else if (type == short.class) {
132                         size = SHT_LEN;
133                 } else if (type == Short.class) {
134                         size = SHT_LEN;
135                 } else if (     type == int.class) {
136                         size = INT_LEN;
137                 } else if (     type == Integer.class) {
138                         size = INT_LEN;
139                 } else if (     type == long.class) {
140                         size = LNG_LEN;
141                 } else if (     type == Long.class) {
142                         size = LNG_LEN;
143                 } else if (     type == float.class) {
144                         size = FLT_LEN;
145                 } else if (     type == Float.class) {
146                         size = FLT_LEN;
147                 } else if (     type == double.class) {
148                         size = DBL_LEN;
149                 } else if ( type == Double.class) {
150                         size = DBL_LEN;
151                 } else if (     type == boolean.class) {
152                         size = BOL_LEN;
153                 } else if (     type == Boolean.class) {
154                         size = BOL_LEN;
155                 } else if (     type == char.class) {
156                         size = CHR_LEN;
157                 } else if (     type == Character[].class) {
158                         size = CHR_LEN;
159                 } else if (type == String[].class) {
160                         size = -1;
161                 } else
162                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
163
164                 return size;
165         }
166
167         
168         /**
169          * getParamObject() converts byte array of certain object type into Object
170          */
171         public static Object getParamObject(Class<?> type, Class<?> genTypeKey, Class<?> genTypeVal, byte[] paramBytes) {
172                 
173                 Object retObj = null;
174                 if (type == byte.class ||
175                         type == Byte.class) {
176                         retObj = (Object) paramBytes[0];
177                 } else if (     type == short.class ||
178                                         type == Short.class) {
179                         retObj = (Object) byteArrayToShort(paramBytes);
180                 } else if (     type == int.class ||
181                                         type == Integer.class) {
182                         retObj = (Object) byteArrayToInt(paramBytes);
183                 } else if (     type == long.class ||
184                                         type == Long.class) {
185                         retObj = (Object) byteArrayToLong(paramBytes);
186                 } else if (     type == float.class ||
187                                         type == Float.class) {
188                         retObj = (Object) byteArrayToFloat(paramBytes);
189                 } else if (     type == double.class ||
190                                         type == Double.class) {
191                         retObj = (Object) byteArrayToDouble(paramBytes);
192                 } else if (     type == boolean.class ||
193                                         type == Boolean.class) {
194                         retObj = (Object) byteArrayToBoolean(paramBytes);
195                 } else if (     type == char.class ||
196                                         type == Character.class) {
197                         retObj = (Object) byteArrayToChar(paramBytes);
198                 } else if (type == String.class) {
199                         retObj = (Object) byteArrayToString(paramBytes);
200                 // Array
201                 } else if (type.isArray()) {
202                         retObj = getParamObjectArray(type, paramBytes);
203                 // Set
204                 // e.g. Set<String> - type = Set.class, genTypeVal = String.class
205                 } else if (type == Set.class) {
206                         retObj = getParamSetObject(genTypeVal, paramBytes);
207                 // List
208                 } else if (type == List.class) {
209                         retObj = getParamListObject(genTypeVal, paramBytes);
210                 // Map
211                 // e.g. Map<String,Integer> - type = Map.class, genTypeKey = String.class, genTypeVal = Integer.class
212                 } else if (type == Map.class) {
213                         retObj = getParamMapObject(genTypeKey, genTypeVal, paramBytes);
214                 } else
215                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
216                 
217                 return retObj;
218         }
219
220
221         /**
222          * getParamObjectArray() converts byte array of certain object type into array of Objects
223          */
224         public static Object getParamObjectArray(Class<?> type, byte[] paramBytes) {
225                 
226                 Object retObj = null;
227                 if ((type == byte[].class)      ||
228                         (type == byte.class)) {
229                         retObj = (Object) paramBytes;
230                 } else if ( (type == Byte[].class) ||
231                                         (type == Byte.class)) {
232                         retObj = (Object) byteArrayToByteArray(paramBytes);
233                 } else if ( (type == short[].class) ||
234                                         (type == short.class)) {
235                         retObj = (Object) byteArrayToShtArray(paramBytes);
236                 } else if ( (type == Short[].class) ||
237                                         (type == Short.class)) {
238                         retObj = (Object) byteArrayToShortArray(paramBytes);
239                 } else if (     (type == int[].class) ||
240                                         (type == int.class)) {
241                         retObj = (Object) byteArrayToIntArray(paramBytes);
242                 } else if (     (type == Integer[].class) ||
243                                         (type == Integer.class)) {
244                         retObj = (Object) byteArrayToIntegerArray(paramBytes);
245                 } else if (     (type == long[].class) ||
246                                         (type == long.class)) {
247                         retObj = (Object) byteArrayToLngArray(paramBytes);
248                 } else if (     (type == Long[].class) ||
249                                         (type == Long.class)) {
250                         retObj = (Object) byteArrayToLongArray(paramBytes);
251                 } else if (     (type == float[].class) ||
252                                         (type == float.class)) {
253                         retObj = (Object) byteArrayToFltArray(paramBytes);
254                 } else if (     (type == Float[].class) ||
255                                         (type == Float.class)) {
256                         retObj = (Object) byteArrayToFloatArray(paramBytes);
257                 } else if (     (type == double[].class) ||
258                                         (type == double.class)) {
259                         retObj = (Object) byteArrayToDblArray(paramBytes);
260                 } else if ( (type == Double[].class) ||
261                                         (type == Double.class)) {
262                         retObj = (Object) byteArrayToDoubleArray(paramBytes);
263                 } else if (     (type == boolean[].class) || 
264                                         (type == boolean.class)) {
265                         retObj = (Object) byteArrayToBolArray(paramBytes);
266                 } else if (     (type == Boolean[].class) ||
267                                         (type == Boolean.class)) {
268                         retObj = (Object) byteArrayToBooleanArray(paramBytes);
269                 } else if (     (type == char[].class) ||
270                                         (type == char.class)) {
271                         retObj = (Object) byteArrayToChrArray(paramBytes);
272                 } else if (     (type == Character[].class) ||
273                                         (type == Character.class)) {
274                         retObj = (Object) byteArrayToCharacterArray(paramBytes);
275                 } else if ( (type == String[].class) ||
276                                         (type == String.class)) {
277                         retObj = (Object) byteArrayToStringArray(paramBytes);
278                 } else
279                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
280                 
281                 return retObj;
282         }
283
284
285         /**
286          * getObjectBytes() converts an object into byte array
287          */
288         public static byte[] getObjectBytes(Object obj) {
289                 
290                 byte[] retObjBytes = null;
291                 if (obj instanceof Byte) {
292                         retObjBytes = (byte[]) obj;
293                 } else if (obj instanceof Short) {
294                         retObjBytes = shortToByteArray((short) obj);
295                 } else if (obj instanceof Integer) {
296                         retObjBytes = intToByteArray((int) obj);
297                 } else if (obj instanceof Long) {
298                         retObjBytes = longToByteArray((long) obj);
299                 } else if (obj instanceof Float) {
300                         retObjBytes = floatToByteArray((float) obj);
301                 } else if (obj instanceof Double) {
302                         retObjBytes = doubleToByteArray((double) obj);
303                 } else if (obj instanceof Character) {
304                         retObjBytes = charToByteArray((char) obj);
305                 } else if (obj instanceof Boolean) {
306                         retObjBytes = booleanToByteArray((boolean) obj);
307                 } else if (obj instanceof String) {
308                         retObjBytes = stringToByteArray((String) obj);
309                 // Arrays
310                 } else if (obj.getClass().isArray()) {
311                         retObjBytes = getArrayObjectBytes(obj);
312                 // Set and its implementations
313                 } else if (obj instanceof Set<?>) {
314                         retObjBytes = setToByteArray((Set<?>) obj);
315                 // List and its implementations
316                 } else if (obj instanceof List<?>) {
317                         retObjBytes = listToByteArray((List<?>) obj);
318                 // Map and its implementations
319                 } else if (obj instanceof Map<?,?>) {
320                         retObjBytes = mapToByteArray((Map<?,?>) obj);
321                 } else
322                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
323
324                 return retObjBytes;
325         }
326
327
328         /**
329          * getArrayObjectBytes() converts array of objects into bytes array
330          */
331         public static byte[] getArrayObjectBytes(Object obj) {
332
333                 byte[] retObjBytes = null;
334                 if (obj instanceof byte[]) {
335                         retObjBytes = (byte[]) obj;
336                 } else if (obj instanceof Byte[]) {
337                         retObjBytes = arrByteToByteArray((Byte[]) obj);
338                 } else if (obj instanceof short[]) {
339                         retObjBytes = arrShortToByteArray((short[]) obj);
340                 } else if (obj instanceof Short[]) {
341                         retObjBytes = arrShortToByteArray((Short[]) obj);
342                 } else if (obj instanceof int[]) {
343                         retObjBytes = arrIntToByteArray((int[]) obj);
344                 } else if (obj instanceof Integer[]) {
345                         retObjBytes = arrIntToByteArray((Integer[]) obj);
346                 } else if (obj instanceof long[]) {
347                         retObjBytes = arrLongToByteArray((long[]) obj);
348                 } else if (obj instanceof Long[]) {
349                         retObjBytes = arrLongToByteArray((Long[]) obj);
350                 } else if (obj instanceof float[]) {
351                         retObjBytes = arrFloatToByteArray((float[]) obj);
352                 } else if (obj instanceof Float[]) {
353                         retObjBytes = arrFloatToByteArray((Float[]) obj);
354                 } else if (obj instanceof double[]) {
355                         retObjBytes = arrDoubleToByteArray((double[]) obj);
356                 } else if (obj instanceof Double[]) {
357                         retObjBytes = arrDoubleToByteArray((Double[]) obj);
358                 } else if (obj instanceof char[]) {
359                         retObjBytes = arrCharToByteArray((char[]) obj);
360                 } else if (obj instanceof Character[]) {
361                         retObjBytes = arrCharToByteArray((Character[]) obj);
362                 } else if (obj instanceof boolean[]) {
363                         retObjBytes = arrBooleanToByteArray((boolean[]) obj);
364                 } else if (obj instanceof Boolean[]) {
365                         retObjBytes = arrBooleanToByteArray((Boolean[]) obj);
366                 } else if (obj instanceof String[]) {
367                         retObjBytes = arrStringToByteArray((String[]) obj);
368                 } else
369                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
370
371                 return retObjBytes;     
372         }
373
374
375         // Collection data structures
376         public static byte[] setToByteArray(Set<?> set) {
377
378                 // Find out the class of the type
379                 Iterator<?> it = set.iterator();
380                 Object[] arrObj = null;
381                 Object obj = it.next();
382
383                 if (obj instanceof Byte) {
384                         arrObj = set.toArray(new Byte[set.size()]);
385                 } else if (obj instanceof Short) {
386                         arrObj = set.toArray(new Short[set.size()]);
387                 } else if (obj instanceof Integer) {
388                         arrObj = set.toArray(new Integer[set.size()]);
389                 } else if (obj instanceof Long) {
390                         arrObj = set.toArray(new Long[set.size()]);
391                 } else if (obj instanceof Float) {
392                         arrObj = set.toArray(new Float[set.size()]);
393                 } else if (obj instanceof Double) {
394                         arrObj = set.toArray(new Double[set.size()]);
395                 } else if (obj instanceof Character) {
396                         arrObj = set.toArray(new Character[set.size()]);
397                 } else if (obj instanceof Boolean) {
398                         arrObj = set.toArray(new Boolean[set.size()]);
399                 } else if (obj instanceof String) {
400                         arrObj = set.toArray(new String[set.size()]);
401                 } else
402                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
403
404                 byte[] arrObjBytes = getArrayObjectBytes(arrObj);
405                 return arrObjBytes;
406         }
407
408
409         public static byte[] listToByteArray(List<?> list) {
410
411                 // Find out the class of the type
412                 Iterator<?> it = list.iterator();
413                 Object[] arrObj = null;
414                 Object obj = it.next();
415
416                 if (obj instanceof Byte) {
417                         arrObj = list.toArray(new Byte[list.size()]);
418                 } else if (obj instanceof Short) {
419                         arrObj = list.toArray(new Short[list.size()]);
420                 } else if (obj instanceof Integer) {
421                         arrObj = list.toArray(new Integer[list.size()]);
422                 } else if (obj instanceof Long) {
423                         arrObj = list.toArray(new Long[list.size()]);
424                 } else if (obj instanceof Float) {
425                         arrObj = list.toArray(new Float[list.size()]);
426                 } else if (obj instanceof Double) {
427                         arrObj = list.toArray(new Double[list.size()]);
428                 } else if (obj instanceof Character) {
429                         arrObj = list.toArray(new Character[list.size()]);
430                 } else if (obj instanceof Boolean) {
431                         arrObj = list.toArray(new Boolean[list.size()]);
432                 } else if (obj instanceof String) {
433                         arrObj = list.toArray(new String[list.size()]);
434                 } else
435                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
436
437                 byte[] arrObjBytes = getArrayObjectBytes(arrObj);
438                 return arrObjBytes;
439         }
440
441
442         // Convert keySet of a Map
443         public static byte[] mapKeyToByteArray(Map<?,?> map) {
444
445                 // Map<K,V>
446                 // Find out the class of the type for K
447                 Iterator<?> it = map.keySet().iterator();
448                 Object[] arrObj = null;
449                 Object obj = it.next();
450
451                 if (obj instanceof Byte) {
452                         arrObj = map.keySet().toArray(new Byte[map.size()]);
453                 } else if (obj instanceof Short) {
454                         arrObj = map.keySet().toArray(new Short[map.size()]);
455                 } else if (obj instanceof Integer) {
456                         arrObj = map.keySet().toArray(new Integer[map.size()]);
457                 } else if (obj instanceof Long) {
458                         arrObj = map.keySet().toArray(new Long[map.size()]);
459                 } else if (obj instanceof Float) {
460                         arrObj = map.keySet().toArray(new Float[map.size()]);
461                 } else if (obj instanceof Double) {
462                         arrObj = map.keySet().toArray(new Double[map.size()]);
463                 } else if (obj instanceof Character) {
464                         arrObj = map.keySet().toArray(new Character[map.size()]);
465                 } else if (obj instanceof Boolean) {
466                         arrObj = map.keySet().toArray(new Boolean[map.size()]);
467                 } else if (obj instanceof String) {
468                         arrObj = map.keySet().toArray(new String[map.size()]);
469                 } else
470                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
471                 byte[] arrObjBytes = getArrayObjectBytes(arrObj);
472
473                 return arrObjBytes;
474         }
475
476
477         // Convert entrySet of a Map
478         public static byte[] mapEntryToByteArray(Map<?,?> map) {
479
480                 // Map<K,V>
481                 // Find out the class of the type for V
482                 Iterator<?> it = map.values().iterator();
483                 Object[] arrObj = null;
484                 Object obj = it.next();
485
486                 if (obj instanceof Byte) {
487                         arrObj = map.values().toArray(new Byte[map.size()]);
488                 } else if (obj instanceof Short) {
489                         arrObj = map.values().toArray(new Short[map.size()]);
490                 } else if (obj instanceof Integer) {
491                         arrObj = map.values().toArray(new Integer[map.size()]);
492                 } else if (obj instanceof Long) {
493                         arrObj = map.values().toArray(new Long[map.size()]);
494                 } else if (obj instanceof Float) {
495                         arrObj = map.values().toArray(new Float[map.size()]);
496                 } else if (obj instanceof Double) {
497                         arrObj = map.values().toArray(new Double[map.size()]);
498                 } else if (obj instanceof Character) {
499                         arrObj = map.values().toArray(new Character[map.size()]);
500                 } else if (obj instanceof Boolean) {
501                         arrObj = map.values().toArray(new Boolean[map.size()]);
502                 } else if (obj instanceof String) {
503                         arrObj = map.values().toArray(new String[map.size()]);
504                 } else
505                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
506
507                 byte[] arrObjBytes = getArrayObjectBytes(arrObj);
508                 return arrObjBytes;
509         }
510
511
512         // Merge keySet and entrySet of a Map into one long byte array
513         public static byte[] mapToByteArray(Map<?,?> map) {
514
515                 // Put map size in the packet
516                 byte[] numEntries = intToByteArray(map.size());
517                 byte[] keySetBytes = mapKeyToByteArray(map);
518                 byte[] entrySetBytes = mapEntryToByteArray(map);
519                 byte[] mapBytes = new byte[INT_LEN + keySetBytes.length + entrySetBytes.length];
520                 // Copy the bytes
521                 System.arraycopy(numEntries, 0, mapBytes, 0, INT_LEN);
522                 System.arraycopy(keySetBytes, 0, mapBytes, INT_LEN, keySetBytes.length);
523                 System.arraycopy(entrySetBytes, 0, mapBytes, (INT_LEN + keySetBytes.length), entrySetBytes.length);
524
525                 return mapBytes;
526         }
527
528
529         // Get a Set object from bytes
530         public static Object getParamSetObject(Class<?> genericType, byte[] paramBytes) {
531
532                 Set<Object> retSet = new HashSet<Object>();
533                 Object retObj = null;
534                 if (genericType == Byte.class) {
535                         Byte[] retArr = byteArrayToByteArray(paramBytes);
536                         Collections.addAll(retSet, retArr);
537                 } else if (genericType == Short.class) {
538                         Short[] retArr = byteArrayToShortArray(paramBytes);
539                         Collections.addAll(retSet, retArr);
540                 } else if (genericType == Integer.class) {
541                         Integer[] retArr = byteArrayToIntegerArray(paramBytes);
542                         Collections.addAll(retSet, retArr);
543                 } else if (genericType == Long.class) {
544                         Long[] retArr = byteArrayToLongArray(paramBytes);
545                         Collections.addAll(retSet, retArr);
546                 } else if (genericType == Float.class) {
547                         Float[] retArr = byteArrayToFloatArray(paramBytes);
548                         Collections.addAll(retSet, retArr);
549                 } else if (genericType == Double.class) {
550                         Double[] retArr = byteArrayToDoubleArray(paramBytes);
551                         Collections.addAll(retSet, retArr);
552                 } else if (genericType == Boolean.class) {
553                         Boolean[] retArr = byteArrayToBooleanArray(paramBytes);
554                         Collections.addAll(retSet, retArr);
555                 } else if (genericType == Character.class) {
556                         Character[] retArr = byteArrayToCharacterArray(paramBytes);
557                         Collections.addAll(retSet, retArr);
558                 } else if (genericType == String.class) {
559                         String[] retArr = byteArrayToStringArray(paramBytes);
560                         Collections.addAll(retSet, retArr);
561                 } else
562                         throw new Error("IoTRMIUtil: Unrecognizable object: " + genericType.getSimpleName());
563
564                 return retSet;
565         }
566
567
568         // Get a List object from bytes
569         public static Object getParamListObject(Class<?> genericType, byte[] paramBytes) {
570
571                 List<Object> retList = new ArrayList<Object>();
572                 Object retObj = null;
573                 if (genericType == Byte.class) {
574                         Byte[] retArr = byteArrayToByteArray(paramBytes);
575                         Collections.addAll(retList, retArr);
576                 } else if (genericType == Short.class) {
577                         Short[] retArr = byteArrayToShortArray(paramBytes);
578                         Collections.addAll(retList, retArr);
579                 } else if (genericType == Integer.class) {
580                         Integer[] retArr = byteArrayToIntegerArray(paramBytes);
581                         Collections.addAll(retList, retArr);
582                 } else if (genericType == Long.class) {
583                         Long[] retArr = byteArrayToLongArray(paramBytes);
584                         Collections.addAll(retList, retArr);
585                 } else if (genericType == Float.class) {
586                         Float[] retArr = byteArrayToFloatArray(paramBytes);
587                         Collections.addAll(retList, retArr);
588                 } else if (genericType == Double.class) {
589                         Double[] retArr = byteArrayToDoubleArray(paramBytes);
590                         Collections.addAll(retList, retArr);
591                 } else if (genericType == Boolean.class) {
592                         Boolean[] retArr = byteArrayToBooleanArray(paramBytes);
593                         Collections.addAll(retList, retArr);
594                 } else if (genericType == Character.class) {
595                         Character[] retArr = byteArrayToCharacterArray(paramBytes);
596                         Collections.addAll(retList, retArr);
597                 } else if (genericType == String.class) {
598                         String[] retArr = byteArrayToStringArray(paramBytes);
599                         Collections.addAll(retList, retArr);
600                 } else
601                         throw new Error("IoTRMIUtil: Unrecognizable object: " + genericType.getSimpleName());
602
603                 return retList;
604         }
605
606
607         // Get a Key array for Map object from bytes
608         public static Object getParamMapObject(Class<?> genTypeKey, Class<?> genTypeVal, byte[] paramBytes) {
609
610                 // The complete set of bytes always consists of all keys followed by all values - <K,V> pairs
611                 // Calculate number of elements
612                 byte[] numElBytes = new byte[INT_LEN];
613                 System.arraycopy(paramBytes, 0, numElBytes, 0, INT_LEN);
614                 int numEl = byteArrayToInt(numElBytes);
615                 int keyLen = numEl * getTypeSize(genTypeKey);
616                 int valLen = numEl * getTypeSize(genTypeVal);
617                 byte[] prmKeyBytes = new byte[keyLen];
618                 byte[] prmValBytes = new byte[valLen];
619                 // Copy bytes
620                 System.arraycopy(paramBytes, INT_LEN, prmKeyBytes, 0, keyLen);
621                 System.arraycopy(paramBytes, (INT_LEN + keyLen), prmValBytes, 0, valLen);
622                 // Get array of keys
623                 Object[] retObjKey = (Object[]) getParamObjectArray(genTypeKey, prmKeyBytes);
624                 Object[] retObjVal = (Object[]) getParamObjectArray(genTypeVal, prmValBytes);
625                 // Put everything back to a Map
626                 Map<Object,Object> retMap = new HashMap<Object,Object>();
627                 IoTRMITypes.arraysToMap(retMap, retObjKey, retObjVal);
628
629                 return retMap;
630         }
631
632
633         /**
634          * Converters to byte array
635          */
636         // Single variables     
637         public static byte[] shortToByteArray(short s) {
638
639                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN);
640                 bb.putShort(s);
641
642                 return bb.array();
643         }
644
645
646         public static byte[] intToByteArray(int i) {
647
648                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN);
649                 bb.putInt(i);
650
651                 return bb.array();
652         }
653
654
655         public static byte[] longToByteArray(long l) {
656
657                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN);
658                 bb.putLong(l);
659
660                 return bb.array();
661         }
662
663
664         public static byte[] floatToByteArray(float f) {
665
666                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN);
667                 bb.putFloat(f);
668
669                 return bb.array();
670         }
671
672
673         public static byte[] doubleToByteArray(double d) {
674
675                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN);
676                 bb.putDouble(d);
677
678                 return bb.array();
679         }
680
681
682         public static byte[] charToByteArray(char c) {
683
684                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN);
685                 bb.putChar(c);
686
687                 return bb.array();
688         }
689
690
691         public static byte[] booleanToByteArray(boolean b) {
692
693                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN);
694                 if (b)
695                         bb.put((byte)1);
696                 else
697                         bb.put((byte)0);
698
699                 return bb.array();
700         }
701
702
703         public static byte[] stringToByteArray(String str) {
704
705                 return str.getBytes();
706         }
707
708
709         // Arrays
710         public static byte[] arrByteToByteArray(Byte[] arrByte) {
711
712                 byte[] arrByt = new byte[arrByte.length];
713                 for(int i = 0; i < arrByte.length; i++) {
714                         arrByt[i] = arrByte[i];
715                 }
716
717                 return arrByt;
718         }
719
720
721         public static byte[] arrShortToByteArray(short[] arrShort) {
722
723                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
724                 for(short s : arrShort) {
725                         bb.putShort(s);
726                 }
727
728                 return bb.array();
729         }
730
731
732         public static byte[] arrShortToByteArray(Short[] arrShort) {
733
734                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
735                 for(Short s : arrShort) {
736                         bb.putShort(s);
737                 }
738
739                 return bb.array();
740         }
741
742
743         public static byte[] arrIntToByteArray(int[] arrInt) {
744
745                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
746                 for(int i : arrInt) {
747                         bb.putInt(i);
748                 }
749
750                 return bb.array();
751         }
752
753
754         public static byte[] arrIntToByteArray(Integer[] arrInt) {
755
756                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
757                 for(Integer i : arrInt) {
758                         bb.putInt(i);
759                 }
760
761                 return bb.array();
762         }
763
764
765         public static byte[] arrLongToByteArray(long[] arrLong) {
766
767                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
768                 for(long l : arrLong) {
769                         bb.putLong(l);
770                 }
771
772                 return bb.array();
773         }
774
775
776         public static byte[] arrLongToByteArray(Long[] arrLong) {
777
778                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
779                 for(Long l : arrLong) {
780                         bb.putLong(l);
781                 }
782
783                 return bb.array();
784         }
785
786
787         public static byte[] arrFloatToByteArray(float[] arrFloat) {
788
789                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
790                 for(float f : arrFloat) {
791                         bb.putFloat(f);
792                 }
793
794                 return bb.array();
795         }
796
797
798         public static byte[] arrFloatToByteArray(Float[] arrFloat) {
799
800                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
801                 for(Float f : arrFloat) {
802                         bb.putFloat(f);
803                 }
804
805                 return bb.array();
806         }
807
808
809         public static byte[] arrDoubleToByteArray(double[] arrDouble) {
810
811                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
812                 for(double d : arrDouble) {
813                         bb.putDouble(d);
814                 }
815
816                 return bb.array();
817         }
818
819
820         public static byte[] arrDoubleToByteArray(Double[] arrDouble) {
821
822                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
823                 for(Double d : arrDouble) {
824                         bb.putDouble(d);
825                 }
826
827                 return bb.array();
828         }
829
830
831         public static byte[] arrCharToByteArray(char[] arrChar) {
832
833                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
834                 for(char c : arrChar) {
835                         bb.putChar(c);
836                 }
837
838                 return bb.array();
839         }
840
841
842         public static byte[] arrCharToByteArray(Character[] arrChar) {
843
844                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
845                 for(Character c : arrChar) {
846                         bb.putChar(c);
847                 }
848
849                 return bb.array();
850         }
851
852
853         public static byte[] arrBooleanToByteArray(boolean[] arrBool) {
854
855                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
856                 for(boolean b : arrBool) {
857                         if (b)
858                                 bb.put((byte)1);
859                         else
860                                 bb.put((byte)0);
861                 }
862
863                 return bb.array();
864         }
865
866
867         public static byte[] arrBooleanToByteArray(Boolean[] arrBool) {
868
869                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
870                 for(Boolean b : arrBool) {
871                         if (b)
872                                 bb.put((byte)1);
873                         else
874                                 bb.put((byte)0);
875                 }
876
877                 return bb.array();
878         }
879
880
881         public static byte[] arrStringToByteArray(String[] arrString) {
882
883                 // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
884                 // Prepare array of bytes
885                 int arrLen = INT_LEN;   // First allocation for array length
886                 for (int i = 0; i < arrString.length; i++) {
887                         arrLen = arrLen + INT_LEN + arrString[i].length();
888                 }       
889                 byte[] arrStrBytes = new byte[arrLen];
890                 // Copy bytes
891                 int pos = 0;
892                 byte[] strArrLenBytes = intToByteArray(arrString.length);
893                 System.arraycopy(strArrLenBytes, 0, arrStrBytes, pos, INT_LEN);
894                 pos = pos + INT_LEN;
895                 for (String str : arrString) {
896
897                         // Copy string length
898                         int strLen = str.length();
899                         byte[] strLenBytes = intToByteArray(strLen);
900                         System.arraycopy(strLenBytes, 0, arrStrBytes, pos, INT_LEN);
901                         pos = pos + INT_LEN;
902                         // Copy string
903                         byte[] strBytes = stringToByteArray(str);
904                         System.arraycopy(strBytes, 0, arrStrBytes, pos, strLen);
905                         pos = pos + strLen;
906                 }
907
908                 return arrStrBytes;
909         }
910
911
912         /**
913          * Converters from byte array
914          */
915         // Single variables     
916         public static short byteArrayToShort(byte[] bytes) {
917
918                 return ByteBuffer.wrap(bytes).getShort();
919         }
920
921
922         public static int byteArrayToInt(byte[] bytes) {
923
924                 return ByteBuffer.wrap(bytes).getInt();
925         }
926
927
928         public static long byteArrayToLong(byte[] bytes) {
929
930                 return ByteBuffer.wrap(bytes).getLong();
931         }
932
933
934         public static float byteArrayToFloat(byte[] bytes) {
935
936                 return ByteBuffer.wrap(bytes).getFloat();
937         }
938
939
940         public static double byteArrayToDouble(byte[] bytes) {
941
942                 return ByteBuffer.wrap(bytes).getDouble();
943         }
944
945
946         public static char byteArrayToChar(byte[] bytes) {
947
948                 return ByteBuffer.wrap(bytes).getChar();
949         }
950
951
952         public static boolean byteArrayToBoolean(byte[] bytes) {
953
954                 Byte boolValByte = ByteBuffer.wrap(bytes).get();
955                 short boolVal = boolValByte.shortValue();
956                 if (boolVal == 1)
957                         return true;
958                 else
959                         return false;
960         }
961
962
963     public static String byteArrayToString(byte[] bytes) {
964         return new String(bytes);
965     }
966
967
968         // Arrays
969         public static Byte[] byteArrayToByteArray(byte[] arrByt) {
970
971                 Byte[] arrByte = new Byte[arrByt.length];
972                 for(int i = 0; i < arrByt.length; i++) {
973                         arrByte[i] = arrByt[i];
974                 }
975
976                 return arrByte;
977         }
978         
979         
980         public static short[] byteArrayToShtArray(byte[] bytes) {
981
982                 // Single element bytes
983                 byte[] elmt = new byte[SHT_LEN];
984                 // Prepare array
985                 int arrLen = bytes.length / SHT_LEN;
986                 short[] arr = new short[arrLen];
987                 for(int i = 0; i < arrLen; i++) {
988                         int offset = i * SHT_LEN;
989                         System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
990                         arr[i] = byteArrayToShort(elmt);
991                 }
992
993                 return arr;
994         }
995
996
997         public static Short[] byteArrayToShortArray(byte[] bytes) {
998
999                 // Single element bytes
1000                 byte[] elmt = new byte[SHT_LEN];
1001                 // Prepare array
1002                 int arrLen = bytes.length / SHT_LEN;
1003                 Short[] arr = new Short[arrLen];
1004                 for(int i = 0; i < arrLen; i++) {
1005                         int offset = i * SHT_LEN;
1006                         System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
1007                         arr[i] = byteArrayToShort(elmt);
1008                 }
1009
1010                 return arr;
1011         }
1012
1013
1014         public static int[] byteArrayToIntArray(byte[] bytes) {
1015
1016                 // Single element bytes
1017                 byte[] elmt = new byte[INT_LEN];
1018                 // Prepare array
1019                 int arrLen = bytes.length / INT_LEN;
1020                 int[] arr = new int[arrLen];
1021                 for(int i = 0; i < arrLen; i++) {
1022                         int offset = i * INT_LEN;
1023                         System.arraycopy(bytes, offset, elmt, 0, INT_LEN);              
1024                         arr[i] = byteArrayToInt(elmt);
1025                 }
1026
1027                 return arr;
1028         }
1029
1030
1031         public static Integer[] byteArrayToIntegerArray(byte[] bytes) {
1032
1033                 // Single element bytes
1034                 byte[] elmt = new byte[INT_LEN];
1035                 // Prepare array
1036                 int arrLen = bytes.length / INT_LEN;
1037                 Integer[] arr = new Integer[arrLen];
1038                 for(int i = 0; i < arrLen; i++) {
1039                         int offset = i * INT_LEN;
1040                         System.arraycopy(bytes, offset, elmt, 0, INT_LEN);
1041                         arr[i] = byteArrayToInt(elmt);
1042                 }
1043
1044                 return arr;
1045         }
1046
1047
1048         public static long[] byteArrayToLngArray(byte[] bytes) {
1049
1050                 // Single element bytes
1051                 byte[] elmt = new byte[LNG_LEN];
1052                 // Prepare array
1053                 int arrLen = bytes.length / LNG_LEN;
1054                 long[] arr = new long[arrLen];
1055                 for(int i = 0; i < arrLen; i++) {
1056                         int offset = i * LNG_LEN;
1057                         System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);              
1058                         arr[i] = byteArrayToLong(elmt);
1059                 }
1060
1061                 return arr;
1062         }
1063
1064
1065         public static Long[] byteArrayToLongArray(byte[] bytes) {
1066
1067                 // Single element bytes
1068                 byte[] elmt = new byte[LNG_LEN];
1069                 // Prepare array
1070                 int arrLen = bytes.length / LNG_LEN;
1071                 Long[] arr = new Long[arrLen];
1072                 for(int i = 0; i < arrLen; i++) {
1073                         int offset = i * LNG_LEN;
1074                         System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);
1075                         arr[i] = byteArrayToLong(elmt);
1076                 }
1077
1078                 return arr;
1079         }
1080
1081
1082         public static float[] byteArrayToFltArray(byte[] bytes) {
1083
1084                 // Single element bytes
1085                 byte[] elmt = new byte[FLT_LEN];
1086                 // Prepare array
1087                 int arrLen = bytes.length / FLT_LEN;
1088                 float[] arr = new float[arrLen];
1089                 for(int i = 0; i < arrLen; i++) {
1090                         int offset = i * FLT_LEN;
1091                         System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);              
1092                         arr[i] = byteArrayToFloat(elmt);
1093                 }
1094
1095                 return arr;
1096         }
1097
1098
1099         public static Float[] byteArrayToFloatArray(byte[] bytes) {
1100
1101                 // Single element bytes
1102                 byte[] elmt = new byte[FLT_LEN];
1103                 // Prepare array
1104                 int arrLen = bytes.length / FLT_LEN;
1105                 Float[] arr = new Float[arrLen];
1106                 for(int i = 0; i < arrLen; i++) {
1107                         int offset = i * FLT_LEN;
1108                         System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);
1109                         arr[i] = byteArrayToFloat(elmt);
1110                 }
1111
1112                 return arr;
1113         }
1114
1115
1116         public static double[] byteArrayToDblArray(byte[] bytes) {
1117
1118                 // Single element bytes
1119                 byte[] elmt = new byte[DBL_LEN];
1120                 // Prepare array
1121                 int arrLen = bytes.length / DBL_LEN;
1122                 double[] arr = new double[arrLen];
1123                 for(int i = 0; i < arrLen; i++) {
1124                         int offset = i * DBL_LEN;
1125                         System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
1126                         arr[i] = byteArrayToDouble(elmt);
1127                 }
1128
1129                 return arr;
1130         }
1131
1132
1133         public static Double[] byteArrayToDoubleArray(byte[] bytes) {
1134
1135                 // Single element bytes
1136                 byte[] elmt = new byte[DBL_LEN];
1137                 // Prepare array
1138                 int arrLen = bytes.length / DBL_LEN;
1139                 Double[] arr = new Double[arrLen];
1140                 for(int i = 0; i < arrLen; i++) {
1141                         int offset = i * DBL_LEN;
1142                         System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
1143                         arr[i] = byteArrayToDouble(elmt);
1144                 }
1145
1146                 return arr;
1147         }
1148
1149
1150         public static char[] byteArrayToChrArray(byte[] bytes) {
1151
1152                 // Single element bytes
1153                 byte[] elmt = new byte[CHR_LEN];
1154                 // Prepare array
1155                 int arrLen = bytes.length / CHR_LEN;
1156                 char[] arr = new char[arrLen];
1157                 for(int i = 0; i < arrLen; i++) {
1158                         int offset = i * CHR_LEN;
1159                         System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
1160                         arr[i] = byteArrayToChar(elmt);
1161                 }
1162
1163                 return arr;
1164         }
1165
1166
1167         public static Character[] byteArrayToCharacterArray(byte[] bytes) {
1168
1169                 // Single element bytes
1170                 byte[] elmt = new byte[CHR_LEN];
1171                 // Prepare array
1172                 int arrLen = bytes.length / CHR_LEN;
1173                 Character[] arr = new Character[arrLen];
1174                 for(int i = 0; i < arrLen; i++) {
1175                         int offset = i * CHR_LEN;
1176                         System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
1177                         arr[i] = byteArrayToChar(elmt);
1178                 }
1179
1180                 return arr;
1181         }
1182
1183
1184         public static boolean[] byteArrayToBolArray(byte[] bytes) {
1185
1186                 // Single element bytes
1187                 byte[] elmt = new byte[BOL_LEN];
1188                 // Prepare array
1189                 int arrLen = bytes.length / BOL_LEN;
1190                 boolean[] arr = new boolean[arrLen];
1191                 for(int i = 0; i < arrLen; i++) {
1192                         int offset = i * BOL_LEN;
1193                         System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
1194                         arr[i] = byteArrayToBoolean(elmt);
1195                 }
1196
1197                 return arr;
1198         }
1199
1200
1201         public static Boolean[] byteArrayToBooleanArray(byte[] bytes) {
1202
1203                 // Single element bytes
1204                 byte[] elmt = new byte[BOL_LEN];
1205                 // Prepare array
1206                 int arrLen = bytes.length / BOL_LEN;
1207                 Boolean[] arr = new Boolean[arrLen];
1208                 for(int i = 0; i < arrLen; i++) {
1209                         int offset = i * BOL_LEN;
1210                         System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
1211                         arr[i] = byteArrayToBoolean(elmt);
1212                 }
1213
1214                 return arr;
1215         }
1216
1217
1218         public static String[] byteArrayToStringArray(byte[] bytes) {
1219
1220                 // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
1221                 // Get string array length
1222                 int pos = 0;
1223                 byte[] strArrLenBytes = new byte[INT_LEN];
1224                 System.arraycopy(bytes, pos, strArrLenBytes, 0, INT_LEN);
1225                 int strArrLen = byteArrayToInt(strArrLenBytes);
1226                 pos = pos + INT_LEN;
1227                 // Prepare string array
1228                 String[] strArray = new String[strArrLen];
1229                 // Extract array of strings
1230                 for(int i = 0; i < strArrLen; i++) {
1231
1232                         // Extract string length
1233                         byte[] strLenBytes = new byte[INT_LEN];
1234                         System.arraycopy(bytes, pos, strLenBytes, 0, INT_LEN);
1235                         int strLen = byteArrayToInt(strLenBytes);
1236                         pos = pos + INT_LEN;
1237                         // Extract string
1238                         byte[] strBytes = new byte[strLen];
1239                         System.arraycopy(bytes, pos, strBytes, 0, strLen);
1240                         pos = pos + strLen;
1241                         strArray[i] = byteArrayToString(strBytes);
1242                 }
1243
1244                 return strArray;
1245         }
1246
1247
1248         /**
1249          * toByteArray() gets Object and return its byte array
1250          * <p>
1251          * Adapted from http://www.java2s.com/
1252          *              @see <a href="http://www.java2s.com/Code/Java/File-Input-
1253          *              Output/Convertobjecttobytearrayandconvertbytearraytoobject.htm"</a>
1254          */
1255     // toByteArray and toObject are taken from: http://tinyurl.com/69h8l7x
1256     public static byte[] toByteArray(Object obj) throws IOException {
1257
1258         byte[] bytes = null;
1259         ByteArrayOutputStream bos = null;
1260         ObjectOutputStream oos = null;
1261         try {
1262
1263             bos = new ByteArrayOutputStream();
1264             oos = new ObjectOutputStream(bos);
1265             oos.writeObject(obj);
1266             oos.flush();
1267             bytes = bos.toByteArray();
1268         } finally {
1269
1270             if (oos != null) {
1271                 oos.close();
1272             }
1273             if (bos != null) {
1274                 bos.close();
1275             }
1276         }
1277         return bytes;
1278     }
1279
1280
1281         /**
1282          * toObject() gets byte array and return its Object
1283          * <p>
1284          * Adapted from http://www.java2s.com/
1285          *              @see <a href="http://www.java2s.com/Code/Java/File-Input-
1286          *              Output/Convertobjecttobytearrayandconvertbytearraytoobject.htm"</a>
1287          */
1288     public static Object toObject(byte[] bytes) throws IOException, ClassNotFoundException {
1289
1290         Object obj = null;
1291         ByteArrayInputStream bis = null;
1292         ObjectInputStream ois = null;
1293         try {
1294
1295             bis = new ByteArrayInputStream(bytes);
1296             ois = new ObjectInputStream(bis);
1297             obj = ois.readObject();
1298         } finally {
1299
1300             if (bis != null) {
1301                 bis.close();
1302             }
1303             if (ois != null) {
1304                 ois.close();
1305             }
1306         }
1307         return obj;
1308     }
1309 }