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 #ifndef _PreComp_
00026 # include <algorithm>
00027 #endif
00028
00029 #include "DynamicProperty.h"
00030 #include "Property.h"
00031 #include "PropertyContainer.h"
00032 #include <Base/Reader.h>
00033 #include <Base/Writer.h>
00034 #include <Base/Console.h>
00035 #include <Base/Exception.h>
00036 #include <Base/Tools.h>
00037
00038
00039 using namespace App;
00040
00041
00042 DynamicProperty::DynamicProperty(PropertyContainer* p) : pc(p)
00043 {
00044 }
00045
00046 DynamicProperty::~DynamicProperty()
00047 {
00048 }
00049
00050 void DynamicProperty::getPropertyList(std::vector<Property*> &List) const
00051 {
00052
00053 this->pc->PropertyContainer::getPropertyList(List);
00054 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it)
00055 List.push_back(it->second.property);
00056 }
00057
00058 void DynamicProperty::getPropertyMap(std::map<std::string,Property*> &Map) const
00059 {
00060
00061 this->pc->PropertyContainer::getPropertyMap(Map);
00062 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it)
00063 Map[it->first] = it->second.property;
00064 }
00065
00066 Property *DynamicProperty::getPropertyByName(const char* name) const
00067 {
00068 std::map<std::string,PropData>::const_iterator it = props.find(name);
00069 if (it != props.end())
00070 return it->second.property;
00071 return this->pc->PropertyContainer::getPropertyByName(name);
00072 }
00073
00074 Property *DynamicProperty::getDynamicPropertyByName(const char* name) const
00075 {
00076 std::map<std::string,PropData>::const_iterator it = props.find(name);
00077 if (it != props.end())
00078 return it->second.property;
00079 return 0;
00080 }
00081
00082 std::vector<std::string> DynamicProperty::getDynamicPropertyNames() const
00083 {
00084 std::vector<std::string> names;
00085 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00086 names.push_back(it->first);
00087 }
00088 return names;
00089 }
00090
00091 void DynamicProperty::addDynamicProperties(const PropertyContainer* cont)
00092 {
00093 std::vector<std::string> names = cont->getDynamicPropertyNames();
00094 for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); ++it) {
00095 App::Property* prop = cont->getDynamicPropertyByName(it->c_str());
00096 if (prop) {
00097 addDynamicProperty(
00098 prop->getTypeId().getName(),
00099 prop->getName(),
00100 prop->getGroup(),
00101 prop->getDocumentation(),
00102 prop->getType(),
00103 cont->isReadOnly(prop),
00104 cont->isHidden(prop));
00105 }
00106 }
00107 }
00108
00109 const char* DynamicProperty::getName(const Property* prop) const
00110 {
00111 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00112 if (it->second.property == prop)
00113 return it->first.c_str();
00114 }
00115 return this->pc->PropertyContainer::getName(prop);
00116 }
00117
00118 unsigned int DynamicProperty::getMemSize (void) const
00119 {
00120 std::map<std::string,Property*> Map;
00121 getPropertyMap(Map);
00122 std::map<std::string,Property*>::const_iterator It;
00123 unsigned int size = 0;
00124 for (It = Map.begin(); It != Map.end();++It)
00125 size += It->second->getMemSize();
00126 return size;
00127 }
00128
00129 short DynamicProperty::getPropertyType(const Property* prop) const
00130 {
00131 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00132 if (it->second.property == prop)
00133 return it->second.attr;
00134 }
00135 return this->pc->PropertyContainer::getPropertyType(prop);
00136 }
00137
00138 short DynamicProperty::getPropertyType(const char *name) const
00139 {
00140 std::map<std::string,PropData>::const_iterator it = props.find(name);
00141 if (it != props.end())
00142 return it->second.attr;
00143 return this->pc->PropertyContainer::getPropertyType(name);
00144 }
00145
00146 const char* DynamicProperty::getPropertyGroup(const Property* prop) const
00147 {
00148 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00149 if (it->second.property == prop)
00150 return it->second.group.c_str();
00151 }
00152 return this->pc->PropertyContainer::getPropertyGroup(prop);
00153 }
00154
00155 const char* DynamicProperty::getPropertyGroup(const char *name) const
00156 {
00157 std::map<std::string,PropData>::const_iterator it = props.find(name);
00158 if (it != props.end())
00159 return it->second.group.c_str();
00160 return this->pc->PropertyContainer::getPropertyGroup(name);
00161 }
00162
00163 const char* DynamicProperty::getPropertyDocumentation(const Property* prop) const
00164 {
00165 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00166 if (it->second.property == prop)
00167 return it->second.doc.c_str();
00168 }
00169 return this->pc->PropertyContainer::getPropertyDocumentation(prop);
00170 }
00171
00172 const char* DynamicProperty::getPropertyDocumentation(const char *name) const
00173 {
00174 std::map<std::string,PropData>::const_iterator it = props.find(name);
00175 if (it != props.end())
00176 return it->second.doc.c_str();
00177 return this->pc->PropertyContainer::getPropertyDocumentation(name);
00178 }
00179
00180 bool DynamicProperty::isReadOnly(const Property* prop) const
00181 {
00182 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00183 if (it->second.property == prop)
00184 return it->second.readonly;
00185 }
00186 return this->pc->PropertyContainer::isReadOnly(prop);
00187 }
00188
00189 bool DynamicProperty::isReadOnly(const char *name) const
00190 {
00191 std::map<std::string,PropData>::const_iterator it = props.find(name);
00192 if (it != props.end())
00193 return it->second.readonly;
00194 return this->pc->PropertyContainer::isReadOnly(name);
00195 }
00196
00197 bool DynamicProperty::isHidden(const Property* prop) const
00198 {
00199 for (std::map<std::string,PropData>::const_iterator it = props.begin(); it != props.end(); ++it) {
00200 if (it->second.property == prop)
00201 return it->second.hidden;
00202 }
00203 return this->pc->PropertyContainer::isHidden(prop);
00204 }
00205
00206 bool DynamicProperty::isHidden(const char *name) const
00207 {
00208 std::map<std::string,PropData>::const_iterator it = props.find(name);
00209 if (it != props.end())
00210 return it->second.hidden;
00211 return this->pc->PropertyContainer::isHidden(name);
00212 }
00213
00214 Property* DynamicProperty::addDynamicProperty(const char* type, const char* name, const char* group,
00215 const char* doc, short attr, bool ro, bool hidden)
00216 {
00217 Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(type,true));
00218 if (!base)
00219 return 0;
00220 if (!base->getTypeId().isDerivedFrom(Property::getClassTypeId())) {
00221 delete base;
00222 std::stringstream str;
00223 str << "'" << type << "' is not a property type";
00224 throw Base::Exception(str.str());
00225 }
00226
00227
00228 Property* pcProperty = static_cast<Property*>(base);
00229 std::string ObjectName;
00230 if (name && *name != '\0')
00231 ObjectName = getUniquePropertyName(name);
00232 else
00233 ObjectName = getUniquePropertyName(type);
00234
00235 pcProperty->setContainer(this->pc);
00236 PropData data;
00237 data.property = pcProperty;
00238 data.group = (group ? group : "");
00239 data.doc = (doc ? doc : "");
00240 data.attr = attr;
00241 data.readonly = ro;
00242 data.hidden = hidden;
00243 props[ObjectName] = data;
00244
00245 return pcProperty;
00246 }
00247
00248 std::string DynamicProperty::getUniquePropertyName(const char *Name) const
00249 {
00250 std::string CleanName = Base::Tools::getIdentifier(Name);
00251
00252
00253 std::map<std::string,Property*> objectProps;
00254 getPropertyMap(objectProps);
00255 std::map<std::string,Property*>::const_iterator pos;
00256 pos = objectProps.find(CleanName);
00257
00258 if (pos == objectProps.end()) {
00259
00260 return CleanName;
00261 }
00262 else {
00263 std::vector<std::string> names;
00264 names.reserve(objectProps.size());
00265 for (pos = objectProps.begin();pos != objectProps.end();++pos) {
00266 names.push_back(pos->first);
00267 }
00268 return Base::Tools::getUniqueName(CleanName, names);
00269 }
00270 }
00271
00272 std::string DynamicProperty::encodeAttribute(const std::string& str) const
00273 {
00274 std::string tmp;
00275 for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
00276 if (*it == '<')
00277 tmp += "<";
00278 else if (*it == '"')
00279 tmp += """;
00280 else if (*it == '&')
00281 tmp += "&";
00282 else if (*it == '>')
00283 tmp += ">";
00284 else if (*it == '\n')
00285 tmp += " ";
00286 else
00287 tmp += *it;
00288 }
00289
00290 return tmp;
00291 }
00292
00293 void DynamicProperty::Save (Base::Writer &writer) const
00294 {
00295 std::map<std::string,Property*> Map;
00296 getPropertyMap(Map);
00297
00298 writer.incInd();
00299 writer.Stream() << writer.ind() << "<Properties Count=\"" << Map.size() << "\">" << std::endl;
00300 std::map<std::string,Property*>::iterator it;
00301 for (it = Map.begin(); it != Map.end(); ++it)
00302 {
00303 writer.incInd();
00304
00305 std::map<std::string,PropData>::const_iterator pt = props.find(it->first);
00306 if (pt == props.end()) {
00307 writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\""
00308 << it->second->getTypeId().getName() << "\">" << std::endl;
00309 }
00310 else {
00311 writer.Stream() << writer.ind() << "<Property name=\"" << it->first
00312 << "\" type=\"" << it->second->getTypeId().getName()
00313 << "\" group=\"" << encodeAttribute(pt->second.group)
00314 << "\" doc=\"" << encodeAttribute(pt->second.doc)
00315 << "\" attr=\"" << pt->second.attr << "\" ro=\"" << pt->second.readonly
00316 << "\" hide=\"" << pt->second.hidden << "\">" << std::endl;
00317 }
00318
00319 writer.incInd();
00320 try {
00321
00322
00323
00324 it->second->Save(writer);
00325 }
00326 catch (const Base::Exception &e) {
00327 Base::Console().Error("%s\n", e.what());
00328 }
00329 catch (const std::exception &e) {
00330 Base::Console().Error("%s\n", e.what());
00331 }
00332 catch (const char* e) {
00333 Base::Console().Error("%s\n", e);
00334 }
00335 #ifndef FC_DEBUG
00336 catch (...) {
00337 Base::Console().Error("DynamicProperty::Save: Unknown C++ exception thrown. Try to continue...\n");
00338 }
00339 #endif
00340 writer.decInd();
00341 writer.Stream() << writer.ind() << "</Property>" << std::endl;
00342 writer.decInd();
00343 }
00344 writer.Stream() << writer.ind() << "</Properties>" << std::endl;
00345 writer.decInd();
00346 }
00347
00348 void DynamicProperty::Restore(Base::XMLReader &reader)
00349 {
00350 reader.readElement("Properties");
00351 int Cnt = reader.getAttributeAsInteger("Count");
00352
00353 for (int i=0 ;i<Cnt ;i++) {
00354 reader.readElement("Property");
00355 const char* PropName = reader.getAttribute("name");
00356 const char* TypeName = reader.getAttribute("type");
00357 Property* prop = getPropertyByName(PropName);
00358 try {
00359 if (!prop) {
00360 short attribute = 0;
00361 bool readonly = false, hidden = false;
00362 const char *group=0, *doc=0, *attr=0, *ro=0, *hide=0;
00363 if (reader.hasAttribute("group"))
00364 group = reader.getAttribute("group");
00365 if (reader.hasAttribute("doc"))
00366 doc = reader.getAttribute("doc");
00367 if (reader.hasAttribute("attr")) {
00368 attr = reader.getAttribute("attr");
00369 if (attr) attribute = attr[0]-48;
00370 }
00371 if (reader.hasAttribute("ro")) {
00372 ro = reader.getAttribute("ro");
00373 if (ro) readonly = (ro[0]-48) != 0;
00374 }
00375 if (reader.hasAttribute("hide")) {
00376 hide = reader.getAttribute("hide");
00377 if (hide) hidden = (hide[0]-48) != 0;
00378 }
00379 prop = addDynamicProperty(TypeName, PropName, group, doc, attribute, readonly, hidden);
00380 }
00381 }
00382 catch(const Base::Exception& e) {
00383
00384 Base::Console().Warning(e.what());
00385 }
00386
00387
00388
00389
00390
00391 if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0)
00392 prop->Restore(reader);
00393 else if (prop)
00394 Base::Console().Warning("%s: Overread data for property %s of type %s, expected type is %s\n",
00395 pc->getTypeId().getName(), prop->getName(), prop->getTypeId().getName(), TypeName);
00396 else
00397 Base::Console().Warning("%s: No property found with name %s and type %s\n",
00398 pc->getTypeId().getName(), PropName, TypeName);
00399 reader.readEndElement("Property");
00400 }
00401
00402 reader.readEndElement("Properties");
00403 }