summaryrefslogtreecommitdiff
path: root/cpp/src/FreezeScript/Transformer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/FreezeScript/Transformer.cpp')
-rw-r--r--cpp/src/FreezeScript/Transformer.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/cpp/src/FreezeScript/Transformer.cpp b/cpp/src/FreezeScript/Transformer.cpp
new file mode 100644
index 00000000000..01a1c7519f1
--- /dev/null
+++ b/cpp/src/FreezeScript/Transformer.cpp
@@ -0,0 +1,310 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Transformer.h>
+#include <FreezeScript/TransformDescriptors.h>
+#include <FreezeScript/Exception.h>
+#include <FreezeScript/TransformAnalyzer.h>
+#include <FreezeScript/Util.h>
+#include <db_cxx.h>
+
+using namespace std;
+
+namespace FreezeScript
+{
+
+class DescriptorHandler : public IceXML::Handler
+{
+public:
+
+ DescriptorHandler(const DataFactoryPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&, const ErrorReporterPtr&);
+
+ virtual void startElement(const std::string&, const IceXML::Attributes&, int, int);
+ virtual void endElement(const std::string&, int, int);
+ virtual void characters(const std::string&, int, int);
+ virtual void error(const std::string&, int, int);
+
+ TransformDBDescriptorPtr descriptor() const;
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ ErrorReporterPtr _errorReporter;
+ DescriptorPtr _current;
+ TransformDBDescriptorPtr _descriptor;
+};
+
+} // End of namespace FreezeScript
+
+//
+// DescriptorHandler
+//
+FreezeScript::DescriptorHandler::DescriptorHandler(const DataFactoryPtr& factory, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit,
+ const ErrorReporterPtr& errorReporter) :
+ _factory(factory), _old(oldUnit), _new(newUnit), _errorReporter(errorReporter)
+{
+}
+
+void
+FreezeScript::DescriptorHandler::startElement(const string& name, const IceXML::Attributes& attributes, int line,
+ int column)
+{
+ DescriptorPtr d;
+
+ if(name == "transformdb")
+ {
+ if(_current)
+ {
+ _errorReporter->descriptorError("<transformdb> must be the top-level element", line);
+ }
+
+ _descriptor = new TransformDBDescriptor(line, _factory, _errorReporter, attributes, _old, _new);
+ d = _descriptor;
+ }
+ else if(name == "database")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<database> must be a child of <transformdb>", line);
+ }
+
+ d = new DatabaseDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "record")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<record> must be a child of <database>", line);
+ }
+
+ d = new RecordDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "transform")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<transform> must be a child of <transformdb>", line);
+ }
+
+ d = new TransformDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "init")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<init> must be a child of <transformdb>", line);
+ }
+
+ d = new InitDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "set")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<set> cannot be a top-level element", line);
+ }
+
+ d = new SetDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "define")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<define> cannot be a top-level element", line);
+ }
+
+ d = new DefineDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "add")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<add> cannot be a top-level element", line);
+ }
+
+ d = new AddDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "remove")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<remove> cannot be a top-level element", line);
+ }
+
+ d = new RemoveDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "delete")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<delete> cannot be a top-level element", line);
+ }
+
+ d = new DeleteDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "fail")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<fail> cannot be a top-level element", line);
+ }
+
+ d = new FailDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "echo")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<echo> cannot be a top-level element", line);
+ }
+
+ d = new EchoDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "if")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<if> cannot be a top-level element", line);
+ }
+
+ d = new IfDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "iterate")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<iterate> cannot be a top-level element", line);
+ }
+
+ d = new IterateDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else
+ {
+ _errorReporter->descriptorError("unknown descriptor `" + name + "'", line);
+ }
+
+ if(_current)
+ {
+ _current->addChild(d);
+ }
+ _current = d;
+}
+
+void
+FreezeScript::DescriptorHandler::endElement(const std::string& name, int, int)
+{
+ assert(_current);
+ _current = _current->parent();
+}
+
+void
+FreezeScript::DescriptorHandler::characters(const std::string&, int, int)
+{
+}
+
+void
+FreezeScript::DescriptorHandler::error(const std::string& msg, int line, int col)
+{
+ _errorReporter->descriptorError(msg, line);
+}
+
+FreezeScript::TransformDBDescriptorPtr
+FreezeScript::DescriptorHandler::descriptor() const
+{
+ return _descriptor;
+}
+
+//
+// Transformer
+//
+FreezeScript::Transformer::Transformer(const Ice::CommunicatorPtr& communicator, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit, bool ignoreTypeChanges, bool purgeObjects) :
+ _communicator(communicator), _old(oldUnit), _new(newUnit), _ignoreTypeChanges(ignoreTypeChanges),
+ _purgeObjects(purgeObjects)
+{
+ createCoreSliceTypes(_old);
+ createCoreSliceTypes(_new);
+
+ createEvictorSliceTypes(_old);
+ createEvictorSliceTypes(_new);
+}
+
+void
+FreezeScript::Transformer::analyze(const string& oldKey, const string& newKey, const string& oldValue,
+ const string& newValue, ostream& descriptors, Ice::StringSeq& missingTypes,
+ Ice::StringSeq& errors)
+{
+ //
+ // Look up the Slice definitions for the key and value types.
+ //
+ Slice::TypePtr oldKeyType = findType(_old, oldKey, errors);
+ Slice::TypePtr newKeyType = findType(_new, newKey, errors);
+ Slice::TypePtr oldValueType = findType(_old, oldValue, errors);
+ Slice::TypePtr newValueType = findType(_new, newValue, errors);
+ if(!oldKeyType || !newKeyType || !oldValueType || !newValueType)
+ {
+ return;
+ }
+
+ TransformAnalyzer analyzer(_old, _new, _ignoreTypeChanges);
+ analyzer.analyze(oldKeyType, newKeyType, oldValueType, newValueType, descriptors, missingTypes, errors);
+}
+
+void
+FreezeScript::Transformer::analyze(ostream& descriptors, Ice::StringSeq& missingTypes, Ice::StringSeq& errors)
+{
+ const string keyType = "::Freeze::EvictorStorageKey";
+ const string valueType = "::Freeze::ObjectRecord";
+ analyze(keyType, keyType, valueType, valueType, descriptors, missingTypes, errors);
+}
+
+void
+FreezeScript::Transformer::transform(istream& is, Db* db, DbTxn* txn, Db* dbNew, DbTxn* txnNew, ostream& errors,
+ bool suppress)
+{
+ ErrorReporterPtr errorReporter = new ErrorReporter(errors, suppress);
+
+ try
+ {
+ DataFactoryPtr factory = new DataFactory(_communicator, _new, errorReporter);
+ DescriptorHandler dh(factory, _old, _new, errorReporter);
+ IceXML::Parser::parse(is, dh);
+
+ TransformDBDescriptorPtr descriptor = dh.descriptor();
+ descriptor->validate();
+ descriptor->transform(_communicator, db, txn, dbNew, txnNew, _purgeObjects);
+ }
+ catch(const IceXML::ParserException& ex)
+ {
+ errorReporter->error(ex.reason());
+ }
+}
+
+Slice::TypePtr
+FreezeScript::Transformer::findType(const Slice::UnitPtr& u, const string& type, Ice::StringSeq& errors)
+{
+ Slice::TypeList l;
+
+ l = u->lookupType(type, false);
+ if(l.empty())
+ {
+ errors.push_back("error: unknown type `" + type + "'");
+ return 0;
+ }
+
+ return l.front();
+}