Issue #2389: ObjectIdentifiers constructed from a property sometimes do not
resolve correctly, because the resolver may fail if a different document objects has a Label equal to the property's document object's identifier.
This commit is contained in:
parent
d53cb8146e
commit
3aa44e6b0c
|
@ -117,13 +117,24 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, const
|
|||
, documentObjectNameSet(false)
|
||||
, propertyIndex(-1)
|
||||
{
|
||||
if (owner) {
|
||||
const DocumentObject * docObj = freecad_dynamic_cast<const DocumentObject>(owner);
|
||||
if (!docObj)
|
||||
throw Base::Exception("Property must be owned by a document object.");
|
||||
|
||||
const Document * doc = docObj->getDocument();
|
||||
|
||||
documentName = String(doc->getName(), false, true);
|
||||
documentObjectName = String(docObj->getNameInDocument(), false, true);
|
||||
|
||||
}
|
||||
if (property.size() > 0)
|
||||
addComponent(Component::SimpleComponent(property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct an ObjectIdentifier object given a property. The property is assumed to be single-valued.
|
||||
* @param prop Property to construct object idenfier for.
|
||||
* @param prop Property to construct object identifier for.
|
||||
*/
|
||||
|
||||
ObjectIdentifier::ObjectIdentifier(const Property &prop)
|
||||
|
@ -132,6 +143,16 @@ ObjectIdentifier::ObjectIdentifier(const Property &prop)
|
|||
, documentObjectNameSet(false)
|
||||
, propertyIndex(-1)
|
||||
{
|
||||
DocumentObject * docObj = freecad_dynamic_cast<DocumentObject>(prop.getContainer());
|
||||
|
||||
if (!docObj)
|
||||
throw Base::Exception("Property must be owned by a document object.");
|
||||
|
||||
Document * doc = docObj->getDocument();
|
||||
|
||||
documentName = String(doc->getName(), false, true);
|
||||
documentObjectName = String(docObj->getNameInDocument(), false, true);
|
||||
|
||||
addComponent(Component::SimpleComponent(String(owner->getPropertyName(&prop))));
|
||||
}
|
||||
|
||||
|
@ -508,32 +529,35 @@ std::string ObjectIdentifier::Component::toString() const
|
|||
* @return Pointer to document object if a unique pointer is found, 0 otherwise.
|
||||
*/
|
||||
|
||||
App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * doc, const std::string & name) const
|
||||
App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * doc, const String & name) const
|
||||
{
|
||||
DocumentObject * o1 = 0;
|
||||
DocumentObject * o2 = 0;
|
||||
DocumentObject * objectById = 0;
|
||||
DocumentObject * objectByLabel = 0;
|
||||
std::vector<DocumentObject*> docObjects = doc->getObjects();
|
||||
|
||||
// No object found with matching label, try using name directly
|
||||
objectById = doc->getObject(static_cast<const char*>(name));
|
||||
|
||||
if (name.isForceIdentifier())
|
||||
return objectById;
|
||||
|
||||
for (std::vector<DocumentObject*>::iterator j = docObjects.begin(); j != docObjects.end(); ++j) {
|
||||
if (strcmp((*j)->Label.getValue(), name.c_str()) == 0) {
|
||||
if (strcmp((*j)->Label.getValue(), static_cast<const char*>(name)) == 0) {
|
||||
// Found object with matching label
|
||||
if (o1 != 0)
|
||||
if (objectByLabel != 0)
|
||||
return 0;
|
||||
o1 = *j;
|
||||
objectByLabel = *j;
|
||||
}
|
||||
}
|
||||
|
||||
// No object found with matching label, try using name directly
|
||||
o2 = doc->getObject(name.c_str());
|
||||
|
||||
if (o1 == 0 && o2 == 0) // Not found at all
|
||||
if (objectByLabel == 0 && objectById == 0) // Not found at all
|
||||
return 0;
|
||||
else if (o1 == 0) // Found by name
|
||||
return o2;
|
||||
else if (o2 == 0) // Found by label
|
||||
return o1;
|
||||
else if (o1 == o2) // Found by both name and label, same object
|
||||
return o1;
|
||||
else if (objectByLabel == 0) // Found by name
|
||||
return objectById;
|
||||
else if (objectById == 0) // Found by label
|
||||
return objectByLabel;
|
||||
else if (objectByLabel == objectById) // Found by both name and label, same object
|
||||
return objectByLabel;
|
||||
else
|
||||
return 0; // Found by both name and label, two different objects
|
||||
}
|
||||
|
@ -574,11 +598,11 @@ void ObjectIdentifier::resolve() const
|
|||
}
|
||||
}
|
||||
|
||||
documentName = String(doc->getName());
|
||||
documentName = String(doc->getName(), false, documentName.isForceIdentifier());
|
||||
|
||||
/* Document object name specified? */
|
||||
if (documentObjectNameSet) {
|
||||
docObject = getDocumentObject(doc, documentObjectName.getString());
|
||||
docObject = getDocumentObject(doc, documentObjectName);
|
||||
if (!docObject)
|
||||
return;
|
||||
if (components.size() > 0) {
|
||||
|
@ -591,7 +615,7 @@ void ObjectIdentifier::resolve() const
|
|||
else {
|
||||
/* Document object name not specified, resolve from path */
|
||||
if (components.size() == 1) {
|
||||
documentObjectName = String(static_cast<const DocumentObject*>(owner)->getNameInDocument());
|
||||
documentObjectName = String(static_cast<const DocumentObject*>(owner)->getNameInDocument(), false, documentObjectName.isForceIdentifier());
|
||||
propertyName = components[0].name.getString();
|
||||
propertyIndex = 0;
|
||||
}
|
||||
|
@ -602,12 +626,12 @@ void ObjectIdentifier::resolve() const
|
|||
docObject = getDocumentObject(doc, components[0].name);
|
||||
|
||||
if (docObject) {
|
||||
documentObjectName = components[0].name;
|
||||
documentObjectName = String(components[0].name, false, documentObjectName.isForceIdentifier());
|
||||
propertyName = components[1].name.getString();
|
||||
propertyIndex = 1;
|
||||
}
|
||||
else {
|
||||
documentObjectName = String(static_cast<const DocumentObject*>(owner)->getNameInDocument());
|
||||
documentObjectName = String(static_cast<const DocumentObject*>(owner)->getNameInDocument(), false, documentObjectName.isForceIdentifier());
|
||||
propertyName = components[0].name.getString();
|
||||
propertyIndex = 0;
|
||||
}
|
||||
|
@ -629,6 +653,10 @@ Document * ObjectIdentifier::getDocument(String name) const
|
|||
name = getDocumentName();
|
||||
|
||||
App::Document * docById = App::GetApplication().getDocument(name);
|
||||
|
||||
if (name.isForceIdentifier())
|
||||
return docById;
|
||||
|
||||
App::Document * docByLabel = 0;
|
||||
const std::vector<App::Document*> docs = App::GetApplication().getDocuments();
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
public:
|
||||
|
||||
// Constructor
|
||||
String(const std::string & s = "", bool _isRealString = false) : str(s), isString(_isRealString) { }
|
||||
String(const std::string & s = "", bool _isRealString = false, bool _forceIdentifier = false) : str(s), isString(_isRealString), forceIdentifier(_forceIdentifier) { }
|
||||
|
||||
// Accessors
|
||||
|
||||
|
@ -57,6 +57,8 @@ public:
|
|||
/** Return true is string need to be quoted */
|
||||
bool isRealString() const { return isString; }
|
||||
|
||||
bool isForceIdentifier() const { return forceIdentifier; }
|
||||
|
||||
/** Returns a possibly quoted string */
|
||||
std::string toString() const;
|
||||
|
||||
|
@ -80,6 +82,8 @@ public:
|
|||
|
||||
std::string str;
|
||||
bool isString;
|
||||
bool forceIdentifier;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -227,7 +231,7 @@ protected:
|
|||
|
||||
void resolve() const;
|
||||
|
||||
App::DocumentObject *getDocumentObject(const App::Document *doc, const std::string &name) const;
|
||||
App::DocumentObject *getDocumentObject(const App::Document *doc, const String &name) const;
|
||||
|
||||
const App::PropertyContainer * owner;
|
||||
bool documentNameSet;
|
||||
|
|
Loading…
Reference in New Issue
Block a user