diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/include/XMLTransform/XMLTransform.h | 52 | ||||
-rw-r--r-- | cpp/src/XMLTransform/TransformDB.cpp | 19 | ||||
-rw-r--r-- | cpp/src/XMLTransform/XMLTransform.cpp | 493 | ||||
-rw-r--r-- | cpp/test/XMLTransform/transform/Populate.cpp | 104 |
4 files changed, 516 insertions, 152 deletions
diff --git a/cpp/include/XMLTransform/XMLTransform.h b/cpp/include/XMLTransform/XMLTransform.h index 97ad5f34775..b455b70d484 100644 --- a/cpp/include/XMLTransform/XMLTransform.h +++ b/cpp/include/XMLTransform/XMLTransform.h @@ -20,6 +20,8 @@ #include <xercesc/dom/DOM.hpp> +#include <map> + #ifdef WIN32 # ifdef XML_TRANSFORM_API_EXPORTS # define XML_TRANSFORM_API __declspec(dllexport) @@ -102,6 +104,23 @@ public: }; // +// Raised if a type was not found in the new schema. +// +class XML_TRANSFORM_API MissingTypeException : public ::IceUtil::Exception +{ +public: + + MissingTypeException(const char*, int); + + virtual ::std::string ice_name() const; + virtual void ice_print(::std::ostream&) const; + virtual ::IceUtil::Exception* ice_clone() const; + virtual void ice_throw() const; + + ::std::string reason; +}; + +// // Raised in the case of a general transformation failure. // class XML_TRANSFORM_API TransformException : public ::IceUtil::Exception @@ -158,7 +177,12 @@ public: Transform(); virtual ~Transform(); - virtual void transform(::IceUtil::XMLOutput&, const DocumentInfoPtr&, const ::std::string&, DOMNode*) = 0; + typedef ::std::map< ::std::string, ::std::string > MissingTypeMap; + + virtual void transform(::IceUtil::XMLOutput&, const DocumentInfoPtr&, const ::std::string&, DOMNode*, + const MissingTypeMap&) = 0; + virtual void checkMissingTypes(const DocumentInfoPtr&, DOMNode*, const MissingTypeMap&) { } + virtual void collectMissingTypes(const DocumentInfoPtr&, DOMNode*, MissingTypeMap&) { } virtual ::std::ostream& print(::std::ostream&) = 0; }; @@ -181,7 +205,7 @@ public: DOMDocument*, DOMDocument*); ~Transformer(); - void transform(::IceUtil::XMLOutput&, DOMDocument*, bool = true); + void transform(::IceUtil::XMLOutput&, DOMDocument*, bool, bool = true); private: @@ -200,28 +224,36 @@ private: class XML_TRANSFORM_API DBTransformer { - void transform(const Freeze::DBEnvironmentPtr&, const Freeze::DBPtr&, const Ice::StringSeq&, const Ice::StringSeq&, - const Ice::StringSeq&, const Ice::StringSeq&, DOMDocument*, DOMDocument*); - public: - DBTransformer(); + DBTransformer(const Freeze::DBEnvironmentPtr&, const Freeze::DBPtr&, const Ice::StringSeq&, const Ice::StringSeq&, + const Ice::StringSeq&, const Ice::StringSeq&, bool); ~DBTransformer(); // // This version allows the caller to specify the filenames for the // old and new schemas. // - void transform(const Freeze::DBEnvironmentPtr&, const Freeze::DBPtr&, const Ice::StringSeq&, const Ice::StringSeq&, - const Ice::StringSeq&, const Ice::StringSeq&, const std::string&, const std::string&); + void transform(const std::string&, const std::string&); // // This version allows the caller to specify a single schema for // transformation. This is commonly used for schemas whose formal // types don't change, but whose actual (instance) types do change. // - void transform(const Freeze::DBEnvironmentPtr&, const Freeze::DBPtr&, const Ice::StringSeq&, const Ice::StringSeq&, - const Ice::StringSeq&, const Ice::StringSeq&, const std::string&); + void transform(const std::string&); + +private: + + void transform(DOMDocument*, DOMDocument*); + + Freeze::DBEnvironmentPtr _dbEnv; + Freeze::DBPtr _db; + Ice::StringSeq _loadOld; + Ice::StringSeq _loadNew; + Ice::StringSeq _pathOld; + Ice::StringSeq _pathNew; + bool _force; }; } // End namespace XMLTransform diff --git a/cpp/src/XMLTransform/TransformDB.cpp b/cpp/src/XMLTransform/TransformDB.cpp index d34bf79d6b7..cfee8e9184b 100644 --- a/cpp/src/XMLTransform/TransformDB.cpp +++ b/cpp/src/XMLTransform/TransformDB.cpp @@ -31,6 +31,7 @@ usage(const string& appName) "--load-new PATH Load new schema from the given file or directory.\n" "--path-old DIR Add directory DIR to the old schema import search path.\n" "--path-new DIR Add directory DIR to the new schema import search path.\n" + "--force Force removal of objects whose types cannot be found.\n" "-h, --help Show this message.\n" "-v, --version Display the Ice version.\n" ; @@ -51,6 +52,7 @@ main(int argc, char* argv[]) bool evictor = false; Ice::StringSeq loadOld, loadNew; Ice::StringSeq pathOld, pathNew; + bool force = false; int idx = 1; while(idx < argc) @@ -128,6 +130,15 @@ main(int argc, char* argv[]) } --argc; } + else if(strcmp(argv[idx], "--force") == 0) + { + force = true; + for(int i = idx ; i + 1 < argc ; ++i) + { + argv[i] = argv[i + 1]; + } + --argc; + } else if(strcmp(argv[idx], "-h") == 0 || strcmp(argv[idx], "--help") == 0) { usage(argv[0]); @@ -159,9 +170,9 @@ main(int argc, char* argv[]) try { dbEnv = Freeze::initializeWithTxn(communicator, argv[1]); - db = dbEnv->openDB(argv[2], false); + db = dbEnv->openDBWithTxn(0, argv[2], false); - XMLTransform::DBTransformer transformer; + XMLTransform::DBTransformer transformer(dbEnv, db, loadOld, loadNew, pathOld, pathNew, force); if(evictor) { @@ -183,11 +194,11 @@ main(int argc, char* argv[]) " <xs:element name=\"Key\" type=\"_internal.Ice.IdentityType\"/>" " <xs:element name=\"Value\" type=\"ice:_internal.objectType\"/></xs:schema>"; - transformer.transform(dbEnv, db, loadOld, loadNew, pathOld, pathNew, schema); + transformer.transform(schema); } else { - transformer.transform(dbEnv, db, loadOld, loadNew, pathOld, pathNew, argv[3], argv[4]); + transformer.transform(argv[3], argv[4]); } } catch(const Freeze::DBNotFoundException&) diff --git a/cpp/src/XMLTransform/XMLTransform.cpp b/cpp/src/XMLTransform/XMLTransform.cpp index cacfb377d20..217a0080ef3 100644 --- a/cpp/src/XMLTransform/XMLTransform.cpp +++ b/cpp/src/XMLTransform/XMLTransform.cpp @@ -168,6 +168,36 @@ XMLTransform::SchemaViolation::ice_throw() const throw *this; } +XMLTransform::MissingTypeException::MissingTypeException(const char* file, int line) : + Exception(file, line) +{ +} + +string +XMLTransform::MissingTypeException::ice_name() const +{ + return "MissingTypeException"; +} + +void +XMLTransform::MissingTypeException::ice_print(ostream& out) const +{ + Exception::ice_print(out); + out << ":\n" << reason; +} + +::IceUtil::Exception* +XMLTransform::MissingTypeException::ice_clone() const +{ + return new MissingTypeException(*this); +} + +void +XMLTransform::MissingTypeException::ice_throw() const +{ + throw *this; +} + XMLTransform::TransformException::TransformException(const char* file, int line) : Exception(file, line) { @@ -511,7 +541,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node, const MissingTypeMap&) { if(node == 0) { @@ -543,7 +573,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput&, const DocumentInfoPtr&, const string&, DOMNode*) + transform(::IceUtil::XMLOutput&, const DocumentInfoPtr&, const string&, DOMNode*, const MissingTypeMap&) { throw SchemaViolation(__FILE__, __LINE__); } @@ -576,7 +606,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode*) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode*, const MissingTypeMap&) { } @@ -605,9 +635,16 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node, + const MissingTypeMap& map) + { + _transform->transform(os, info, _name, node, map); + } + + virtual void + checkMissingTypes(const DocumentInfoPtr& info, DOMNode* node, const MissingTypeMap& map) { - _transform->transform(os, info, _name, node); + _transform->checkMissingTypes(info, node, map); } virtual ostream& @@ -645,7 +682,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node, const MissingTypeMap&) { if(node == 0) { @@ -693,7 +730,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node, const MissingTypeMap&) { if(node == 0) { @@ -769,7 +806,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string&, DOMNode* node, const MissingTypeMap&) { if(node == 0) { @@ -812,22 +849,52 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node, + const MissingTypeMap& map) { if(node == 0) { throw SchemaViolation(__FILE__, __LINE__); } + + string length = getAttributeByName(node, "length"); + long l = atol(length.c_str()); + + // + // Before we emit anything, we check for missing types. + // If a MissingTypeException is raised for an element, + // that element will be skipped. We have to do this in + // advance in order to properly compute the sequence length. + // + DOMNodeList* children = node->getChildNodes(); + unsigned int i; + for(i = 0; i < children->getLength(); ++i) + { + DOMNode* child = children->item(i); + if(child->getNodeType() != DOMNode::ELEMENT_NODE) + { + continue; + } + + try + { + _transform->checkMissingTypes(info, child, map); + } + catch(const MissingTypeException& ex) + { + --l; + } + } + string name = toString(node->getNodeName()); os << ::IceUtil::se(name); - string length = getAttributeByName(node, "length"); - os << ::IceUtil::attr("length", length); + ostringstream lstr; + lstr << l; - long l = atol(length.c_str()); + os << ::IceUtil::attr("length", lstr.str()); - DOMNodeList* children = node->getChildNodes(); - for(unsigned int i = 0; i < children->getLength(); ++i) + for(i = 0; i < children->getLength(); ++i) { DOMNode* child = children->item(i); if(child->getNodeType() != DOMNode::ELEMENT_NODE) @@ -840,13 +907,40 @@ public: { throw SchemaViolation(__FILE__, __LINE__); } - _transform->transform(os, info, nodeName, child); - --l; + + try + { + _transform->transform(os, info, nodeName, child, map); + } + catch(const MissingTypeException&) + { + // Skip this element + } } os << ::IceUtil::ee; } + virtual void + checkMissingTypes(const DocumentInfoPtr& info, DOMNode* node, const MissingTypeMap& map) + { + if(node == 0) + { + throw SchemaViolation(__FILE__, __LINE__); + } + DOMNodeList* children = node->getChildNodes(); + for(unsigned int i = 0; i < children->getLength(); ++i) + { + DOMNode* child = children->item(i); + if(child->getNodeType() != DOMNode::ELEMENT_NODE) + { + continue; + } + + _transform->checkMissingTypes(info, child, map); + } + } + virtual ostream& print(ostream& os) { @@ -887,7 +981,8 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string&, DOMNode* node, + const MissingTypeMap& map) { if(node == 0) { @@ -904,12 +999,43 @@ public: for(vector<ElementTransformPtr>::const_iterator p = _transforms.begin(); p != _transforms.end(); ++p) { DOMNode* child = findChild(node, (*p)->namespaceURI(), (*p)->name()); - (*p)->transform(os, info, (*p)->name(), child); + try + { + (*p)->transform(os, info, (*p)->name(), child, map); + } + catch(const MissingTypeException& ex) + { + // + // A struct member cannot be removed if it refers to + // a missing type, so we translate MissingTypeException + // into SchemaViolation. + // + SchemaViolation e(__FILE__, __LINE__); + ostringstream ostr; + ostr << "error during transform of struct member `" << (*p)->name() << "':" << endl << ex.reason; + e.reason = ostr.str(); + throw e; + } } os << ::IceUtil::ee; } + virtual void + checkMissingTypes(const DocumentInfoPtr& info, DOMNode* node, const MissingTypeMap& map) + { + if(node == 0) + { + throw SchemaViolation(__FILE__, __LINE__); + } + + for(vector<ElementTransformPtr>::const_iterator p = _transforms.begin(); p != _transforms.end(); ++p) + { + DOMNode* child = findChild(node, (*p)->namespaceURI(), (*p)->name()); + (*p)->checkMissingTypes(info, child, map); + } + } + virtual ostream& print(ostream& os) { @@ -944,28 +1070,61 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string& name, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string& name, DOMNode* node, + const MissingTypeMap& map) { - // - // First check for the "href" attribute, which indicates a - // reference to another object. We simply emit the node - // as-is. The referenced object, which is a child of the - // root node, will be transformed automatically. - // - string id = getAttributeByName(node, "href"); - if(!id.empty()) + // + // If the object is null simply emit the node as-is. + // + string nil = getAttributeByName(node, "xsi:nil"); + if(!nil.empty() && nil == "true") { os << node; return; } + // + // Otherwise, xsi:type must be present. + // + string type = getAttributeByName(node, "xsi:type"); + if(type.empty()) + { + throw SchemaViolation(__FILE__, __LINE__); + } + + string n = convertQName(type, info); + // - // If the object is null simply emit the node as-is. + // Technically this is only permitted to be a more derived + // type - however, this will not be enforced here. + // + TransformMap::const_iterator p = _transforms->find(n); + if(p == _transforms->end()) + { + // + // No transformation found for this type. This should + // have already been discovered by collectMissingTypes. + // + string id = getAttributeByName(node, "id"); + assert(!id.empty()); + MissingTypeMap::const_iterator q = map.find(id); + assert(q != map.end()); + MissingTypeException ex(__FILE__, __LINE__); + ex.reason = "unable to find a transformation for type `" + n + "'"; + throw ex; + } + p->second->transform(os, info, name, node, map); + } + + virtual void + collectMissingTypes(const DocumentInfoPtr& info, DOMNode* node, MissingTypeMap& map) + { + // + // Check if the object is null. // string nil = getAttributeByName(node, "xsi:nil"); if(!nil.empty() && nil == "true") { - os << node; return; } @@ -987,11 +1146,12 @@ public: TransformMap::const_iterator p = _transforms->find(n); if(p == _transforms->end()) { - SchemaViolation ex(__FILE__, __LINE__); - ex.reason = "unable to find a transformation for type `" + n + "'"; - throw ex; + string id = getAttributeByName(node, "id"); + assert(!id.empty()); + string sliceType = getAttributeByName(node, "type"); + assert(!sliceType.empty()); + map.insert(make_pair(id, sliceType)); } - p->second->transform(os, info, name, node); } virtual ostream& @@ -1010,6 +1170,92 @@ private: typedef ::IceUtil::Handle<ClassTransform> ClassTransformPtr; // +// Transform for an object reference. +// +class ReferenceTransform : public Transform +{ +public: + + ReferenceTransform() + { + } + + virtual void + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string& name, DOMNode* node, + const MissingTypeMap& map) + { + // + // First check for the "href" attribute, which indicates a + // reference to another object. The referenced object, which + // is a child of the root node, will be transformed automatically. + // + string id = getAttributeByName(node, "href"); + if(!id.empty()) + { + id.erase(0, 1); // Remove the '#'. + // + // If the id is present in the missing type map, then + // we must raise an exception. + // + MissingTypeMap::const_iterator q = map.find(id); + if(q != map.end()) + { + MissingTypeException ex(__FILE__, __LINE__); + ex.reason = "unable to find a transformation for type `" + q->second + "'"; + throw ex; + } + + os << node; + return; + } + + // + // If there is no "href" attribute, then the object must be nil. + // + string nil = getAttributeByName(node, "xsi:nil"); + if(nil.empty()) + { + throw SchemaViolation(__FILE__, __LINE__); + } + os << node; + } + + virtual void + checkMissingTypes(const DocumentInfoPtr& info, DOMNode* node, const MissingTypeMap& map) + { + // + // First check for the "href" attribute, which indicates a + // reference to another object. + // + string id = getAttributeByName(node, "href"); + if(!id.empty()) + { + id.erase(0, 1); // Remove the '#'. + // + // If the id is present in the missing types map, then + // we must raise an exception. + // + MissingTypeMap::const_iterator q = map.find(id); + if(q != map.end()) + { + MissingTypeException ex(__FILE__, __LINE__); + ex.reason = "unable to find a transformation for type `" + q->second + "'"; + throw ex; + } + } + } + + virtual ostream& + print(ostream& os) + { + os << "[reference]\n"; + return os; + } +}; + +typedef ::IceUtil::Handle<ReferenceTransform> ReferenceTransformPtr; + +// // This transform produces a new struct. The contents of the struct will contain whatever default value is // appropriate. // @@ -1023,7 +1269,8 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string& name, DOMNode* node) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr& info, const string& name, DOMNode* node, + const MissingTypeMap& map) { os << ::IceUtil::se(name); @@ -1031,7 +1278,7 @@ public: for(vector<ElementTransformPtr>::const_iterator p = _transforms.begin(); p != _transforms.end(); ++p) { - (*p)->transform(os, info, (*p)->name(), child); + (*p)->transform(os, info, (*p)->name(), child, map); } os << ::IceUtil::ee; @@ -1069,7 +1316,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string& name, DOMNode*) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string& name, DOMNode*, const MissingTypeMap&) { os << ::IceUtil::se(name); os << ::IceUtil::startEscapes << _s << ::IceUtil::endEscapes; @@ -1104,7 +1351,7 @@ public: } virtual void - transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string& name, DOMNode*) + transform(::IceUtil::XMLOutput& os, const DocumentInfoPtr&, const string& name, DOMNode*, const MissingTypeMap&) { os << ::IceUtil::se(name); os << ::IceUtil::attr(_attrName, _attrValue); @@ -1389,9 +1636,9 @@ XMLTransform::TransformFactory::create(DOMDocument* fromDoc, DOMDocument* toDoc, // // Finally process each element from the old schema document. // - for(DocumentMap::const_iterator p = _fromDocs.begin(); p != _fromDocs.end(); ++p) + for(DocumentMap::const_iterator q = _fromDocs.begin(); q != _fromDocs.end(); ++q) { - processElements(p->second); + processElements(q->second); } } @@ -1909,12 +2156,17 @@ XMLTransform::TransformFactory::createTransform(const DocumentInfoPtr& fromTypeI case TypeString: case TypeProxy: // Same as string - case TypeReference: // Same as string { transform = new NilTransform(); break; } + case TypeReference: + { + transform = new ReferenceTransform(); + break; + } + case TypeEnumeration: { // @@ -1956,48 +2208,10 @@ XMLTransform::TransformFactory::createTransform(const DocumentInfoPtr& fromTypeI break; } + // + // A dictionary is treated as a sequence of struct. + // case TypeDictionary: - { - // - // If the type names are not the same then it's illegal. - // - // TODO: This doesn't allow the renaming of types. By removing this comparison renaming of types - // would be permitted. Should this be permitted? - // - if(fromTypeName != toTypeName) - { - IllegalTransform ex(__FILE__, __LINE__); - ex.reason = "renaming types is not supported (from " + fromTypeName + " to " + toTypeName + ")"; - throw ex; - } - - DOMNode* fromSeq = findChild(from, sequenceElementName); - DOMNode* toSeq = findChild(to, sequenceElementName); - if(fromSeq == 0 || toSeq == 0) - { - InvalidSchema ex(__FILE__, __LINE__); - ex.reason = "missing sequence element in " + fromTypeName; - throw ex; - } - - // - // Sequences have one element - which contains the type of the sequence. - // - DOMNode* fromElement = findChild(fromSeq, elementElementName); - DOMNode* toElement = findChild(toSeq, elementElementName); - - if(fromElement == 0 || toElement == 0) - { - InvalidSchema ex(__FILE__, __LINE__); - ex.reason = "invalid sequence element in " + fromTypeName; - throw ex; - } - - transform = new SequenceTransform(createTransform(fromInfo, getTypeAttribute(fromElement), - toInfo, getTypeAttribute(toElement))); - break; - } - case TypeSequence: { // @@ -2033,7 +2247,7 @@ XMLTransform::TransformFactory::createTransform(const DocumentInfoPtr& fromTypeI ex.reason = "invalid sequence element in " + fromTypeName; throw ex; } - + transform = new SequenceTransform(createTransform(fromInfo, getTypeAttribute(fromElement), toInfo, getTypeAttribute(toElement))); break; @@ -2529,7 +2743,7 @@ XMLTransform::Transformer::~Transformer() } void -XMLTransform::Transformer::transform(::IceUtil::XMLOutput& os, DOMDocument* doc, bool emitRoot) +XMLTransform::Transformer::transform(::IceUtil::XMLOutput& os, DOMDocument* doc, bool force, bool emitRoot) { DOMNode* root = doc->getFirstChild(); @@ -2549,6 +2763,12 @@ XMLTransform::Transformer::transform(::IceUtil::XMLOutput& os, DOMDocument* doc, DocumentInfoPtr info = new DocumentInfo(doc, false, root); DOMNodeList* children = root->getChildNodes(); + + // + // Collect the missing types from all elements before + // transforming. + // + Transform::MissingTypeMap map; for(i = 0; i < children->getLength(); ++i) { DOMNode* child = children->item(i); @@ -2572,7 +2792,68 @@ XMLTransform::Transformer::transform(::IceUtil::XMLOutput& os, DOMDocument* doc, throw ex; } - p->second->transform(os, info, nodeName, child); + p->second->collectMissingTypes(info, child, map); + } + + // + // If there are missing types, and we are not told to + // force removal of objects, then raise an exception. + // + if(!map.empty() && !force) + { + set<string> types; + for(Transform::MissingTypeMap::const_iterator q = map.begin(); q != map.end(); ++q) + { + types.insert(q->second); + } + ostringstream ostr; + ostr << "The following types could not be found:"; + for(set<string>::const_iterator r = types.begin(); r != types.end(); ++r) + { + ostr << endl << " " << *r; + } + MissingTypeException ex(__FILE__, __LINE__); + ex.reason = ostr.str(); + throw ex; + } + + // + // Transform. + // + for(i = 0; i < children->getLength(); ++i) + { + DOMNode* child = children->item(i); + if(child->getNodeType() != DOMNode::ELEMENT_NODE) + { + continue; + } + + string nodeName = toString(child->getNodeName()); + + // + // Create local@namespace version of the element name. + // + string n = convertQName(nodeName, info); + + TransformMap::const_iterator p = _elements.find(n); + if(p == _elements.end()) + { + SchemaViolation ex(__FILE__, __LINE__); + ex.reason = "cannot find element " + n; + throw ex; + } + + try + { + p->second->transform(os, info, nodeName, child, map); + } + catch(const MissingTypeException&) + { + if(!force) + { + throw; + } + } } if(emitRoot) @@ -2581,7 +2862,12 @@ XMLTransform::Transformer::transform(::IceUtil::XMLOutput& os, DOMDocument* doc, } } -XMLTransform::DBTransformer::DBTransformer() +XMLTransform::DBTransformer::DBTransformer(const DBEnvironmentPtr& dbEnv, const DBPtr& db, + const Ice::StringSeq& loadOld, const Ice::StringSeq& loadNew, + const Ice::StringSeq& pathOld, const Ice::StringSeq& pathNew, + bool force) : + _dbEnv(dbEnv), _db(db), _loadOld(loadOld), _loadNew(loadNew), _pathOld(pathOld), _pathNew(pathNew), + _force(force) { try { @@ -2600,10 +2886,7 @@ XMLTransform::DBTransformer::~DBTransformer() } void -XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPtr& db, - const Ice::StringSeq& loadOld, const Ice::StringSeq& loadNew, - const Ice::StringSeq& pathOld, const Ice::StringSeq& pathNew, - DOMDocument* oldSchema, DOMDocument* newSchema) +XMLTransform::DBTransformer::transform(DOMDocument* oldSchema, DOMDocument* newSchema) { DOMTreeErrorReporter errReporter; @@ -2617,7 +2900,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt string reason; try { - Transformer transformer(loadOld, loadNew, pathOld, pathNew, oldSchema, newSchema); + Transformer transformer(_loadOld, _loadNew, _pathOld, _pathNew, oldSchema, newSchema); // // Header and footer for instance documents. @@ -2634,7 +2917,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt // keys first, then update the records. // vector<Key> keys; - cursor = db->getCursor(); + cursor = _db->getCursor(); do { Key k; @@ -2646,7 +2929,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt cursor->close(); cursor = 0; - txn = dbEnv->startTransaction(); + txn = _dbEnv->startTransaction(); vector<Key>::const_iterator p; for(p = keys.begin(); p != keys.end(); ++p) @@ -2666,7 +2949,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt ostringstream keyStream; IceUtil::XMLOutput keyOut(keyStream); - transformer.transform(keyOut, keyDoc, false); + transformer.transform(keyOut, keyDoc, _force, false); Key newKey; const std::string& keyStr = keyStream.str(); @@ -2676,7 +2959,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt // // Transform value // - Value value = db->getWithTxn(txn, k); + Value value = _db->getWithTxn(txn, k); string fullValue; fullValue.append(header); fullValue.append(&value[0], value.size()); @@ -2687,7 +2970,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt ostringstream valueStream; IceUtil::XMLOutput valueOut(valueStream); - transformer.transform(valueOut, valueDoc, false); + transformer.transform(valueOut, valueDoc, _force, false); Value newValue; const std::string& valueStr = valueStream.str(); @@ -2698,15 +2981,15 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt // Update database - only insert new key,value pair if the transformed // key doesn't match an existing key. // - db->delWithTxn(txn, k); - if(db->containsWithTxn(txn, newKey)) + _db->delWithTxn(txn, k); + if(_db->containsWithTxn(txn, newKey)) { reason = "transformed key matches an existing record:\n" + keyStr; txn->abort(); txn = 0; break; } - db->putWithTxn(txn, newKey, newValue); + _db->putWithTxn(txn, newKey, newValue); } if(txn) @@ -2765,10 +3048,7 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt } void -XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPtr& db, - const Ice::StringSeq& loadOld, const Ice::StringSeq& loadNew, - const Ice::StringSeq& pathOld, const Ice::StringSeq& pathNew, - const string& oldSchemaFile, const string& newSchemaFile) +XMLTransform::DBTransformer::transform(const string& oldSchemaFile, const string& newSchemaFile) { DOMTreeErrorReporter errReporter; @@ -2807,14 +3087,11 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt throw e; } - transform(dbEnv, db, loadOld, loadNew, pathOld, pathNew, oldSchema, newSchema); + transform(oldSchema, newSchema); } void -XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPtr& db, - const Ice::StringSeq& loadOld, const Ice::StringSeq& loadNew, - const Ice::StringSeq& pathOld, const Ice::StringSeq& pathNew, - const string& schemaStr) +XMLTransform::DBTransformer::transform(const string& schemaStr) { DOMTreeErrorReporter errReporter; @@ -2850,5 +3127,5 @@ XMLTransform::DBTransformer::transform(const DBEnvironmentPtr& dbEnv, const DBPt throw e; } - transform(dbEnv, db, loadOld, loadNew, pathOld, pathNew, schema, schema); + transform(schema, schema); } diff --git a/cpp/test/XMLTransform/transform/Populate.cpp b/cpp/test/XMLTransform/transform/Populate.cpp index c9027568b73..2ebb00d98fe 100644 --- a/cpp/test/XMLTransform/transform/Populate.cpp +++ b/cpp/test/XMLTransform/transform/Populate.cpp @@ -83,7 +83,6 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) Int i; DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming primitives... " << flush; @@ -108,7 +107,10 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "byteToShort", false); emitSchemas("xs:byte", "xs:short"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -130,7 +132,10 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "shortToInt", false); emitSchemas("xs:short", "xs:int"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -152,7 +157,10 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "intToLong", false); emitSchemas("xs:int", "xs:long"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -174,7 +182,10 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "longToByte", false); emitSchemas("xs:long", "xs:byte"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -196,7 +207,10 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "floatToDouble", false); emitSchemas("xs:float", "xs:double"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -223,7 +237,8 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) emitSchemas("xs:long", "xs:byte"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -256,7 +271,8 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) emitSchemas("xs:long", "xs:short"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -289,7 +305,8 @@ transformPrimitive(const DBEnvironmentPtr& dbEnv) emitSchemas("xs:long", "xs:int"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -323,7 +340,6 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) Int i; DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming primitive sequences... " << flush; @@ -350,7 +366,10 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "byteToShortSeq", false); emitSchemas("tns:_internal.Test.Seq1Type", "tns:_internal.Test.Seq1Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -374,7 +393,10 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "shortToIntSeq", false); emitSchemas("tns:_internal.Test.Seq2Type", "tns:_internal.Test.Seq2Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -398,7 +420,10 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "intToLongSeq", false); emitSchemas("tns:_internal.Test.Seq3Type", "tns:_internal.Test.Seq3Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -422,7 +447,10 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "longToByteSeq", false); emitSchemas("tns:_internal.Test.Seq4Type", "tns:_internal.Test.Seq4Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -451,7 +479,8 @@ transformPrimitiveSequence(const DBEnvironmentPtr& dbEnv) emitSchemas("tns:_internal.Test.Seq4Type", "tns:_internal.Test.Seq4Type"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -483,7 +512,6 @@ static void transformEnum(const DBEnvironmentPtr& dbEnv) { DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming enumerations... " << flush; @@ -506,7 +534,10 @@ transformEnum(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "enum", false); emitSchemas("tns:_internal.Test.E1Type", "tns:_internal.Test.E1Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -529,7 +560,8 @@ transformEnum(const DBEnvironmentPtr& dbEnv) emitSchemas("tns:_internal.Test.E1Type", "tns:_internal.Test.E1Type"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -561,7 +593,6 @@ static void transformDictionary(const DBEnvironmentPtr& dbEnv) { DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming dictionaries... " << flush; @@ -586,7 +617,10 @@ transformDictionary(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "dict", false); emitSchemas("tns:_internal.Test.D1Type", "tns:_internal.Test.D1Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -611,7 +645,8 @@ transformDictionary(const DBEnvironmentPtr& dbEnv) emitSchemas("tns:_internal.Test.D1Type", "tns:_internal.Test.D1Type"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -643,7 +678,6 @@ static void transformStruct(const DBEnvironmentPtr& dbEnv) { DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming structs... " << flush; @@ -674,7 +708,10 @@ transformStruct(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "struct", false); emitSchemas("tns:_internal.Test.S1Type", "tns:_internal.Test.S1Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -704,7 +741,8 @@ transformStruct(const DBEnvironmentPtr& dbEnv) emitSchemas("tns:_internal.Test.S1Type", "tns:_internal.Test.S1Type"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -751,7 +789,6 @@ static void transformClass(const DBEnvironmentPtr& dbEnv) { DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq dummy; cout << "transforming classes... " << flush; @@ -834,7 +871,10 @@ transformClass(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "class", false); emitSchemas("tns:_internal.Test.C1Type", "tns:_internal.Test.C1Type"); - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); + } db->close(); db = 0; @@ -880,7 +920,8 @@ transformClass(const DBEnvironmentPtr& dbEnv) emitSchemas("tns:_internal.Test.C1Type", "tns:_internal.Test.C1Type"); try { - transformer.transform(dbEnv, db, dummy, dummy, paths, paths, oldSchema, newSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, dummy, dummy, paths, paths, false); + transformer.transform(oldSchema, newSchema); test(false); } catch(const XMLTransform::IllegalTransform&) @@ -927,7 +968,6 @@ static void transformEvictor(const DBEnvironmentPtr& dbEnv) { DBPtr db; - XMLTransform::DBTransformer transformer; StringSeq loadOld, loadNew; Identity ident; EvictorPtr evictor; @@ -1032,7 +1072,10 @@ transformEvictor(const DBEnvironmentPtr& dbEnv) db = 0; db = dbEnv->openDBWithTxn(0, "evictor", false); - transformer.transform(dbEnv, db, loadOld, loadNew, paths, paths, evictorSchema); + { + XMLTransform::DBTransformer transformer(dbEnv, db, loadOld, loadNew, paths, paths, false); + transformer.transform(evictorSchema); + } db->close(); db = 0; @@ -1081,7 +1124,8 @@ transformEvictor(const DBEnvironmentPtr& dbEnv) db = dbEnv->openDBWithTxn(0, "failure", false); try { - transformer.transform(dbEnv, db, loadOld, loadNew, paths, paths, evictorSchema); + XMLTransform::DBTransformer transformer(dbEnv, db, loadOld, loadNew, paths, paths, false); + transformer.transform(evictorSchema); test(false); } catch(const XMLTransform::IllegalTransform&) |