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