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