diff options
author | Mark Spruiell <mes@zeroc.com> | 2003-10-23 23:30:22 +0000 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2003-10-23 23:30:22 +0000 |
commit | 46e5bed95534ca359771d79a431bbee065acc49e (patch) | |
tree | 86bb4dd8e49f67b809900f3cc4d61397b862ce3c /cpp | |
parent | minor output fix (diff) | |
download | ice-46e5bed95534ca359771d79a431bbee065acc49e.tar.bz2 ice-46e5bed95534ca359771d79a431bbee065acc49e.tar.xz ice-46e5bed95534ca359771d79a431bbee065acc49e.zip |
adding support for renaming types
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/Transform/Data.cpp | 152 | ||||
-rw-r--r-- | cpp/src/Transform/Data.h | 5 | ||||
-rw-r--r-- | cpp/src/Transform/Transformer.cpp | 97 |
3 files changed, 169 insertions, 85 deletions
diff --git a/cpp/src/Transform/Data.cpp b/cpp/src/Transform/Data.cpp index a149d5c531d..9cac11ce1e0 100644 --- a/cpp/src/Transform/Data.cpp +++ b/cpp/src/Transform/Data.cpp @@ -473,7 +473,7 @@ Transform::Data::print(ostream& os) const } bool -Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& src) +Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& src, DataInterceptor& interceptor) { Slice::BuiltinPtr b1 = Slice::BuiltinPtr::dynamicCast(dest); if(b1) @@ -629,7 +629,7 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& if(cl1) { Slice::ClassDeclPtr cl2 = Slice::ClassDeclPtr::dynamicCast(src); - if(cl2 && checkClasses(cl1, cl2)) + if(cl2 && checkClasses(cl1, cl2, interceptor)) { return true; } @@ -640,7 +640,12 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& Slice::StructPtr s1 = Slice::StructPtr::dynamicCast(dest); if(s1) { - Slice::StructPtr s2 = Slice::StructPtr::dynamicCast(src); + Slice::TypePtr s = interceptor.getRename(src); + if(!s) + { + s = src; + } + Slice::StructPtr s2 = Slice::StructPtr::dynamicCast(s); if(s2 && s1->scoped() == s2->scoped()) { return true; @@ -659,7 +664,7 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& } Slice::ProxyPtr p2 = Slice::ProxyPtr::dynamicCast(src); - if(p2 && checkClasses(p1->_class(), p2->_class())) + if(p2 && checkClasses(p1->_class(), p2->_class(), interceptor)) { return true; } @@ -673,7 +678,8 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& Slice::DictionaryPtr d2 = Slice::DictionaryPtr::dynamicCast(src); if(d2) { - return isCompatible(d1->keyType(), d2->keyType()) && isCompatible(d1->valueType(), d2->valueType()); + return isCompatible(d1->keyType(), d2->keyType(), interceptor) && + isCompatible(d1->valueType(), d2->valueType(), interceptor); } return false; @@ -685,7 +691,7 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& Slice::SequencePtr seq2 = Slice::SequencePtr::dynamicCast(src); if(seq2) { - return isCompatible(seq1->type(), seq2->type()); + return isCompatible(seq1->type(), seq2->type(), interceptor); } return false; @@ -694,9 +700,19 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& Slice::EnumPtr e1 = Slice::EnumPtr::dynamicCast(dest); if(e1) { - Slice::EnumPtr e2 = Slice::EnumPtr::dynamicCast(src); Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src); - if((e2 && e1->scoped() == e2->scoped()) || (b2 && b2->kind() == Slice::Builtin::KindString)) + if(b2 && b2->kind() == Slice::Builtin::KindString) + { + return true; + } + + Slice::TypePtr s = interceptor.getRename(src); + if(!s) + { + s = src; + } + Slice::EnumPtr e2 = Slice::EnumPtr::dynamicCast(s); + if(e2 && e1->scoped() == e2->scoped()) { return true; } @@ -709,8 +725,17 @@ Transform::Data::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& } bool -Transform::Data::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::ClassDeclPtr& src) +Transform::Data::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::ClassDeclPtr& src, + DataInterceptor& interceptor) { + // + // Here are the rules for verifying class compatibility: + // + // 1. If the type ids are the same, assume they are compatible. + // 2. If the source type has been renamed, then check its equivalent new definition for compatibility. + // 3. Otherwise, the types are only compatible if they are defined in the same Slice unit, and if the + // destination type is a base type of the source type. + // string s1 = dest->scoped(); string s2 = src->scoped(); if(s1 == s2) @@ -719,17 +744,26 @@ Transform::Data::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::Clas } else { - Slice::ClassDefPtr def = src->definition(); - if(!def) + Slice::TypePtr t = interceptor.getRename(src); + Slice::ClassDeclPtr s = Slice::ClassDeclPtr::dynamicCast(t); + if(s) { - _errorReporter->error("class " + s2 + " declared but not defined"); + return checkClasses(dest, s, interceptor); } - Slice::ClassList bases = def->allBases(); - for(Slice::ClassList::iterator p = bases.begin(); p != bases.end(); ++p) + else if(dest->unit().get() == src->unit().get()) { - if((*p)->scoped() == s1) + Slice::ClassDefPtr def = src->definition(); + if(!def) { - return true; + _errorReporter->error("class " + s2 + " declared but not defined"); + } + Slice::ClassList bases = def->allBases(); + for(Slice::ClassList::iterator p = bases.begin(); p != bases.end(); ++p) + { + if((*p)->scoped() == s1) + { + return true; + } } } } @@ -2078,7 +2112,7 @@ void Transform::StructData::transformI(const DataPtr& data, DataInterceptor& interceptor) { StructDataPtr s = StructDataPtr::dynamicCast(data); - if(s && _type->scoped() == s->_type->scoped()) + if(s && isCompatible(_type, s->_type, interceptor)) { // // Invoke transform() on members with the same name. @@ -2356,7 +2390,7 @@ void Transform::SequenceData::transformI(const DataPtr& data, DataInterceptor& interceptor) { SequenceDataPtr s = SequenceDataPtr::dynamicCast(data); - if(s && isCompatible(_type, s->_type)) + if(s && isCompatible(_type, s->_type, interceptor)) { DataList elements; for(DataList::const_iterator p = s->_elements.begin(); p != s->_elements.end(); ++p) @@ -2653,7 +2687,7 @@ Transform::EnumData::transformI(const DataPtr& data, DataInterceptor& intercepto { EnumDataPtr e = EnumDataPtr::dynamicCast(data); StringDataPtr s = StringDataPtr::dynamicCast(data); - if(e && _type->scoped() == e->_type->scoped()) + if(e && isCompatible(_type, e->_type, interceptor)) { // // Get the enumerator's name and attempt to find it in our type. @@ -2898,7 +2932,7 @@ void Transform::DictionaryData::transformI(const DataPtr& data, DataInterceptor& interceptor) { DictionaryDataPtr d = DictionaryDataPtr::dynamicCast(data); - if(d && isCompatible(_type, d->_type)) + if(d && isCompatible(_type, d->_type, interceptor)) { DataMap m; for(DataMap::const_iterator p = d->_map.begin(); p != d->_map.end(); ++p) @@ -2967,15 +3001,6 @@ Transform::DictionaryData::add(const DataPtr& key, const DataPtr& value) { assert(!readOnly()); - if(!isCompatible(_type->keyType(), key->getType())) - { - _errorReporter->typeMismatchError(_type->keyType(), key->getType(), true); - } - if(!isCompatible(_type->valueType(), value->getType())) - { - _errorReporter->typeMismatchError(_type->valueType(), value->getType(), true); - } - DataMap::iterator p = _map.find(key); assert(p == _map.end()); @@ -3093,8 +3118,6 @@ Transform::ObjectData::transform(const DataPtr& data, DataInterceptor& intercept ObjectDataPtr o = ObjectDataPtr::dynamicCast(data); if(o) { - assert(isCompatible(_type, o->_type)); - // // The source object must be present in the object map (we currently don't support // transforming two ObjectData instances from the same Slice unit - this transform @@ -3493,7 +3516,7 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept // // Allow a nil value from type Object. // - if(Slice::BuiltinPtr::dynamicCast(o->_type) || isCompatible(_type, o->_type)) + if(Slice::BuiltinPtr::dynamicCast(o->_type) || isCompatible(_type, o->_type, interceptor)) { setValue(0); } @@ -3505,7 +3528,7 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept else { Slice::TypePtr otype = o->_value->getType(); - if(isCompatible(_type, otype)) + if(isCompatible(_type, otype, interceptor)) { // // If the types are in the same Slice unit, then we can simply @@ -3527,42 +3550,41 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept } else { - string name = typeName(otype); - Slice::TypeList l = _type->unit()->lookupType(name, false); - if(l.empty()) - { - throw ClassNotFoundException(name); - } - else + // + // If the type has been renamed, we need to get its equivalent + // in the new Slice definitions. + // + Slice::TypePtr newType = interceptor.getRename(otype); + if(!newType) { - Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(l.front()); - if(decl) - { - Slice::ClassDefPtr def = decl->definition(); - if(!def) - { - _errorReporter->error("no definition for " + name); - } - } - // - // Create a new object and increment its reference count. We do this - // because it's possible for its reference count to be manipulated - // during transformation, and we don't want it to be destroyed. - // - ObjectDataPtr data = new ObjectData(_factory, l.front(), _readOnly); - data->incRef(); - try + string name = typeName(otype); + Slice::TypeList l = _type->unit()->lookupType(name, false); + if(l.empty()) { - data->transform(o->_value, interceptor); + throw ClassNotFoundException(name); } - catch(...) - { - data->decRef(); - throw; - } - setValue(data); - data->decRef(); + newType = l.front(); } + + // + // Use createObject() so that an initializer is invoked if necessary. + // + DataPtr newObj = _factory->createObject(newType, _readOnly); + ObjectRefPtr newRef = ObjectRefPtr::dynamicCast(newObj); + assert(newRef); + + try + { + newRef->_value->transform(o->_value, interceptor); + } + catch(...) + { + newObj->destroy(); + throw; + } + + setValue(newRef->_value); + newObj->destroy(); } } } diff --git a/cpp/src/Transform/Data.h b/cpp/src/Transform/Data.h index fef7aea4f66..ce509d3d133 100644 --- a/cpp/src/Transform/Data.h +++ b/cpp/src/Transform/Data.h @@ -51,6 +51,7 @@ public: virtual void postTransform(const DataPtr&, const DataPtr&) = 0; virtual ObjectDataMap& getObjectMap() = 0; virtual bool purgeObjects() const = 0; + virtual Slice::TypePtr getRename(const Slice::TypePtr&) const = 0; }; class DataInitializer : virtual public IceUtil::SimpleShared @@ -135,8 +136,8 @@ protected: Data(const ErrorReporterPtr&, bool); - bool isCompatible(const Slice::TypePtr&, const Slice::TypePtr&); - bool checkClasses(const Slice::ClassDeclPtr&, const Slice::ClassDeclPtr&); + bool isCompatible(const Slice::TypePtr&, const Slice::TypePtr&, DataInterceptor&); + bool checkClasses(const Slice::ClassDeclPtr&, const Slice::ClassDeclPtr&, DataInterceptor&); ErrorReporterPtr _errorReporter; bool _readOnly; diff --git a/cpp/src/Transform/Transformer.cpp b/cpp/src/Transform/Transformer.cpp index 02945be4552..e0dd4721d36 100644 --- a/cpp/src/Transform/Transformer.cpp +++ b/cpp/src/Transform/Transformer.cpp @@ -35,6 +35,7 @@ class TransformDescriptor; typedef IceUtil::Handle<TransformDescriptor> TransformDescriptorPtr; typedef map<string, TransformDescriptorPtr> TransformMap; +typedef map<string, string> RenameMap; class DeleteRecordException {}; @@ -268,14 +269,16 @@ class TransformDescriptor : public ExecutableContainerDescriptor { public: - TransformDescriptor(const DescriptorPtr&, int, const string&, bool); + TransformDescriptor(const DescriptorPtr&, int, const string&, bool, const string&); string type() const; + string rename() const; bool doDefaultTransform() const; private: bool _default; + string _rename; Slice::TypePtr _oldType; Slice::TypePtr _newType; }; @@ -315,7 +318,7 @@ public: virtual void execute(TransformSymbolTable&, DataInterceptor&); bool transform(IceInternal::BasicStream&, IceInternal::BasicStream&, IceInternal::BasicStream&, - IceInternal::BasicStream&, const TransformMap&, bool); + IceInternal::BasicStream&, const TransformMap&, const RenameMap&, bool); private: @@ -352,7 +355,8 @@ private: Slice::UnitPtr _new; ErrorReporterPtr _errorReporter; DatabaseDescriptorPtr _database; - TransformMap _transforms; + TransformMap _transformMap; + RenameMap _renameMap; vector<DescriptorPtr> _children; }; typedef IceUtil::Handle<TransformerDescriptor> TransformerDescriptorPtr; @@ -385,12 +389,13 @@ class TransformInterceptor : public DataInterceptor public: TransformInterceptor(const DataFactoryPtr&, const ErrorReporterPtr&, const Slice::UnitPtr&, - const Slice::UnitPtr&, const TransformMap&, bool); + const Slice::UnitPtr&, const TransformMap&, const RenameMap&, bool); virtual bool preTransform(const DataPtr&, const DataPtr&); virtual void postTransform(const DataPtr&, const DataPtr&); virtual ObjectDataMap& getObjectMap(); virtual bool purgeObjects() const; + virtual Slice::TypePtr getRename(const Slice::TypePtr&) const; private: @@ -399,6 +404,7 @@ private: Slice::UnitPtr _old; Slice::UnitPtr _new; const TransformMap& _transformMap; + const RenameMap& _renameMap; ObjectDataMap _objectMap; bool _purgeObjects; }; @@ -1322,8 +1328,8 @@ Transform::IterateDescriptor::execute(TransformSymbolTable& sym, DataInterceptor // TransformDescriptor // Transform::TransformDescriptor::TransformDescriptor(const DescriptorPtr& parent, int line, const string& type, - bool def) : - ExecutableContainerDescriptor(parent, line, "transform"), Descriptor(parent, line), _default(def) + bool def, const string& rename) : + ExecutableContainerDescriptor(parent, line, "transform"), Descriptor(parent, line), _default(def), _rename(rename) { DescriptorErrorContext ctx(errorReporter(), "transform", _line); @@ -1344,6 +1350,15 @@ Transform::TransformDescriptor::TransformDescriptor(const DescriptorPtr& parent, { _newType = l.front(); } + + if(!rename.empty()) + { + l = oldUnit()->lookupType(rename, false); + if(l.empty()) + { + errorReporter()->error("unable to find type `" + rename + "' in old Slice definitions"); + } + } } string @@ -1352,6 +1367,12 @@ Transform::TransformDescriptor::type() const return typeName(_newType); } +string +Transform::TransformDescriptor::rename() const +{ + return _rename; +} + bool Transform::TransformDescriptor::doDefaultTransform() const { @@ -1391,8 +1412,9 @@ Transform::InitDescriptor::initialize(const DataFactoryPtr& factory, const DataP // // Also need an interceptor in order to call execute. // - TransformMap transforms; - TransformInterceptor interceptor(factory, errorReporter(), oldUnit(), newUnit(), transforms, false); + TransformMap transformMap; + RenameMap renameMap; + TransformInterceptor interceptor(factory, errorReporter(), oldUnit(), newUnit(), transformMap, renameMap, false); execute(sym, interceptor); } @@ -1500,11 +1522,13 @@ Transform::DatabaseDescriptor::execute(TransformSymbolTable&, DataInterceptor&) bool Transform::DatabaseDescriptor::transform(IceInternal::BasicStream& inKey, IceInternal::BasicStream& inValue, IceInternal::BasicStream& outKey, IceInternal::BasicStream& outValue, - const TransformMap& transforms, bool purgeObjects) + const TransformMap& transformMap, const RenameMap& renameMap, + bool purgeObjects) { errorReporter()->raise(false); - TransformInterceptor interceptor(factory(), errorReporter(), oldUnit(), newUnit(), transforms, purgeObjects); + TransformInterceptor interceptor(factory(), errorReporter(), oldUnit(), newUnit(), transformMap, renameMap, + purgeObjects); // // Create data representations of the old key and value types. @@ -1598,12 +1622,22 @@ Transform::TransformerDescriptor::addChild(const DescriptorPtr& child) else if(transform) { string name = transform->type(); - TransformMap::iterator p = _transforms.find(name); - if(p != _transforms.end()) + TransformMap::iterator p = _transformMap.find(name); + if(p != _transformMap.end()) { errorReporter()->error("transform `" + name + "' specified more than once"); } - _transforms.insert(TransformMap::value_type(name, transform)); + _transformMap.insert(TransformMap::value_type(name, transform)); + string rename = transform->rename(); + if(!rename.empty()) + { + RenameMap::iterator q = _renameMap.find(rename); + if(q != _renameMap.end()) + { + errorReporter()->error("multiple transform descriptors specify the rename value `" + rename + "'"); + } + _renameMap.insert(RenameMap::value_type(rename, name)); + } _children.push_back(transform); } else if(init) @@ -1696,7 +1730,7 @@ Transform::TransformerDescriptor::transform(const Ice::CommunicatorPtr& communic outValue.startWriteEncaps(); try { - if(_database->transform(inKey, inValue, outKey, outValue, _transforms, purgeObjects)) + if(_database->transform(inKey, inValue, outKey, outValue, _transformMap, _renameMap, purgeObjects)) { outValue.endWriteEncaps(); Dbt dbNewKey(&outKey.b[0], outKey.b.size()), dbNewValue(&outValue.b[0], outValue.b.size()); @@ -1808,7 +1842,9 @@ Transform::DescriptorHandler::startElement(const string& name, const IceXML::Att IceXML::Attributes::const_iterator p; - string type; + string type, rename; + bool def = true; + p = attributes.find("type"); if(p == attributes.end()) { @@ -1816,7 +1852,6 @@ Transform::DescriptorHandler::startElement(const string& name, const IceXML::Att } type = p->second; - bool def = true; p = attributes.find("default"); if(p != attributes.end()) { @@ -1826,7 +1861,13 @@ Transform::DescriptorHandler::startElement(const string& name, const IceXML::Att } } - d = new TransformDescriptor(_current, line, type, def); + p = attributes.find("rename"); + if(p != attributes.end()) + { + rename = p->second; + } + + d = new TransformDescriptor(_current, line, type, def, rename); } else if(name == "init") { @@ -2132,9 +2173,10 @@ Transform::TransformInterceptor::TransformInterceptor(const DataFactoryPtr& fact const Slice::UnitPtr& oldUnit, const Slice::UnitPtr& newUnit, const TransformMap& transformMap, + const RenameMap& renameMap, bool purgeObjects) : _factory(factory), _errorReporter(errorReporter), _old(oldUnit), _new(newUnit), _transformMap(transformMap), - _purgeObjects(purgeObjects) + _renameMap(renameMap), _purgeObjects(purgeObjects) { } @@ -2194,6 +2236,25 @@ Transform::TransformInterceptor::purgeObjects() const return _purgeObjects; } +Slice::TypePtr +Transform::TransformInterceptor::getRename(const Slice::TypePtr& oldType) const +{ + Slice::TypePtr result; + + if(oldType->unit().get() == _old.get()) + { + RenameMap::const_iterator p = _renameMap.find(typeName(oldType)); + if(p != _renameMap.end()) + { + Slice::TypeList l = _new->lookupType(p->second, false); + assert(!l.empty()); + return l.front(); + } + } + + return result; +} + // // Transformer // |