91454ed9be01734b94ddcb266a1245f06254ffe8
[platform/core/uifw/dali-core.git] / dali / public-api / object / property-value.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/object/property-value.h>
20
21 // EXTERNAL INCLUDES
22 #include <ostream>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/object/any.h>
26 #include <dali/public-api/math/angle-axis.h>
27 #include <dali/public-api/math/radian.h>
28 #include <dali/public-api/math/vector2.h>
29 #include <dali/public-api/math/vector3.h>
30 #include <dali/public-api/math/vector4.h>
31 #include <dali/public-api/math/matrix3.h>
32 #include <dali/public-api/math/matrix.h>
33 #include <dali/public-api/math/rect.h>
34 #include <dali/public-api/math/quaternion.h>
35 #include <dali/public-api/object/property-map.h>
36 #include <dali/public-api/object/property-types.h>
37 #include <dali/integration-api/debug.h>
38
39 namespace Dali
40 {
41
42 struct Property::Value::Impl
43 {
44   Impl()
45   : mType( Property::NONE )
46   {
47   }
48
49   Impl(bool boolValue)
50   : mType( PropertyTypes::Get<bool>() ),
51     mValue( boolValue )
52   {
53   }
54
55   Impl(float floatValue)
56   : mType( PropertyTypes::Get<float>() ),
57     mValue( floatValue )
58   {
59   }
60
61   Impl(int integerValue)
62   : mType( PropertyTypes::Get<int>() ),
63     mValue( integerValue )
64   {
65   }
66
67   Impl(unsigned int unsignedIntegerValue)
68   : mType( PropertyTypes::Get<unsigned int>() ),
69     mValue( unsignedIntegerValue )
70   {
71   }
72
73   Impl(const Vector2& vectorValue)
74   : mType( PropertyTypes::Get<Vector2>() ),
75     mValue( vectorValue )
76   {
77   }
78
79   Impl(const Vector3& vectorValue)
80   : mType( PropertyTypes::Get<Vector3>() ),
81     mValue( vectorValue )
82   {
83   }
84
85   Impl(const Vector4& vectorValue)
86   : mType( PropertyTypes::Get<Vector4>() ),
87     mValue( vectorValue )
88   {
89   }
90
91   Impl(const Matrix3& matrixValue)
92   : mType(PropertyTypes::Get<Matrix3>()),
93     mValue(matrixValue)
94   {
95   }
96
97   Impl(const Matrix& matrixValue)
98   : mType(PropertyTypes::Get<Matrix>()),
99     mValue(matrixValue)
100   {
101   }
102
103   Impl(const AngleAxis& angleAxisValue)
104   : mType( PropertyTypes::Get<AngleAxis>() ),
105     mValue( angleAxisValue )
106   {
107   }
108
109   Impl(const Quaternion& quaternionValue)
110   : mType( PropertyTypes::Get<Quaternion>() ),
111     mValue( quaternionValue )
112   {
113   }
114
115   Impl(const std::string& stringValue)
116     : mType( PropertyTypes::Get<std::string>() ),
117       mValue( stringValue )
118   {
119   }
120
121   Impl(const Rect<int>& rect)
122     : mType( PropertyTypes::Get<Rect<int> >() ),
123       mValue( rect )
124   {
125   }
126
127   Impl(Property::Map container)
128     : mType( PropertyTypes::Get<Property::Map >() ),
129       mValue( container )
130   {
131   }
132
133   Impl(Property::Array container)
134     : mType( PropertyTypes::Get<Property::Array >() ),
135       mValue( container )
136   {
137   }
138
139   Type mType;
140
141   typedef Any AnyValue;
142   AnyValue mValue;
143 };
144
145 Property::Value::Value()
146 : mImpl( NULL )
147 {
148   mImpl = new Impl();
149 }
150
151 Property::Value::Value(bool boolValue)
152 : mImpl( NULL )
153 {
154   mImpl = new Impl( boolValue );
155 }
156
157 Property::Value::Value(float floatValue)
158 : mImpl( NULL )
159 {
160   mImpl = new Impl( floatValue );
161 }
162
163 Property::Value::Value(int integerValue)
164 : mImpl( NULL )
165 {
166   mImpl = new Impl( integerValue );
167 }
168
169 Property::Value::Value(unsigned int unsignedIntegerValue)
170 : mImpl( NULL )
171 {
172   mImpl = new Impl( unsignedIntegerValue );
173 }
174
175 Property::Value::Value(const Vector2& vectorValue)
176 : mImpl( NULL )
177 {
178   mImpl = new Impl( vectorValue );
179 }
180
181 Property::Value::Value(const Vector3& vectorValue)
182 : mImpl( NULL )
183 {
184   mImpl = new Impl( vectorValue );
185 }
186
187 Property::Value::Value(const Vector4& vectorValue)
188 : mImpl( NULL )
189 {
190   mImpl = new Impl( vectorValue );
191 }
192
193 Property::Value::Value(const Matrix3& matrixValue)
194 : mImpl( NULL )
195 {
196   mImpl = new Impl( matrixValue );
197 }
198
199 Property::Value::Value(const Matrix& matrixValue)
200 : mImpl( NULL )
201 {
202   mImpl = new Impl( matrixValue );
203 }
204
205 Property::Value::Value(const Rect<int>& rect)
206 : mImpl( NULL )
207 {
208   mImpl = new Impl( rect );
209 }
210
211 Property::Value::Value(const AngleAxis& angleAxisValue)
212 : mImpl( NULL )
213 {
214   mImpl = new Impl( angleAxisValue );
215 }
216
217 Property::Value::Value(const Quaternion& quaternionValue)
218 {
219   mImpl = new Impl( quaternionValue );
220 }
221
222 Property::Value::Value(const std::string& stringValue)
223 {
224   mImpl = new Impl( stringValue );
225 }
226
227 Property::Value::Value(const char *stringValue)
228 {
229   mImpl = new Impl( std::string(stringValue) );
230 }
231
232 Property::Value::Value(Property::Array &arrayValue)
233 {
234   mImpl = new Impl( arrayValue );
235 }
236
237 Property::Value::Value(Property::Map &mapValue)
238 {
239   mImpl = new Impl( mapValue );
240 }
241
242
243 Property::Value::~Value()
244 {
245   delete mImpl;
246 }
247
248 Property::Value::Value(const Value& value)
249 {
250   switch (value.GetType())
251   {
252     case Property::BOOLEAN:
253     {
254       mImpl = new Impl( value.Get<bool>() );
255       break;
256     }
257
258     case Property::FLOAT:
259     {
260       mImpl = new Impl( value.Get<float>() );
261       break;
262     }
263
264     case Property::INTEGER:
265     {
266       mImpl = new Impl( value.Get<int>() );
267       break;
268     }
269
270     case Property::UNSIGNED_INTEGER:
271     {
272       mImpl = new Impl( value.Get<unsigned int>() );
273       break;
274     }
275
276     case Property::VECTOR2:
277     {
278       mImpl = new Impl( value.Get<Vector2>() );
279       break;
280     }
281
282     case Property::VECTOR3:
283     {
284       mImpl = new Impl( value.Get<Vector3>() );
285       break;
286     }
287
288     case Property::VECTOR4:
289     {
290       mImpl = new Impl( value.Get<Vector4>() );
291       break;
292     }
293
294     case Property::RECTANGLE:
295     {
296       mImpl = new Impl( value.Get<Rect<int> >() );
297       break;
298     }
299
300     case Property::ROTATION:
301     {
302       mImpl = new Impl( value.Get<Quaternion>() );
303       break;
304     }
305
306     case Property::MATRIX3:
307     {
308       mImpl = new Impl( value.Get<Matrix3>());
309       break;
310     }
311
312     case Property::MATRIX:
313     {
314       mImpl = new Impl( value.Get<Matrix>());
315       break;
316     }
317
318     case Property::STRING:
319     {
320       mImpl = new Impl( value.Get<std::string>() );
321       break;
322     }
323
324     case Property::MAP:
325     {
326       mImpl = new Impl( value.Get<Property::Map>() );
327       break;
328     }
329
330     case Property::ARRAY:
331     {
332       mImpl = new Impl( value.Get<Property::Array>() );
333       break;
334     }
335
336     case Property::NONE: // fall
337     default:
338     {
339       mImpl = new Impl();
340       break;
341     }
342   }
343 }
344
345 Property::Value::Value(Type type)
346 {
347   switch (type)
348   {
349     case Property::BOOLEAN:
350     {
351       mImpl = new Impl( false );
352       break;
353     }
354
355     case Property::FLOAT:
356     {
357       mImpl = new Impl( 0.f );
358       break;
359     }
360
361     case Property::INTEGER:
362     {
363       mImpl = new Impl( 0 );
364       break;
365     }
366
367     case Property::UNSIGNED_INTEGER:
368     {
369       mImpl = new Impl( 0U );
370       break;
371     }
372
373     case Property::VECTOR2:
374     {
375       mImpl = new Impl( Vector2::ZERO );
376       break;
377     }
378
379     case Property::VECTOR3:
380     {
381       mImpl = new Impl( Vector3::ZERO );
382       break;
383     }
384
385     case Property::VECTOR4:
386     {
387       mImpl = new Impl( Vector4::ZERO );
388       break;
389     }
390
391     case Property::RECTANGLE:
392     {
393       mImpl = new Impl( Rect<int>(0,0,0,0) );
394       break;
395     }
396
397     case Property::ROTATION:
398     {
399       mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
400       break;
401     }
402
403     case Property::STRING:
404     {
405       mImpl = new Impl( std::string() );
406       break;
407     }
408
409     case Property::MAP:
410     {
411       mImpl = new Impl( Property::Map() );
412       break;
413     }
414
415     case Property::MATRIX:
416     {
417       mImpl = new Impl( Matrix() );
418       break;
419     }
420
421     case Property::MATRIX3:
422     {
423       mImpl = new Impl( Matrix3() );
424       break;
425     }
426
427     case Property::ARRAY:
428     {
429       mImpl = new Impl( Property::Array() );
430       break;
431     }
432
433     case Property::NONE: // fall
434     default:
435     {
436       mImpl = new Impl();
437       break;
438     }
439   }
440 }
441
442 Property::Value& Property::Value::operator=(const Property::Value& value)
443 {
444   if (this == &value)
445   {
446     // skip self assignment
447     return *this;
448   }
449
450   mImpl->mType = value.GetType();
451
452   switch (mImpl->mType)
453   {
454     case Property::BOOLEAN:
455     {
456       mImpl->mValue = value.Get<bool>();
457       break;
458     }
459
460     case Property::FLOAT:
461     {
462       mImpl->mValue = value.Get<float>();
463       break;
464     }
465
466     case Property::INTEGER:
467     {
468       mImpl->mValue = value.Get<int>();
469       break;
470     }
471
472     case Property::UNSIGNED_INTEGER:
473     {
474       mImpl->mValue = value.Get<unsigned int>();
475       break;
476     }
477
478     case Property::VECTOR2:
479     {
480       mImpl->mValue = value.Get<Vector2>();
481       break;
482     }
483
484     case Property::VECTOR3:
485     {
486       mImpl->mValue = value.Get<Vector3>();
487       break;
488     }
489
490     case Property::VECTOR4:
491     {
492       mImpl->mValue = value.Get<Vector4>();
493       break;
494     }
495
496     case Property::RECTANGLE:
497     {
498       mImpl->mValue = value.Get<Rect<int> >();
499       break;
500     }
501
502     case Property::ROTATION:
503     {
504       mImpl->mValue = value.Get<Quaternion>();
505       break;
506     }
507
508     case Property::STRING:
509     {
510       mImpl->mValue = value.Get<std::string>();
511       break;
512     }
513
514     case Property::MATRIX:
515     {
516       mImpl->mValue = value.Get<Matrix>();
517       break;
518     }
519
520     case Property::MATRIX3:
521     {
522       mImpl->mValue = value.Get<Matrix3>();
523       break;
524     }
525
526     case Property::MAP:
527     {
528       mImpl->mValue = value.Get<Property::Map>();
529       break;
530     }
531
532     case Property::ARRAY:
533     {
534       mImpl->mValue = value.Get<Property::Array>();
535       break;
536     }
537
538     case Property::NONE: // fall
539     default:
540     {
541       mImpl->mValue = Impl::AnyValue(0);
542       break;
543     }
544   }
545
546   return *this;
547 }
548
549 Property::Type Property::Value::GetType() const
550 {
551   return mImpl->mType;
552 }
553
554 void Property::Value::Get(bool& boolValue) const
555 {
556   DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" );  // AnyCast does asserted type checking
557
558   boolValue = AnyCast<bool>(mImpl->mValue);
559 }
560
561 void Property::Value::Get(float& floatValue) const
562 {
563   DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
564
565   floatValue = AnyCast<float>(mImpl->mValue);
566 }
567
568 void Property::Value::Get(int& integerValue) const
569 {
570   DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
571
572   integerValue = AnyCast<int>(mImpl->mValue);
573 }
574
575 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
576 {
577   DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
578
579   unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
580 }
581
582 void Property::Value::Get(Vector2& vectorValue) const
583 {
584   DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
585
586   vectorValue = AnyCast<Vector2>(mImpl->mValue);
587 }
588
589 void Property::Value::Get(Vector3& vectorValue) const
590 {
591   DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
592
593   vectorValue = AnyCast<Vector3>(mImpl->mValue);
594 }
595
596 void Property::Value::Get(Vector4& vectorValue) const
597 {
598   DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
599
600   vectorValue = AnyCast<Vector4>(mImpl->mValue);
601 }
602
603 void Property::Value::Get(Matrix3& matrixValue) const
604 {
605   DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
606   matrixValue = AnyCast<Matrix3>(mImpl->mValue);
607 }
608
609 void Property::Value::Get(Matrix& matrixValue) const
610 {
611   DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
612   matrixValue = AnyCast<Matrix>(mImpl->mValue);
613 }
614
615 void Property::Value::Get(Rect<int>& rect) const
616 {
617   DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
618
619   rect = AnyCast<Rect<int> >(mImpl->mValue);
620 }
621
622 void Property::Value::Get(AngleAxis& angleAxisValue) const
623 {
624   DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
625
626   // Orientations have two representations
627   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
628                      typeid(AngleAxis)  == mImpl->mValue.GetType() );
629
630   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
631   {
632     Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
633
634     quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
635   }
636   else
637   {
638     angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
639   }
640 }
641
642 void Property::Value::Get(Quaternion& quaternionValue) const
643 {
644   DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
645
646   // Orientations have two representations
647   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
648                typeid(AngleAxis)  == mImpl->mValue.GetType() );
649
650   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
651   {
652     quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
653   }
654   else
655   {
656     AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
657
658     quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
659   }
660 }
661
662 void Property::Value::Get(std::string &out) const
663 {
664   DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
665
666   out = AnyCast<std::string>(mImpl->mValue);
667 }
668
669 void Property::Value::Get(Property::Array &out) const
670 {
671   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
672
673   out = AnyCast<Property::Array>(mImpl->mValue);
674 }
675
676 void Property::Value::Get(Property::Map &out) const
677 {
678   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
679
680   out = AnyCast<Property::Map>(mImpl->mValue);
681 }
682
683 Property::Value& Property::Value::GetValue(const std::string& key) const
684 {
685   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
686
687   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
688
689   DALI_ASSERT_DEBUG(container);
690
691   if(container)
692   {
693     Property::Value* value = container->Find( key );
694     if ( value )
695     {
696       return *value;
697     }
698   }
699
700   DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
701   DALI_ASSERT_ALWAYS(!"Cannot find property map key");
702 }
703
704 bool Property::Value::HasKey(const std::string& key) const
705 {
706   bool has = false;
707
708   if( Property::MAP == GetType() )
709   {
710     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
711
712     DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
713
714     if(container)
715     {
716       Property::Value* value = container->Find( key );
717       if ( value )
718       {
719         has = true;
720       }
721     }
722   }
723
724   return has;
725 }
726
727
728 const std::string& Property::Value::GetKey(const int index) const
729 {
730   switch( GetType() )
731   {
732     case Property::MAP:
733     {
734       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
735       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
736       if(container)
737       {
738         if(0 <= index && index < static_cast<int>(container->Count()))
739         {
740           return container->GetKey( index );
741         }
742       }
743     }
744     break;
745     case Property::NONE:
746     case Property::ARRAY:
747     case Property::BOOLEAN:
748     case Property::FLOAT:
749     case Property::UNSIGNED_INTEGER:
750     case Property::INTEGER:
751     case Property::VECTOR2:
752     case Property::VECTOR3:
753     case Property::VECTOR4:
754     case Property::MATRIX:
755     case Property::MATRIX3:
756     case Property::RECTANGLE:
757     case Property::ROTATION:
758     case Property::STRING:
759     case Property::TYPE_COUNT:
760     {
761       break;
762     }
763   }
764
765
766   // should never return this
767   static std::string null;
768   return null;
769 }
770
771
772 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
773 {
774   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
775
776   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
777
778   if(container)
779   {
780     (*container)[ key ] = value;
781   }
782 }
783
784 Property::Value& Property::Value::GetItem(const int index) const
785 {
786   switch( GetType() )
787   {
788     case Property::MAP:
789     {
790       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
791
792       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
793       if(container)
794       {
795         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
796         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
797
798         return container->GetValue( index );
799       }
800     }
801     break;
802
803     case Property::ARRAY:
804     {
805       int i = 0;
806       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
807
808       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
809       if(container)
810       {
811         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
812         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
813
814         for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
815         {
816           if(i++ == index)
817           {
818             return *iter;
819           }
820         }
821       }
822     }
823     break;
824
825     case Property::NONE:
826     case Property::BOOLEAN:
827     case Property::FLOAT:
828     case Property::INTEGER:
829     case Property::UNSIGNED_INTEGER:
830     case Property::VECTOR2:
831     case Property::VECTOR3:
832     case Property::VECTOR4:
833     case Property::MATRIX3:
834     case Property::MATRIX:
835     case Property::RECTANGLE:
836     case Property::ROTATION:
837     case Property::STRING:
838     case Property::TYPE_COUNT:
839     {
840       DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
841       break;
842     }
843
844   } // switch GetType()
845
846
847   DALI_ASSERT_ALWAYS(!"Property value index not valid");
848 }
849
850 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
851 {
852   Property::Value& ret( GetItem(index) );
853
854   if( Property::MAP == GetType() )
855   {
856     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
857     if( index < static_cast<int>(container->Count()) )
858     {
859       key = container->GetKey( index );
860     }
861   }
862
863   return ret;
864 }
865
866 void Property::Value::SetItem(const int index, const Property::Value &value)
867 {
868   switch( GetType() )
869   {
870     case Property::MAP:
871     {
872       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
873       if( container && index < static_cast<int>(container->Count()) )
874       {
875         Property::Value& indexValue = container->GetValue( index );
876         indexValue = value;
877       }
878     }
879     break;
880
881     case Property::ARRAY:
882     {
883       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
884       if( container && index < static_cast<int>(container->size()) )
885       {
886         (*container)[index] = value;
887       }
888     }
889     break;
890
891     case Property::NONE:
892     case Property::BOOLEAN:
893     case Property::FLOAT:
894     case Property::INTEGER:
895     case Property::UNSIGNED_INTEGER:
896     case Property::VECTOR2:
897     case Property::VECTOR3:
898     case Property::VECTOR4:
899     case Property::MATRIX3:
900     case Property::MATRIX:
901     case Property::RECTANGLE:
902     case Property::ROTATION:
903     case Property::STRING:
904     case Property::TYPE_COUNT:
905     {
906       DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
907       break;
908     }
909   }
910 }
911
912 int Property::Value::AppendItem(const Property::Value &value)
913 {
914   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
915
916   Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
917
918   if(container)
919   {
920     container->push_back(value);
921     return container->size() - 1;
922   }
923   else
924   {
925     return -1;
926   }
927
928 }
929
930 int Property::Value::GetSize() const
931 {
932   int ret = 0;
933
934   switch(GetType())
935   {
936     case Property::MAP:
937     {
938       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
939       if(container)
940       {
941         ret = container->Count();
942       }
943     }
944     break;
945
946     case Property::ARRAY:
947     {
948       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
949       if(container)
950       {
951         ret = container->size();
952       }
953     }
954     break;
955
956     case Property::NONE:
957     case Property::BOOLEAN:
958     case Property::FLOAT:
959     case Property::INTEGER:
960     case Property::UNSIGNED_INTEGER:
961     case Property::VECTOR2:
962     case Property::VECTOR3:
963     case Property::VECTOR4:
964     case Property::MATRIX3:
965     case Property::MATRIX:
966     case Property::RECTANGLE:
967     case Property::ROTATION:
968     case Property::STRING:
969     case Property::TYPE_COUNT:
970     {
971       break;
972     }
973
974   }
975
976   return ret;
977 }
978
979 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
980 {
981
982   const Property::Value::Impl& impl( *value.mImpl );
983
984   switch( impl.mType )
985   {
986     case Dali::Property::STRING:
987     {
988       stream <<  AnyCast<std::string>(impl.mValue).c_str();
989       break;
990     }
991     case Dali::Property::VECTOR2:
992     {
993       stream << AnyCast<Vector2>(impl.mValue);
994       break;
995     }
996     case Dali::Property::VECTOR3:
997     {
998       stream << AnyCast<Vector3>(impl.mValue);
999       break;
1000     }
1001     case Dali::Property::VECTOR4:
1002     {
1003       stream << AnyCast<Vector4>(impl.mValue);
1004       break;
1005     }
1006     case Dali::Property::MATRIX:
1007     {
1008       stream << AnyCast<Matrix>(impl.mValue);
1009       break;
1010     }
1011     case Dali::Property::BOOLEAN:
1012     {
1013       stream << AnyCast<bool>(impl.mValue);
1014       break;
1015     }
1016     case Dali::Property::FLOAT:
1017     {
1018       stream << AnyCast<float>(impl.mValue);
1019       break;
1020     }
1021     case Dali::Property::INTEGER:
1022     {
1023        stream << AnyCast<int>(impl.mValue);
1024        break;
1025     }
1026     case Dali::Property::UNSIGNED_INTEGER:
1027     {
1028       stream << AnyCast<unsigned int>(impl.mValue);
1029       break;
1030     }
1031     case Dali::Property::RECTANGLE:
1032     {
1033       Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1034       value.Get( rect );
1035       stream << rect;
1036       break;
1037     }
1038     case Dali::Property::MATRIX3:
1039     {
1040       stream << AnyCast<Matrix3>(impl.mValue);
1041       break;
1042     }
1043     case Dali::Property::ROTATION:
1044     {
1045       // @todo this may change to Quaternion
1046       Dali::Quaternion q;
1047       value.Get( q );
1048       Dali::Vector4 v4 = q.EulerAngles();
1049       stream << v4;
1050       break;
1051     }
1052
1053     case Dali::Property::ARRAY:
1054     {
1055       // @todo Need to think about the best way to support array
1056       // E.g Do we want to create a JSON style array like:
1057       // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1058       stream << "ARRAY unsupported";
1059       break;
1060     }
1061     case Dali::Property::MAP:
1062     {
1063       Dali::Property::Map map;
1064       value.Get( map );
1065       stream << "Map containing " << map.Count() << " elements";
1066       break;
1067     }
1068     case Dali::Property::TYPE_COUNT:
1069     {
1070       stream << "unsupported TYPE_COUNT";
1071       break;
1072     }
1073     default:
1074     {
1075       stream << "unsupported type = " << value.GetType();
1076       break;
1077     }
1078   }
1079   return stream;
1080 }
1081
1082
1083 } // namespace Dali