summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Transform/Data.cpp152
-rw-r--r--cpp/src/Transform/Data.h5
-rw-r--r--cpp/src/Transform/Transformer.cpp97
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
//