00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <cassert>
00028 # include <algorithm>
00029 #endif
00030
00032 #include <Base/Reader.h>
00033 #include <Base/Writer.h>
00034 #include <Base/Console.h>
00035 #include <Base/Exception.h>
00036
00037 #include "Property.h"
00038 #include "PropertyContainer.h"
00039 #include "PropertyLinks.h"
00040
00041 using namespace App;
00042 using namespace Base;
00043 using namespace std;
00044
00045 TYPESYSTEM_SOURCE(App::PropertyContainer,Base::Persistence);
00046
00047
00048
00049
00050
00051
00052 PropertyContainer::PropertyContainer()
00053 {
00054 propertyData.parentPropertyData = 0;
00055 }
00056
00057 PropertyContainer::~PropertyContainer()
00058 {
00059
00060 }
00061
00062 unsigned int PropertyContainer::getMemSize (void) const
00063 {
00064 std::map<std::string,Property*> Map;
00065 getPropertyMap(Map);
00066 std::map<std::string,Property*>::const_iterator It;
00067 unsigned int size = 0;
00068 for (It = Map.begin(); It != Map.end();++It)
00069 size += It->second->getMemSize();
00070 return size;
00071 }
00072
00073 Property *PropertyContainer::getPropertyByName(const char* name) const
00074 {
00075 return getPropertyData().getPropertyByName(this,name);
00076 }
00077
00078 void PropertyContainer::getPropertyMap(std::map<std::string,Property*> &Map) const
00079 {
00080 getPropertyData().getPropertyMap(this,Map);
00081 }
00082
00083 void PropertyContainer::getPropertyList(std::vector<Property*> &List) const
00084 {
00085 getPropertyData().getPropertyList(this,List);
00086 }
00087
00088 void PropertyContainer::setPropertyStatus(unsigned char bit,bool value)
00089 {
00090 std::vector<Property*> List;
00091 getPropertyList(List);
00092 for(std::vector<Property*>::const_iterator it=List.begin();it!=List.end();++it)
00093 (**it).StatusBits.set(bit,value);
00094 }
00095
00096 short PropertyContainer::getPropertyType(const Property* prop) const
00097 {
00098 return getPropertyData().getType(this,prop);
00099 }
00100
00101 short PropertyContainer::getPropertyType(const char *name) const
00102 {
00103 return getPropertyData().getType(this,name);
00104 }
00105
00106 const char* PropertyContainer::getPropertyGroup(const Property* prop) const
00107 {
00108 return getPropertyData().getGroup(this,prop);
00109 }
00110
00111 const char* PropertyContainer::getPropertyGroup(const char *name) const
00112 {
00113 return getPropertyData().getGroup(this,name);
00114 }
00115
00116 const char* PropertyContainer::getPropertyDocumentation(const Property* prop) const
00117 {
00118 return getPropertyData().getDocumentation(this,prop);
00119 }
00120
00121 const char* PropertyContainer::getPropertyDocumentation(const char *name) const
00122 {
00123 return getPropertyData().getDocumentation(this,name);
00124 }
00125
00126 bool PropertyContainer::isReadOnly(const Property* prop) const
00127 {
00128 return (getPropertyData().getType(this,prop) & Prop_ReadOnly) == Prop_ReadOnly;
00129 }
00130
00131 bool PropertyContainer::isReadOnly(const char *name) const
00132 {
00133 return (getPropertyData().getType(this,name) & Prop_ReadOnly) == Prop_ReadOnly;
00134 }
00135
00136 bool PropertyContainer::isHidden(const Property* prop) const
00137 {
00138 return (getPropertyData().getType(this,prop) & Prop_Hidden) == Prop_Hidden;
00139 }
00140
00141 bool PropertyContainer::isHidden(const char *name) const
00142 {
00143 return (getPropertyData().getType(this,name) & Prop_Hidden) == Prop_Hidden;
00144 }
00145
00146 const char* PropertyContainer::getName(const Property* prop)const
00147 {
00148 return getPropertyData().getName(this,prop);
00149 }
00150
00151
00152 const PropertyData * PropertyContainer::getPropertyDataPtr(void){return &propertyData;}
00153 const PropertyData & PropertyContainer::getPropertyData(void) const{return propertyData;}
00154
00155 PropertyData PropertyContainer::propertyData;
00156
00160 template <class TCLASS>
00161 class PropertyAttribute : public std::binary_function<TCLASS, typename App::PropertyType, bool>
00162 {
00163 public:
00164 PropertyAttribute(const PropertyContainer* c) : cont(c) {}
00165 bool operator () (const TCLASS& prop, typename App::PropertyType attr) const
00166 { return (cont->getPropertyType(prop.second) & attr) == attr; }
00167 private:
00168 const PropertyContainer* cont;
00169 };
00170
00171 void PropertyContainer::Save (Base::Writer &writer) const
00172 {
00173 std::map<std::string,Property*> Map;
00174 getPropertyMap(Map);
00175
00176
00177 size_t ct = std::count_if(Map.begin(), Map.end(), std::bind2nd(PropertyAttribute
00178 <std::pair<std::string,Property*> >(this), Prop_Transient));
00179 size_t size = Map.size() - ct;
00180
00181 writer.incInd();
00182 writer.Stream() << writer.ind() << "<Properties Count=\"" << size << "\">" << endl;
00183 std::map<std::string,Property*>::iterator it;
00184 for (it = Map.begin(); it != Map.end(); ++it)
00185 {
00186
00187 if (!(getPropertyType(it->second) & Prop_Transient))
00188 {
00189 writer.incInd();
00190 writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\""
00191 << it->second->getTypeId().getName() << "\">" << endl;;
00192 writer.incInd();
00193 try {
00194
00195
00196
00197 it->second->Save(writer);
00198 }
00199 catch (const Base::Exception &e) {
00200 Base::Console().Error("%s\n", e.what());
00201 }
00202 catch (const std::exception &e) {
00203 Base::Console().Error("%s\n", e.what());
00204 }
00205 catch (const char* e) {
00206 Base::Console().Error("%s\n", e);
00207 }
00208 #ifndef FC_DEBUG
00209 catch (...) {
00210 Base::Console().Error("PropertyContainer::Save: Unknown C++ exception thrown. Try to continue...\n");
00211 }
00212 #endif
00213 writer.decInd();
00214 writer.Stream() << writer.ind() << "</Property>" << endl;
00215 writer.decInd();
00216 }
00217 }
00218 writer.Stream() << writer.ind() << "</Properties>" << endl;
00219 writer.decInd();
00220 }
00221
00222 void PropertyContainer::Restore(Base::XMLReader &reader)
00223 {
00224 reader.readElement("Properties");
00225 int Cnt = reader.getAttributeAsInteger("Count");
00226
00227 for (int i=0 ;i<Cnt ;i++) {
00228 reader.readElement("Property");
00229 const char* PropName = reader.getAttribute("name");
00230 const char* TypeName = reader.getAttribute("type");
00231 Property* prop = getPropertyByName(PropName);
00232
00233
00234
00235
00236 try {
00237 if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0)
00238 prop->Restore(reader);
00239 }
00240 catch (const Base::XMLParseException&) {
00241 throw;
00242 }
00243 catch (const Base::Exception &e) {
00244 Base::Console().Error("%s\n", e.what());
00245 }
00246 catch (const std::exception &e) {
00247 Base::Console().Error("%s\n", e.what());
00248 }
00249 catch (const char* e) {
00250 Base::Console().Error("%s\n", e);
00251 }
00252 #ifndef FC_DEBUG
00253 catch (...) {
00254 Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown");
00255 }
00256 #endif
00257
00258 reader.readEndElement("Property");
00259 }
00260 reader.readEndElement("Properties");
00261 }
00262
00263 void PropertyData::addProperty(const PropertyContainer *container,const char* PropName, Property *Prop, const char* PropertyGroup , PropertyType Type, const char* PropertyDocu)
00264 {
00265 bool IsIn = false;
00266 for (vector<PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
00267 if(strcmp(It->Name,PropName)==0)
00268 IsIn = true;
00269
00270 if( !IsIn )
00271 {
00272 PropertySpec temp;
00273 temp.Name = PropName;
00274 temp.Offset = (short) ((char*)Prop - (char*)container);
00275 temp.Group = PropertyGroup;
00276 temp.Type = Type;
00277 temp.Docu = PropertyDocu;
00278 propertyData.push_back(temp);
00279 }
00280 }
00281
00282 const PropertyData::PropertySpec *PropertyData::findProperty(const PropertyContainer *container,const char* PropName) const
00283 {
00284 for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
00285 if(strcmp(It->Name,PropName)==0)
00286 return &(*It);
00287
00288 if(parentPropertyData)
00289 return parentPropertyData->findProperty(container,PropName);
00290
00291 return 0;
00292 }
00293
00294 const PropertyData::PropertySpec *PropertyData::findProperty(const PropertyContainer *container,const Property* prop) const
00295 {
00296 const int diff = (int) ((char*)prop - (char*)container);
00297
00298 for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
00299 if(diff == It->Offset)
00300 return &(*It);
00301
00302 if(parentPropertyData)
00303 return parentPropertyData->findProperty(container,prop);
00304
00305 return 0;
00306 }
00307
00308 const char* PropertyData::getName(const PropertyContainer *container,const Property* prop) const
00309 {
00310 const PropertyData::PropertySpec* Spec = findProperty(container,prop);
00311
00312 if(Spec)
00313 return Spec->Name;
00314 else
00315 return 0;
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 }
00328
00329 short PropertyData::getType(const PropertyContainer *container,const Property* prop) const
00330 {
00331 const PropertyData::PropertySpec* Spec = findProperty(container,prop);
00332
00333 if(Spec)
00334 return Spec->Type;
00335 else
00336 return 0;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 }
00351
00352 short PropertyData::getType(const PropertyContainer *container,const char* name) const
00353 {
00354 const PropertyData::PropertySpec* Spec = findProperty(container,name);
00355
00356 if(Spec)
00357 return Spec->Type;
00358 else
00359 return 0;
00360 }
00361
00362 const char* PropertyData::getGroup(const PropertyContainer *container,const Property* prop) const
00363 {
00364 const PropertyData::PropertySpec* Spec = findProperty(container,prop);
00365
00366 if(Spec)
00367 return Spec->Group;
00368 else
00369 return 0;
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 }
00384
00385 const char* PropertyData::getGroup(const PropertyContainer *container,const char* name) const
00386 {
00387 const PropertyData::PropertySpec* Spec = findProperty(container,name);
00388
00389 if(Spec)
00390 return Spec->Group;
00391 else
00392 return 0;
00393 }
00394
00395 const char* PropertyData::getDocumentation(const PropertyContainer *container,const Property* prop) const
00396 {
00397 const PropertyData::PropertySpec* Spec = findProperty(container,prop);
00398
00399 if(Spec)
00400 return Spec->Docu;
00401 else
00402 return 0;
00403 }
00404
00405 const char* PropertyData::getDocumentation(const PropertyContainer *container,const char* name) const
00406 {
00407 const PropertyData::PropertySpec* Spec = findProperty(container,name);
00408
00409 if(Spec)
00410 return Spec->Docu;
00411 else
00412 return 0;
00413 }
00414
00415
00416
00417 Property *PropertyData::getPropertyByName(const PropertyContainer *container,const char* name) const
00418 {
00419 const PropertyData::PropertySpec* Spec = findProperty(container,name);
00420
00421 if(Spec)
00422 return (Property *) (Spec->Offset + (char *)container);
00423 else
00424 return 0;
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 }
00439
00440 void PropertyData::getPropertyMap(const PropertyContainer *container,std::map<std::string,Property*> &Map) const
00441 {
00442 for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
00443 Map[It->Name] = (Property *) (It->Offset + (char *)container);
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 if(parentPropertyData)
00454 parentPropertyData->getPropertyMap(container,Map);
00455
00456 }
00457
00458 void PropertyData::getPropertyList(const PropertyContainer *container,std::vector<Property*> &List) const
00459 {
00460 for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
00461 List.push_back((Property *) (It->Offset + (char *)container) );
00462
00463
00464
00465
00466
00467
00468
00469 if(parentPropertyData)
00470 parentPropertyData->getPropertyList(container,List);
00471
00472 }
00473
00474
00475