Merge branch 'plugin-interface' into master
[platform/upstream/iotivity.git] / service / resource-encapsulation / android / service / src / main / java / org / iotivity / service / RcsValue.java
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 package org.iotivity.service;
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 /**
28  * Value holds a value among various types at a time.
29  *
30  * Type helps identify type information of Value.
31  *
32  * @see RCSResourceAttributes
33  * @see Type
34  */
35 public final class RcsValue {
36
37     private static class NullType {
38         @Override
39         public String toString() {
40             return "";
41         }
42     }
43
44     /**
45      * Identifiers for types of Value.
46      *
47      * @see Type
48      */
49     public static enum TypeId {
50         NULL, BOOLEAN, INTEGER, DOUBLE, STRING, ATTRIBUTES, ARRAY;
51     }
52
53     /**
54      * A Helper class to identify types of Value.
55      *
56      * @see RCSResourceAttributes
57      * @see Value
58      * @see TypeId
59      */
60     public static class Type {
61         private final TypeId mTypeId;
62
63         Type(TypeId typeId) {
64             mTypeId = typeId;
65         }
66
67         /**
68          * Returns type identifier.
69          *
70          * @return Identifier of type
71          *
72          * @see getBaseTypeId
73          */
74         public final TypeId getTypeId() {
75             return mTypeId;
76         }
77
78         protected TypeId getBaseTypeId() {
79             return mTypeId;
80         }
81
82         protected int getDepth() {
83             return 0;
84         }
85
86         /**
87          * Returns the type identifier of a base type of sequence.
88          *
89          * For non sequence types, it is equivalent to calling getId.
90          *
91          * @return identifier of type
92          *
93          * @see getDepth
94          * @see getId
95          */
96         public static TypeId getBaseTypeId(Type t) {
97             return t.getBaseTypeId();
98         }
99
100         /**
101          * Returns the depth of a type.
102          *
103          * The return will be zero for non sequence types.
104          *
105          * @see getBaseTypeId
106          */
107         public static int getDepth(Type t) {
108             return t.getDepth();
109         }
110
111         /**
112          * Factory method to create Type instance from an object.
113          *
114          * @return An instance that has TypeId for obj.
115          *
116          * @note object must be a supported type by Value.
117          *
118          * @throws NullPointerException
119          *             if obj is null.
120          * @throws IllegalArgumentException
121          *             if obj is not supported type.
122          *
123          */
124         public static Type typeOf(Object obj) {
125             if (obj == null) {
126                 throw new NullPointerException("object is null");
127             }
128
129             return typeOf(obj.getClass());
130         }
131
132         /**
133          * Factory method to create Type instance from a clss.
134          *
135          * @return An instance that has TypeId for class.
136          *
137          * @note class must be a supported type by Value.
138          *
139          * @throws NullPointerException
140          *             if cls is null.
141          * @throws IllegalArgumentException
142          *             if cls is not supported type.
143          *
144          */
145         public static Type typeOf(Class<?> cls) {
146             if (cls == null) {
147                 throw new NullPointerException("class is null");
148             }
149
150             if (sTypes.containsKey(cls)) return sTypes.get(cls);
151
152             throw new IllegalArgumentException(
153                     cls.getSimpleName() + " is not supported type.");
154         }
155     }
156
157     private static class ArrayType extends Type {
158         private final TypeId mBaseTypeId;
159         private final int    mDimension;
160
161         ArrayType(TypeId baseTypeId, int dimension) {
162             super(TypeId.ARRAY);
163
164             mBaseTypeId = baseTypeId;
165             mDimension = dimension;
166         }
167
168         @Override
169         protected TypeId getBaseTypeId() {
170             return mBaseTypeId;
171         }
172
173         @Override
174         protected int getDepth() {
175             return mDimension;
176         }
177     }
178
179     private static final NullType sNullValue = new NullType();
180
181     private static Map<Class<?>, Type> sTypes;
182
183     private final Object mObject;
184     private Type         mType;
185
186     static {
187         final Map<Class<?>, Type> types = new HashMap<Class<?>, Type>();
188
189         types.put(NullType.class, new Type(TypeId.NULL));
190         types.put(Boolean.class, new Type(TypeId.BOOLEAN));
191         types.put(Integer.class, new Type(TypeId.INTEGER));
192         types.put(Double.class, new Type(TypeId.DOUBLE));
193         types.put(String.class, new Type(TypeId.STRING));
194         types.put(RcsResourceAttributes.class, new Type(TypeId.ATTRIBUTES));
195
196         types.put(boolean[].class, new ArrayType(TypeId.BOOLEAN, 1));
197         types.put(int[].class, new ArrayType(TypeId.INTEGER, 1));
198         types.put(double[].class, new ArrayType(TypeId.DOUBLE, 1));
199         types.put(String[].class, new ArrayType(TypeId.STRING, 1));
200         types.put(RcsResourceAttributes[].class,
201                 new ArrayType(TypeId.ATTRIBUTES, 1));
202
203         types.put(boolean[][].class, new ArrayType(TypeId.BOOLEAN, 2));
204         types.put(int[][].class, new ArrayType(TypeId.INTEGER, 2));
205         types.put(double[][].class, new ArrayType(TypeId.DOUBLE, 2));
206         types.put(String[][].class, new ArrayType(TypeId.STRING, 2));
207         types.put(RcsResourceAttributes[][].class,
208                 new ArrayType(TypeId.ATTRIBUTES, 2));
209
210         types.put(boolean[][][].class, new ArrayType(TypeId.BOOLEAN, 3));
211         types.put(int[][][].class, new ArrayType(TypeId.INTEGER, 3));
212         types.put(double[][][].class, new ArrayType(TypeId.DOUBLE, 3));
213         types.put(String[][][].class, new ArrayType(TypeId.STRING, 3));
214         types.put(RcsResourceAttributes[][][].class,
215                 new ArrayType(TypeId.ATTRIBUTES, 3));
216
217         sTypes = Collections.unmodifiableMap(types);
218
219     }
220
221     static boolean isSupportedType(Class<?> cls) {
222         return sTypes.containsKey(cls);
223     }
224
225     static void verifySupportedType(Class<?> cls) {
226         if (!isSupportedType(cls)) {
227             throw new IllegalArgumentException(
228                     cls.getSimpleName() + " is not supported type.");
229         }
230     }
231
232     /**
233      * Constructs a new value with an object.
234      *
235      * @param value
236      *            An object
237      *
238      * @throws NullPointerException
239      *             if value is null.
240      * @throws IllegalArgumentException
241      *             if value is not supported type.
242      */
243     public RcsValue(Object value) {
244         if (value == null) throw new NullPointerException("value is null!");
245
246         verifySupportedType(value.getClass());
247
248         mObject = value;
249     }
250
251     /**
252      * Constructs a new value that holds null value.
253      *
254      */
255     public RcsValue() {
256         this(sNullValue);
257     }
258
259     /**
260      * Constructs a new value that holds null value.
261      *
262      * @param value
263      *            a boolean
264      */
265     public RcsValue(boolean value) {
266         this((Object) value);
267     }
268
269     /**
270      * Constructs a new value that holds an int value.
271      *
272      * @param value
273      *            an int
274      */
275     public RcsValue(int value) {
276         this((Object) value);
277     }
278
279     /**
280      * Constructs a new value that holds a double value.
281      *
282      * @param value
283      *            a double
284      */
285     public RcsValue(double value) {
286         this((Object) value);
287     }
288
289     /**
290      * Constructs a new value that holds a String value.
291      *
292      * @param value
293      *            a String
294      *
295      * @throws NullPointerException
296      *             if value is null.
297      */
298     public RcsValue(String value) {
299         this((Object) value);
300     }
301
302     /**
303      * Constructs a new value that holds a RcsResourceAttributes value.
304      *
305      * @param value
306      *            a RcsResourceAttributes
307      *
308      * @throws NullPointerException
309      *             if value is null.
310      */
311     public RcsValue(RcsResourceAttributes value) {
312         this((Object) value);
313     }
314
315     /**
316      * Constructs a new value that holds a boolean array.
317      *
318      * @param value
319      *            a boolean array
320      *
321      * @throws NullPointerException
322      *             if value is null.
323      */
324     public RcsValue(boolean[] value) {
325         this((Object) value);
326     }
327
328     /**
329      * Constructs a new value that holds a two-dimensional boolean array.
330      *
331      * @param value
332      *            a two-dimensional boolean array
333      *
334      * @throws NullPointerException
335      *             if value is null.
336      */
337     public RcsValue(boolean[][] value) {
338         this((Object) value);
339     }
340
341     /**
342      * Constructs a new value that holds a three-dimensional boolean array.
343      *
344      * @param value
345      *            a three-dimensional boolean array
346      *
347      * @throws NullPointerException
348      *             if value is null.
349      */
350     public RcsValue(boolean[][][] value) {
351         this((Object) value);
352     }
353
354     /**
355      * Constructs a new value that holds an int array.
356      *
357      * @param value
358      *            an int array
359      *
360      * @throws NullPointerException
361      *             if value is null.
362      */
363     public RcsValue(int[] value) {
364         this((Object) value);
365     }
366
367     /**
368      * Constructs a new value that holds a two-dimensional int array.
369      *
370      * @param value
371      *            a two-dimensional int array
372      *
373      * @throws NullPointerException
374      *             if value is null.
375      */
376     public RcsValue(int[][] value) {
377         this((Object) value);
378     }
379
380     /**
381      * Constructs a new value that holds a three-dimensional int array.
382      *
383      * @param value
384      *            a three-dimensional int array
385      *
386      * @throws NullPointerException
387      *             if value is null.
388      */
389     public RcsValue(int[][][] value) {
390         this((Object) value);
391     }
392
393     /**
394      * Constructs a new value that holds a double array.
395      *
396      * @param value
397      *            a double array
398      *
399      * @throws NullPointerException
400      *             if value is null.
401      */
402     public RcsValue(double[] value) {
403         this((Object) value);
404     }
405
406     /**
407      * Constructs a new value that holds a two-dimensional double array.
408      *
409      * @param value
410      *            a two-dimensional double array
411      *
412      * @throws NullPointerException
413      *             if value is null.
414      */
415     public RcsValue(double[][] value) {
416         this((Object) value);
417     }
418
419     /**
420      * Constructs a new value that holds a three-dimensional double array.
421      *
422      * @param value
423      *            a three-dimensional double array
424      *
425      * @throws NullPointerException
426      *             if value is null.
427      */
428     public RcsValue(double[][][] value) {
429         this((Object) value);
430     }
431
432     /**
433      * Constructs a new value that holds a String array.
434      *
435      * @param value
436      *            a String array
437      *
438      * @throws NullPointerException
439      *             if value is null.
440      */
441     public RcsValue(String[] value) {
442         this((Object) value);
443     }
444
445     /**
446      * Constructs a new value that holds a two-dimensional String array.
447      *
448      * @param value
449      *            a two-dimensional String array
450      *
451      * @throws NullPointerException
452      *             if value is null.
453      */
454     public RcsValue(String[][] value) {
455         this((Object) value);
456     }
457
458     /**
459      * Constructs a new value that holds a three-dimensional String array.
460      *
461      * @param value
462      *            a three-dimensional String array
463      *
464      * @throws NullPointerException
465      *             if value is null.
466      */
467     public RcsValue(String[][][] value) {
468         this((Object) value);
469     }
470
471     /**
472      * Constructs a new value that holds a RcsResourceAttributes array.
473      *
474      * @param value
475      *            a RcsResourceAttributes array
476      *
477      * @throws NullPointerException
478      *             if value is null.
479      */
480     public RcsValue(RcsResourceAttributes[] value) {
481         this((Object) value);
482     }
483
484     /**
485      * Constructs a new value that holds a two-dimensional RcsResourceAttributes
486      * array.
487      *
488      * @param value
489      *            a two-dimensional RcsResourceAttributes array
490      *
491      * @throws NullPointerException
492      *             if value is null.
493      */
494     public RcsValue(RcsResourceAttributes[][] value) {
495         this((Object) value);
496     }
497
498     /**
499      * Constructs a new value that holds a three-dimensional
500      * RcsResourceAttributes array.
501      *
502      * @param value
503      *            a three-dimensional RcsResourceAttributes array
504      *
505      * @throws NullPointerException
506      *             if value is null.
507      */
508     public RcsValue(RcsResourceAttributes[][][] value) {
509         this((Object) value);
510     }
511
512     /**
513      * Returns the value it represents is null.
514      *
515      * @return true if the value is null.
516      */
517     public boolean isNull() {
518         return isNullObject(mObject);
519     }
520
521     /**
522      * Returns the object represents null for RcsValue.
523      *
524      * @param o
525      *            an object to be tested
526      *
527      * @return true if the object represents null.
528      */
529     public static boolean isNullObject(Object o) {
530         return o == sNullValue;
531     }
532
533     /**
534      * Returns type information.
535      *
536      * @return type information for the value.
537      */
538     public Type getType() {
539         if (mType == null) mType = Type.typeOf(mObject);
540         return mType;
541     }
542
543     /**
544      * Returns the value as T.
545      *
546      * @return a value as T
547      *
548      * @throws ClassCastException
549      *             if the value is not of T.
550      */
551     @SuppressWarnings("unchecked")
552     public <T> T get() {
553         return (T) mObject;
554     }
555
556     @SuppressWarnings("unchecked")
557     private <T> T getOrNull() {
558         try {
559             return (T) mObject;
560         } catch (final ClassCastException e) {
561             return null;
562         }
563     }
564
565     /**
566      * Returns the value as an Object.
567      *
568      * @return an Object
569      */
570     public Object asObject() {
571         return mObject;
572     }
573
574     /**
575      * Returns the value as a boolean, false if the value is not the desired
576      * type.
577      *
578      * @return a boolean value
579      *
580      */
581     public boolean asBoolean() {
582         return asBoolean(false);
583     }
584
585     /**
586      * Returns the value as a boolean.
587      *
588      * @param defaultValue
589      *            value to return if the value is not boolean.
590      *
591      * @return a boolean value
592      *
593      */
594     public boolean asBoolean(boolean defaultValue) {
595         try {
596             return get();
597         } catch (final ClassCastException e) {
598             return defaultValue;
599         }
600     }
601
602     /**
603      * Returns the value as an int, 0 if the value is not the desired type.
604      *
605      * @return an int value
606      *
607      */
608     public int asInt() {
609         return asInt(0);
610     }
611
612     /**
613      * Returns the value as an int.
614      *
615      * @param defaultValue
616      *            value to return if the value is not int.
617      *
618      * @return an int value
619      *
620      */
621     public int asInt(int defaultValue) {
622         try {
623             return get();
624         } catch (final ClassCastException e) {
625             return defaultValue;
626         }
627     }
628
629     /**
630      * Returns the value as a double, 0 if the value is not the desired type.
631      *
632      * @return a double value
633      *
634      */
635     public double asDouble() {
636         return asDouble(0);
637     }
638
639     /**
640      * Returns the value as a double.
641      *
642      * @param defaultValue
643      *            value to return if the value is not double.
644      *
645      * @return a double value
646      *
647      */
648     public double asDouble(double defaultValue) {
649         try {
650             return get();
651         } catch (final ClassCastException e) {
652             return defaultValue;
653         }
654     }
655
656     /**
657      * Returns the value as a string, null if the value is not the desired type.
658      *
659      * @return a string value
660      *
661      */
662     public String asString() {
663         return asString(null);
664     }
665
666     /**
667      * Returns the value as a String.
668      *
669      * @param defaultValue
670      *            value to return if the value is not String.
671      *
672      * @return a String value
673      *
674      */
675     public String asString(String defaultValue) {
676         try {
677             return get();
678         } catch (final ClassCastException e) {
679             return defaultValue;
680         }
681     }
682
683     /**
684      * Returns the value as a RcsResourceAttributes,
685      * null if the value is not the desired type.
686      *
687      * @return a RcsResourceAttributes value
688      *
689      */
690     public RcsResourceAttributes asAttributes() {
691         return getOrNull();
692     }
693
694     /**
695      * Returns the value as a boolean array, null if the value is not the
696      * desired type.
697      *
698      * @return a boolean array
699      *
700      */
701     public boolean[] asBooleanArray() {
702         return getOrNull();
703     }
704
705     /**
706      * Returns the value as a two-dimensional boolean array, null if the value
707      * is not the desired type.
708      *
709      * @return a two-dimensional boolean array
710      *
711      */
712     public boolean[][] asBoolean2DArray() {
713         return getOrNull();
714     }
715
716     /**
717      * Returns the value as a three-dimensional boolean array, null if the value
718      * is not the desired type.
719      *
720      * @return a three-dimensional boolean array
721      *
722      */
723     public boolean[][][] asBoolean3DArray() {
724         return getOrNull();
725     }
726
727     /**
728      * Returns the value as an int array, null if the value is not the
729      * desired type.
730      *
731      * @return an int array
732      *
733      */
734     public int[] asIntArray() {
735         return getOrNull();
736     }
737
738     /**
739      * Returns the value as a two-dimensional int array, null if the value
740      * is not the desired type.
741      *
742      * @return a two-dimensional int array
743      *
744      */
745     public int[][] asInt2DArray() {
746         return getOrNull();
747     }
748
749     /**
750      * Returns the value as a three-dimensional int array, null if the value
751      * is not the desired type.
752      *
753      * @return a three-dimensional int array
754      *
755      */
756     public int[][][] asInt3DArray() {
757         return getOrNull();
758     }
759
760     /**
761      * Returns the value as a double array, null if the value is not the
762      * desired type.
763      *
764      * @return a double array
765      *
766      */
767     public double[] asDoubleArray() {
768         return getOrNull();
769     }
770
771     /**
772      * Returns the value as a two-dimensional double array, null if the value
773      * is not the desired type.
774      *
775      * @return a two-dimensional double array
776      *
777      */
778     public double[][] asDouble2DArray() {
779         return getOrNull();
780     }
781
782     /**
783      * Returns the value as a three-dimensional double array, null if the value
784      * is not the desired type.
785      *
786      * @return a three-dimensional double array
787      *
788      */
789     public double[][][] asDouble3DArray() {
790         return getOrNull();
791     }
792
793     /**
794      * Returns the value as a string array, null if the value is not the
795      * desired type.
796      *
797      * @return a string array
798      *
799      */
800     public String[] asStringArray() {
801         return getOrNull();
802     }
803
804     /**
805      * Returns the value as a two-dimensional string array, null if the value
806      * is not the desired type.
807      *
808      * @return a two-dimensional string array
809      *
810      */
811     public String[][] asString2DArray() {
812         return getOrNull();
813     }
814
815     /**
816      * Returns the value as a three-dimensional string array, null if the value
817      * is not the desired type.
818      *
819      * @return a three-dimensional string array
820      *
821      */
822     public String[][][] asString3DArray() {
823         return getOrNull();
824     }
825
826     /**
827      * Returns the value as an attributes array, null if the value is not the
828      * desired type.
829      *
830      * @return an attributes array
831      *
832      */
833     public RcsResourceAttributes[] asAttributesArray() {
834         return getOrNull();
835     }
836
837     /**
838      * Returns the value as a two-dimensional attributes array, null if the
839      * value is not the desired type.
840      *
841      * @return a two-dimensional attributes array
842      *
843      */
844     public RcsResourceAttributes[][] asAttributes2DArray() {
845         return getOrNull();
846     }
847
848     /**
849      * Returns the value as a three-dimensional attributes array, null if the
850      * value is not the desired type.
851      *
852      * @return a three-dimensional attributes array
853      *
854      */
855     public RcsResourceAttributes[][][] asAttributes3DArray() {
856         return getOrNull();
857     }
858
859     @Override
860     public boolean equals(Object o) {
861         if (o == this) return true;
862         if (!(o instanceof RcsValue)) return false;
863
864         final RcsValue rhs = (RcsValue) o;
865
866         return mObject.equals(rhs.mObject);
867     }
868
869     @Override
870     public int hashCode() {
871         return mObject.hashCode();
872     }
873
874     @Override
875     public String toString() {
876         return mObject.toString();
877     }
878
879 }