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