Ejemplo n.º 1
0
void VisualizationPanel::onPropertySelected( wxPropertyGridEvent& event )
{
  wxPGProperty* pg_property = event.GetProperty();

  selected_display_ = NULL;

  if ( !pg_property )
  {
    return;
  }

  void* client_data = pg_property->GetClientData();
  if ( client_data )
  {
    PropertyBase* property = reinterpret_cast<PropertyBase*>(client_data);

    void* user_data = property->getUserData();
    if ( user_data )
    {
      Display* display = reinterpret_cast<Display*>(user_data);

      if ( manager_->isValidDisplay( display ) )
      {
        selected_display_ = display;
      }
    }
  }
}
char* tlp_cc tpGetPropertyType(TELHandle handle)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        return tlp::createText(para->getType());
    catch_ptr_macro
}
void* tlp_cc tpGetPropertyValueHandle(TELHandle handle)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        return para->getValueHandle();
    catch_ptr_macro
}
Ejemplo n.º 4
0
PropertyBase * Entity::setAttr(const std::string & name, const Element & attr)
{
    PropertyBase * prop;
    // If it is an existing property, just update the value.
    PropertyDict::const_iterator I = m_properties.find(name);
    if (I != m_properties.end()) {
        prop = I->second;
        // Mark it as unclean
        prop->resetFlags(per_clean);
    } else {
        PropertyDict::const_iterator I;
        if (m_type != 0 &&
            (I = m_type->defaults().find(name)) != m_type->defaults().end()) {
            prop = I->second->copy();
        } else {
            // This is an entirely new property, not just a modifcation of
            // one in defaults, so we need to install it to this Entity.
            prop = PropertyManager::instance()->addProperty(name,
                                                            attr.getType());
            prop->install(this, name);
        }
        assert(prop != 0);
        m_properties[name] = prop;
    }

    prop->set(attr);
    // Allow the value to take effect.
    prop->apply(this);
    // Mark the Entity as unclean
    resetFlags(entity_clean);
    return prop;
}
bool tlp_cc tpSetPropertyHint(TELHandle handle, const char* value)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        para->setHint(string(value));
        return true;
    catch_bool_macro
}
char* tlp_cc tpGetPropertyValueAsString(TELHandle handle)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        string val = para->getValueAsString();
        return tlp::createText(val);
    catch_ptr_macro
}
char* tlp_cc tpGetPropertyInfo(TELHandle handle)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        stringstream s;
        s<<"Name="<<para->getName()<<"\tType="<<para->getType()<<"\tDescription="<<para->getDescription()<<"\tHint="<<para->getHint();
        return tlp::createText(s.str());
    catch_ptr_macro
}
Ejemplo n.º 8
0
static int Entity_setattro(PyEntity *self, PyObject *oname, PyObject *v)
{
#ifndef NDEBUG
    if (self->m_entity.e == NULL) {
        PyErr_SetString(PyExc_AssertionError, "NULL entity in Entity.setattr");
        return -1;
    }
#endif // NDEBUG
    char * name = PyString_AsString(oname);
    if (strcmp(name, "map") == 0) {
        PyErr_SetString(PyExc_AttributeError, "map attribute forbidden");
        return -1;
    }
    Entity * entity = self->m_entity.e;
    //std::string attr(name);
    //if (v == NULL) {
        //entity->attributes.erase(attr);
        //return 0;
    //}
    if (strcmp(name, "type") == 0) {
        if (entity->getType() != 0) {
            PyErr_SetString(PyExc_RuntimeError, "Cannot mutate entity type");
            return -1;
        }
        if (!PyString_CheckExact(v)) {
            PyErr_SetString(PyExc_TypeError, "No string type");
            return -1;
        }
        const TypeNode * type = Inheritance::instance().getType(PyString_AsString(v));
        if (type == 0) {
            PyErr_SetString(PyExc_RuntimeError, "Entity type unknown");
            return -1;
        }
        entity->setType(type);
        return 0;
    }
    Element obj;
    if (PyObject_asMessageElement(v, obj) == 0) {
        PropertyBase * p = entity->setAttr(name, obj);
        if (p != 0) {
            p->setFlags(flag_unsent);
        }
        return 0;
    }
    // FIXME In fact it seems that nothing currently hits this bit, so
    // all this code is redundant for entity scripts.
    // If we get here, then the attribute is not Atlas compatable, so we
    // need to store it in a python dictionary
    if (self->Entity_attr == NULL) {
        self->Entity_attr = PyDict_New();
        if (self->Entity_attr == NULL) {
            return -1;
        }
    }
    return PyDict_SetItemString(self->Entity_attr, name, v);
}
Ejemplo n.º 9
0
void StorageManager::updateEntity(LocatedEntity * ent)
{
    std::string location;
    Atlas::Message::MapType map;
    map["pos"] = ent->m_location.pos().toAtlas();
    if (ent->m_location.orientation().isValid()) {
        map["orientation"] = ent->m_location.orientation().toAtlas();
    }
    Database::instance()->encodeObject(map, location);

    //Under normal circumstances only the top world won't have a location.
    if (ent->m_location.m_loc) {
        Database::instance()->updateEntity(ent->getId(),
                                       ent->getSeq(),
                                       location,
                                       ent->m_location.m_loc->getId());
    } else {
        Database::instance()->updateEntityWithoutLoc(ent->getId(),
                                       ent->getSeq(),
                                       location);
    }
    ++m_updateEntityCount;
    KeyValues new_property_tuples;
    KeyValues upd_property_tuples;
    const PropertyDict & properties = ent->getProperties();
    PropertyDict::const_iterator I = properties.begin();
    PropertyDict::const_iterator Iend = properties.end();
    for (; I != Iend; ++I) {
        PropertyBase * prop = I->second;
        if (prop->flags() & per_mask) {
            continue;
        }
        // FIXME check if this is new or just modded.
        if (prop->flags() & per_seen) {
            encodeProperty(prop, upd_property_tuples[I->first]);
            ++m_updatePropertyCount;
        } else {
            encodeProperty(prop, new_property_tuples[I->first]);
            ++m_insertPropertyCount;
        }
        prop->setFlags(per_clean | per_seen);
    }
    if (!new_property_tuples.empty()) {
        Database::instance()->insertProperties(ent->getId(),
                                               new_property_tuples);
    }
    if (!upd_property_tuples.empty()) {
        Database::instance()->updateProperties(ent->getId(),
                                               upd_property_tuples);
    }
    ent->setFlags(entity_clean);
}
bool tlp_cc tpSetPropertyByString(TELHandle handle, const char* value)
{
    start_try
        PropertyBase* para = castHandle<PropertyBase>(handle, __FUNC__);
        if(value)
        {
            string val(value);
            para->setValueFromString(val);
            return true;
        }
        return false;
    catch_bool_macro
}
Ejemplo n.º 11
0
void PropertyExerciser::testAdd(PropertyBase & property,
                                Element::Type element_type)
{
    Anonymous add_target;
    MapType add_target2;
    std::vector<StringType>::const_iterator I = string_values.begin();
    std::vector<StringType>::const_iterator Iend = string_values.end();
    for (; I != Iend; ++I) {
        property.add(*I, add_target);
        property.add(*I, add_target2);
    }

}
Ejemplo n.º 12
0
void TypeNode::addProperties(const MapType & attributes)
{
    MapType::const_iterator J = attributes.begin();
    MapType::const_iterator Jend = attributes.end();
    PropertyBase * p;
    for (; J != Jend; ++J) {
        p = PropertyManager::instance()->addProperty(J->first,
                                                     J->second.getType());
        assert(p != 0);
        p->set(J->second);
        p->setFlags(flag_class);
        m_defaults[J->first] = p;
    }
}
Ejemplo n.º 13
0
void* Plugin::getPropertyValueHandle(const string& propName)
{
    PropertyBase* prop =  mProperties.getProperty(propName);
    if(prop)
    {
        return prop->getValueHandle();
    }
    else
    {
        stringstream str;
        str<<"No property with name: "<<propName;
        throw(Exception(str.str()));
    }
}
Ejemplo n.º 14
0
void Entitytest::test_setAttr_new()
{
    ASSERT_TRUE(!m_TestProperty_install_called);

    PropertyBase * pb = m_entity->setAttr("test_int_property", 24);
    ASSERT_NOT_NULL(pb);

    ASSERT_TRUE((pb->flags() & flag_class) == 0);

    auto * int_property = dynamic_cast<TestProperty *>(pb);
    ASSERT_NOT_NULL(int_property);
    ASSERT_EQUAL(int_property->data(), 24);
    ASSERT_TRUE(m_TestProperty_install_called);
    ASSERT_TRUE(m_TestProperty_apply_called);
}
Ejemplo n.º 15
0
static PyObject * add_properties(PyObject * self, PyEntity * o)
{
    if (!PyEntity_Check(o)) {
        PyErr_SetString(PyExc_TypeError, "Unknown Object type");
        return NULL;
    }

    Entity * ent = o->m_entity.e;
    
    PropertyBase * p = ent->setProperty("terrain", new TerrainProperty);
    p->install(ent, "terrain");
    p->apply(ent);

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 16
0
 bool PropertyBag::addProperty(PropertyBase& p)
 {
     if (&p == 0)
         return false;
     if ( ! p.ready() )
         return false;
     mproperties.push_back(&p);
     return true;
 }
Ejemplo n.º 17
0
void StatisicsPropertyintegration::setup()
{
    m_char_type = new TypeNode("char_type");

    m_char_property = new StatisticsProperty;
    m_char_property->setFlags(flag_class);
    m_char_type->addProperty("char_prop", m_char_property);

    m_char1 = new Entity("1", 1);
    m_char1->setType(m_char_type);
    m_char_property->install(m_char1, "char_prop");
    m_char_property->apply(m_char1);

    m_char2 = new Entity("2", 2);
    m_char2->setType(m_char_type);
    m_char_property->install(m_char2, "char_prop");
    m_char_property->apply(m_char2);
}
Ejemplo n.º 18
0
void PropertyExerciser::testGet(PropertyBase & property, 
                                Element::Type element_type)
{
    Element get_target;
    if (property.get(get_target)) {
        assert(get_target.getType() == element_type);
    } else {
        assert(get_target.getType() == Element::TYPE_NONE);
    }
}
Ejemplo n.º 19
0
void Entitytest::test_setAttr_type()
{
    TestProperty * type_property = new TestProperty;
    type_property->data() = 17;
    type_property->flags() &= flag_class;
    m_type->addProperty("test_int_property", type_property);

    PropertyBase * pb = m_entity->setAttr("test_int_property", 24);
    ASSERT_NOT_NULL(pb);
    ASSERT_NOT_EQUAL(type_property, pb);

    ASSERT_TRUE((pb->flags() & flag_class) == 0);

    auto * int_property = dynamic_cast<TestProperty *>(pb);
    ASSERT_NOT_NULL(int_property);
    ASSERT_EQUAL(int_property->data(), 24);
    ASSERT_TRUE(!m_TestProperty_install_called);
    ASSERT_TRUE(m_TestProperty_apply_called);
}
Ejemplo n.º 20
0
HandlerResult Entity::callDelegate(const std::string & name,
                                   const Operation & op,
                                   OpVector & res)
{
    PropertyBase * p = 0;
    PropertyDict::const_iterator I = m_properties.find(name);
    if (I != m_properties.end()) {
        p = I->second;
    } else if (m_type != 0) {
        I = m_type->defaults().find(name); 
        if (I != m_type->defaults().end()) {
            p = I->second;
        }
    }
    if (p != 0) {
        return p->operation(this, op, res);
    }
    return OPERATION_IGNORED;
}
Ejemplo n.º 21
0
void GenericDirCtrlWrapper::LoadPropertiesFromwxFB(const wxXmlNode* node)
{
    // First call the base-class for the standard things
    wxcWidget::LoadPropertiesFromwxFB(node);

    wxXmlNode* propertynode = XmlUtils::FindNodeByName(node, "property", "defaultfolder");
    if(propertynode) { SetPropertyString(PROP_DEFAULT_FOLDER, propertynode->GetNodeContent()); }

    propertynode = XmlUtils::FindNodeByName(node, "property", "filter");
    if(propertynode) { SetPropertyString(PROP_FILTER, propertynode->GetNodeContent()); }

    propertynode = XmlUtils::FindNodeByName(node, "property", "defaultfilter");
    if(propertynode) { SetPropertyString(PROP_DEFAULT_FILTER, propertynode->GetNodeContent()); }

    propertynode = XmlUtils::FindNodeByName(node, "property", "show_hidden");
    if(propertynode) {
        PropertyBase* prop = GetProperty(PROP_SHOW_HIDDEN);
        if(prop) { prop->SetValue(propertynode->GetNodeContent()); }
    }
}
Ejemplo n.º 22
0
void PropertyExerciser::testSetByType(PropertyBase & property,
                                      Element::Type element_type,
                                      const std::vector<T> & values)
{
    typename std::vector<T>::const_iterator I = values.begin();
    typename std::vector<T>::const_iterator Iend = values.end();
    for (; I != Iend; ++I) {
        property.set(*I);
        testGet(property, element_type);
        testAdd(property, element_type);
    }
}
Ejemplo n.º 23
0
void AreaPropertyintegration::setup()
{
    m_char_type = new TypeNode("char_type");

    m_char_property = new AreaProperty;
    m_char_property->setFlags(flag_class);
    m_char_property->set(
        MapType{
            std::make_pair("shape", MapType{
                std::make_pair("type", "polygon"),
                std::make_pair("points", ListType(3, ListType(2, 1.f)))
            })
        }
    );
    m_char_type->addProperty("char_type", m_char_property);

    m_char1 = new Entity("1", 1);
    m_char1->setType(m_char_type);
    m_char_property->install(m_char1, "char_prop");
    m_char_property->apply(m_char1);
    m_char1->propertyApplied("char_prop", *m_char_property);

    m_char2 = new Entity("2", 2);
    m_char2->setType(m_char_type);
    m_char_property->install(m_char2, "char_prop");
    m_char_property->apply(m_char2);
    m_char2->propertyApplied("char_prop", *m_char_property);
}
Ejemplo n.º 24
0
void BiomassPropertyintegration::setup()
{
    m_world = new Entity("0", 0);

    m_entity = new Entity("1", 1);
    m_entity->m_location.m_loc = m_world;

    PropertyFactory<BiomassProperty> decays_property_factory;

    m_property = decays_property_factory.newProperty();
    m_property->install(m_entity, "biomass");
    m_entity->setProperty("biomass", m_property);
}
Ejemplo n.º 25
0
    bool composeProperty(const PropertyBag& bag, WeightedSample<T>& weightedSample)
    {
        //log(Debug) << "composeProperty of WeightedSample " << endlog();
        std::string tname = detail::DataSourceTypeInfo<T>::getType();
        if ( bag.getType() == std::string("WeightedSample") ) {
            // Get values of sample
            Property<PropertyBag>* el_bag =  bag.getProperty<PropertyBag>("WeightedSampleValue");

            if(el_bag==NULL){
                // Works for properties in WeightedSample
                PropertyBase* element = bag.getItem( 0 );
                //log(Debug)<<element->getName()<<", "<< element->getDescription()<<endlog();
                Property<T> my_property_t (element->getName(),element->getDescription());
                if(my_property_t.getType()!=element->getType())
                {
                    log(Error)<< "Type of "<< element->getName() << " does not match type of WeightedSample"<< "OR "<<"Could not read WeightedSample Value "<<endlog();
                    return false;
                }
                else{
                    my_property_t.getTypeInfo()->composeType(element->getDataSource(),my_property_t.getDataSource());
                    weightedSample.ValueSet( my_property_t.get());
                }
            }
            else{
                // Works for propertybags in WeightedSample
                const std::string el_bagType = el_bag->getType();
                Property<T > el_p(el_bag->getName(),el_bag->getDescription());
                if(!(el_p.getDataSource()->composeType(el_bag->getDataSource()))){
                    log(Error)<<"Could not compose WeightedSampleValue "<<endlog();
                    return false;
                }
                if(el_p.ready()){
                    weightedSample.ValueSet( el_p.get());
                }else{
                    log(Error)<<"Property of WeightedSampleValue was not ready for use"<<endlog();
                    return false;
                }
            }
            // Get weight of sample
            Property<double>* weightProp =  bag.getProperty<double>("WeightedSampleWeight");

            if(!weightProp)
            {
                log(Error)<< "Error reading weight of WeightedSample"<<endlog();
                return false;
            }
            else{
                weightedSample.WeightSet( weightProp->get());
            }
        }
        else {
            Logger::log() << Logger::Error << "Composing Property< WeightedSample<T> > :"
                          << " type mismatch, got type '"<< bag.getType()
                          << "', expected type "<<tname<<"."<<Logger::endl;
            return false;
        }
        return true;
    };
Ejemplo n.º 26
0
void StorageManager::insertEntity(LocatedEntity * ent)
{
    std::string location;
    Atlas::Message::MapType map;
    map["pos"] = ent->m_location.pos().toAtlas();
    if (ent->m_location.orientation().isValid()) {
        map["orientation"] = ent->m_location.orientation().toAtlas();
    }
    Database::instance()->encodeObject(map, location);

    Database::instance()->insertEntity(ent->getId(),
                                       ent->m_location.m_loc->getId(),
                                       ent->getType()->name(),
                                       ent->getSeq(),
                                       location);
    ++m_insertEntityCount;
    KeyValues property_tuples;
    const PropertyDict & properties = ent->getProperties();
    PropertyDict::const_iterator I = properties.begin();
    PropertyDict::const_iterator Iend = properties.end();
    for (; I != Iend; ++I) {
        PropertyBase * prop = I->second;
        if (prop->flags() & per_ephem) {
            continue;
        }
        encodeProperty(prop, property_tuples[I->first]);
        prop->setFlags(per_clean | per_seen);
    }
    if (!property_tuples.empty()) {
        Database::instance()->insertProperties(ent->getId(), property_tuples);
        ++m_insertPropertyCount;
    }
    ent->resetFlags(entity_queued);
    ent->setFlags(entity_clean | entity_pos_clean | entity_orient_clean);
    ent->updated.connect(sigc::bind(sigc::mem_fun(this, &StorageManager::entityUpdated), ent));
    ent->containered.connect(sigc::bind(sigc::mem_fun(this, &StorageManager::entityContainered), ent));

}
Ejemplo n.º 27
0
void DecaysPropertyintegration::setup()
{
    m_world = new Entity("0", 0);
    new TestWorld(*m_world);

    m_entity = new Entity("1", 1);
    m_entity->m_location.m_loc = m_world;

    PropertyFactory<DecaysProperty> decays_property_factory;

    m_property = decays_property_factory.newProperty();
    m_property->install(m_entity, "decays");
    m_entity->setProperty("decays", m_property);
}
void TerrainModPropertyintegration::setup()
{
    m_world = new Entity("0", 0);

    new TestWorld(*m_world);

    m_entity = new Entity("1", 1);
    m_entity->m_location.m_pos = Point3D(5.f, 5.f, 5.f);
    m_entity->m_location.m_loc = m_world;
    m_world->incRef();
    ASSERT_TRUE(m_entity->m_location.isValid());

    PropertyFactory<TerrainModProperty> terrainmod_property_factory;

    m_terrainProperty = new TerrainProperty;
    m_terrainProperty->install(m_world, "terrain");
    m_world->setProperty("terrain", m_terrainProperty);
    m_terrainProperty->apply(m_world);

    m_property = terrainmod_property_factory.newProperty();
    m_property->install(m_entity, "terrainmod");
    m_entity->setProperty("terrainmod", m_property);
    m_property->apply(m_entity);
}
Ejemplo n.º 29
0
        Py::Object add_properties(const Py::Tuple& args)
        {
            auto ent = CyPy_Entity::value(args.front());

            PropertyBase * p = ent->setProperty("statistics", new StatisticsProperty);
            p->install(ent.get(), "statistics");
            p->apply(ent.get());
            ent->propertyApplied("statistics", *p);
            p = ent->setProperty("terrain", new TerrainProperty);
            p->install(ent.get(), "terrain");
            p->apply(ent.get());
            ent->propertyApplied("terrain", *p);
            p = ent->setProperty("line", new LineProperty);
            p->install(ent.get(), "line");
            p->apply(ent.get());
            ent->propertyApplied("line", *p);

            return Py::None();
        }
Ejemplo n.º 30
0
int main()
{

    {
        // Test constructor
        PropertyBase * pb = new EntityProperty();
        delete pb;
    }

    {
        // Check constructor has set flags correctly to zero
        PropertyBase * pb = new EntityProperty;
        assert(pb->flags().m_flags == 0);
        delete pb;
    }

    {
        // Check getting the value fails when property is unassigned
        Element val;

        PropertyBase * pb = new EntityProperty;
        assert(pb->get(val) == -1);
        delete pb;
    }

    {
        // Check that setting the value to a pointer works
        Entity ent("1", 1);

        PropertyBase * pb = new EntityProperty;
        pb->set(Atlas::Message::Element(&ent));
        delete pb;
    }

    {
        // Check that setting the value to a pointer works can get retrieved
        Entity ent("1", 1);
        Element val;

        PropertyBase * pb = new EntityProperty;
        pb->set(Atlas::Message::Element(&ent));
        assert(pb->get(val) == 0);
        assert(val.isMap());
        assert(val.asMap().find("$eid")->second == ent.getId());
        delete pb;
    }

    {
        // Check that adding the uninitialised value to a message works.
        MapType map;
        static const std::string key = "foo";

        PropertyBase * pb = new EntityProperty;

        MapType::const_iterator I = map.find(key);
        assert(I == map.end());

        pb->add(key, map);

        I = map.find(key);
        assert(I != map.end());
        assert(I->second.isString());
        assert(I->second.String().empty());
        delete pb;
    }

    {
        // Check that adding the uninitialised value to an argument works.
        Anonymous arg;
        static const std::string key = "foo";
        Element val;

        PropertyBase * pb = new EntityProperty;

        assert(!arg->hasAttr(key));
        assert(arg->copyAttr(key, val) != 0);

        pb->add(key, arg);

        assert(arg->hasAttr(key));
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isString());
        assert(val.String().empty());
        delete pb;
    }

    {
        // Check that adding the uninitialised value to an argument as a hard
        // attribute works
        Anonymous arg;
        static const std::string key = "id";
        Element val;

        PropertyBase * pb = new EntityProperty;

        assert(!arg->hasAttr(key));
        // Hard coded attribute ID has not been set, so returns false, but
        // copying it gives us the default
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isString());

        pb->add(key, arg);

        assert(arg->hasAttr(key));
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isString());
        delete pb;
    }

    {
        // Check that adding the value to a message works.
        Entity ent("1", 1);
        MapType map;
        static const std::string key = "foo";

        PropertyBase * pb = new EntityProperty;
        pb->set(Atlas::Message::Element(&ent));

        MapType::const_iterator I = map.find(key);
        assert(I == map.end());

        pb->add(key, map);

        I = map.find(key);
        assert(I != map.end());
        assert(I->second.isMap());
        assert(I->second.asMap().find("$eid")->second == ent.getId());
        delete pb;
    }

    {
        // Check that adding the value to an argument works.
        Entity ent("1", 1);
        Anonymous arg;
        static const std::string key = "foo";
        Element val;

        PropertyBase * pb = new EntityProperty;
        pb->set(Atlas::Message::Element(&ent));

        assert(!arg->hasAttr(key));
        assert(arg->copyAttr(key, val) != 0);

        pb->add(key, arg);

        assert(arg->hasAttr(key));
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isMap());
        assert(val.asMap().find("$eid")->second == ent.getId());
        delete pb;
    }

    {
        // Check that adding the value to an argument as a hard attribute works
        Entity ent("1", 1);
        Anonymous arg;
        static const std::string key = "id";
        Element val;

        PropertyBase * pb = new EntityProperty;
        pb->set(Atlas::Message::Element(&ent));

        assert(!arg->hasAttr(key));
        // Hard coded attribute ID has not been set, so returns false, but
        // copying it gives us the default
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isString());
        assert(val.String() != ent.getId());

        pb->add(key, arg);

        assert(arg->hasAttr(key));
        assert(arg->copyAttr(key, val) == 0);
        assert(val.isString());
        assert(val.String() == ent.getId());
        delete pb;
    }

}