summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/datamodel
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-12-15 19:10:50 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-12-15 19:10:50 (GMT)
commitf1700edcd08d6215888e226618555ba43b5324ec (patch)
tree738f30de64f699c3f56d2e15963537c9493a24b4 /src/uscxml/plugins/datamodel
parent2855a9ff7b423140237c9e988252fde0cbacd0a1 (diff)
downloaduscxml-f1700edcd08d6215888e226618555ba43b5324ec.zip
uscxml-f1700edcd08d6215888e226618555ba43b5324ec.tar.gz
uscxml-f1700edcd08d6215888e226618555ba43b5324ec.tar.bz2
Refactoring and plugin support
Diffstat (limited to 'src/uscxml/plugins/datamodel')
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp409
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h92
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp219
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h61
4 files changed, 781 insertions, 0 deletions
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
new file mode 100644
index 0000000..e25ece4
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -0,0 +1,409 @@
+#include "uscxml/Common.h"
+#include "V8DataModel.h"
+#include "dom/V8SCXMLDOM.h"
+#include "uscxml/Message.h"
+#include <glog/logging.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include <Pluma/Connector.hpp>
+#endif
+
+namespace uscxml {
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_CONNECTOR
+bool connect(pluma::Host& host){
+ host.add( new V8DataModelProvider() );
+ return true;
+}
+#endif
+
+V8DataModel::V8DataModel() {
+// _contexts.push_back(v8::Context::New());
+}
+
+DataModel* V8DataModel::create(Interpreter* interpreter) {
+ V8DataModel* dm = new V8DataModel();
+ dm->_interpreter = interpreter;
+ v8::Locker locker;
+ v8::HandleScope scope;
+
+ // see http://stackoverflow.com/questions/3171418/v8-functiontemplate-class-instance
+// dm->_globalTemplate = v8::Persistent<v8::ObjectTemplate>(v8::ObjectTemplate::New());
+// dm->_globalTemplate->Set(v8::String::New("In"), v8::FunctionTemplate::New(jsIn, v8::External::New(reinterpret_cast<void*>(this))));
+
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
+ global->Set(v8::String::New("In"), v8::FunctionTemplate::New(jsIn, v8::External::New(reinterpret_cast<void*>(dm))));
+ global->Set(v8::String::New("print"), v8::FunctionTemplate::New(jsPrint, v8::External::New(reinterpret_cast<void*>(dm))));
+ global->Set(v8::String::New("document"), V8SCXMLDOM::getDocument(interpreter->getDocument()));
+
+ dm->_contexts.push_back(v8::Context::New(NULL, global));
+ dm->setName(interpreter->getName());
+ dm->setSessionId(interpreter->getSessionId());
+ dm->eval("_ioprocessors = {};");
+
+ return dm;
+}
+
+void V8DataModel::setSessionId(const std::string& sessionId) {
+ _sessionId = sessionId;
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+ v8::Handle<v8::Object> global = _contexts.front()->Global();
+
+ global->Set(v8::String::New("_sessionid"), v8::String::New(sessionId.c_str()));
+}
+
+void V8DataModel::setName(const std::string& name) {
+ _name = name;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+ v8::Handle<v8::Object> global = _contexts.front()->Global();
+
+ global->Set(v8::String::New("_name"), v8::String::New(name.c_str()));
+}
+
+V8DataModel::~V8DataModel() {
+ while(_contexts.size() > 0) {
+ _contexts.back().Dispose();
+ _contexts.pop_back();
+ }
+}
+
+void V8DataModel::pushContext() {
+ _contexts.push_back(_contexts.back().New(_contexts.back()));
+}
+
+void V8DataModel::popContext() {
+ if (_contexts.size() > 1) {
+ _contexts.back().Dispose();
+ _contexts.pop_back();
+ }
+}
+
+void V8DataModel::initialize() {
+}
+
+void V8DataModel::setEvent(const Event& event) {
+ _event = event;
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+ v8::Handle<v8::Object> global = _contexts.front()->Global();
+
+ // this is unfortunate - can't we store the template in the object?
+ if (_eventTemplate.IsEmpty()) {
+ v8::Handle<v8::ObjectTemplate> localEventTemplate = v8::ObjectTemplate::New();
+ localEventTemplate->SetInternalFieldCount(1); // we only have a single C++ object
+ localEventTemplate->SetAccessor(v8::String::New("name"), V8DataModel::jsGetEventName);
+ localEventTemplate->SetAccessor(v8::String::New("type"), V8DataModel::jsGetEventType);
+ localEventTemplate->SetAccessor(v8::String::New("sendid"), V8DataModel::jsGetEventSendId);
+ localEventTemplate->SetAccessor(v8::String::New("origin"), V8DataModel::jsGetEventOrigin);
+ localEventTemplate->SetAccessor(v8::String::New("origintype"), V8DataModel::jsGetEventOriginType);
+ localEventTemplate->SetAccessor(v8::String::New("invokeid"), V8DataModel::jsGetEventInvokeId);
+ _eventTemplate = v8::Persistent<v8::ObjectTemplate>::New(localEventTemplate);
+ }
+
+ assert(_eventTemplate->InternalFieldCount() == 1);
+ v8::Handle<v8::Object> eventJS = _eventTemplate->NewInstance();
+ eventJS->SetInternalField(0, v8::External::New(&_event));
+
+ eventJS->Set(v8::String::New("data"), getDataAsValue(event)); // set data part of _event
+ global->Set(v8::String::New("_event"), eventJS);
+}
+
+Data V8DataModel::getStringAsData(const std::string& content) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+ v8::Handle<v8::Value> result = evalAsValue(content);
+ Data data = getValueAsData(result);
+ return data;
+}
+
+Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value) {
+ Data data;
+ if (false) {
+ } else if (value->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+ for (int i = 0; i < array->Length(); i++) {
+ data.array.push_back(getValueAsData(array->Get(i)));
+ }
+ } else if (value->IsBoolean()) {
+ data.atom = (value->ToBoolean()->Value() ? "true" : "false");
+ } else if (value->IsBooleanObject()) {
+ LOG(ERROR) << "IsBooleanObject is unimplemented" << std::endl;
+ } else if (value->IsDate()) {
+ LOG(ERROR) << "IsDate is unimplemented" << std::endl;
+ } else if (value->IsExternal()) {
+ LOG(ERROR) << "IsExternal is unimplemented" << std::endl;
+ } else if (value->IsFalse()) {
+ LOG(ERROR) << "IsFalse is unimplemented" << std::endl;
+ } else if (value->IsFunction()) {
+ LOG(ERROR) << "IsFunction is unimplemented" << std::endl;
+ } else if (value->IsInt32()) {
+ int32_t prop = value->Int32Value();
+ data.atom = toStr(prop);
+ } else if (value->IsNativeError()) {
+ LOG(ERROR) << "IsNativeError is unimplemented" << std::endl;
+ } else if (value->IsNull()) {
+ LOG(ERROR) << "IsNull is unimplemented" << std::endl;
+ } else if (value->IsNumber()) {
+ v8::String::AsciiValue prop(v8::Handle<v8::String>::Cast(v8::Handle<v8::Number>::Cast(value)));
+ data.atom = *prop;
+ } else if (value->IsNumberObject()) {
+ LOG(ERROR) << "IsNumberObject is unimplemented" << std::endl;
+ } else if (value->IsObject()) {
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
+ v8::Local<v8::Array> properties = object->GetPropertyNames();
+ for (int i = 0; i < properties->Length(); i++) {
+ assert(properties->Get(i)->IsString());
+ v8::String::AsciiValue key(v8::Handle<v8::String>::Cast(properties->Get(i)));
+ v8::Local<v8::Value> property = object->Get(properties->Get(i));
+ data.compound[*key] = getValueAsData(property);
+ }
+ } else if (value->IsRegExp()) {
+ LOG(ERROR) << "IsRegExp is unimplemented" << std::endl;
+ } else if(value->IsString()) {
+ v8::String::AsciiValue property(v8::Handle<v8::String>::Cast(value));
+ data.atom = *property;
+ } else if(value->IsStringObject()) {
+ LOG(ERROR) << "IsStringObject is unimplemented" << std::endl;
+ } else if(value->IsTrue()) {
+ LOG(ERROR) << "IsTrue is unimplemented" << std::endl;
+ } else if(value->IsUint32()) {
+ LOG(ERROR) << "IsUint32 is unimplemented" << std::endl;
+ } else if(value->IsUndefined()) {
+ LOG(ERROR) << "IsUndefined is unimplemented" << std::endl;
+ }
+ return data;
+}
+
+v8::Handle<v8::Value> V8DataModel::getDataAsValue(const Data& data) {
+ if (data.compound.size() > 0) {
+ v8::Handle<v8::Object> value = v8::Object::New();
+ std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
+ while(compoundIter != data.compound.end()) {
+ value->Set(v8::String::New(compoundIter->first.c_str()), getDataAsValue(compoundIter->second));
+ compoundIter++;
+ }
+ return value;
+ }
+ if (data.array.size() > 0) {
+ v8::Handle<v8::Object> value = v8::Array::New();
+ std::list<Data>::const_iterator arrayIter = data.array.begin();
+ uint32_t index = 0;
+ while(arrayIter != data.array.end()) {
+ value->Set(index++, getDataAsValue(*arrayIter));
+ arrayIter++;
+ }
+ return value;
+ }
+ if (data.type == Data::VERBATIM) {
+ return v8::String::New(data.atom.c_str());
+ } else {
+ return evalAsValue(data.atom);
+ }
+}
+
+v8::Handle<v8::Value> V8DataModel::jsPrint(const v8::Arguments& args) {
+ if (args.Length() > 0) {
+ v8::String::AsciiValue printMsg(args[0]->ToString());
+ std::cout << *printMsg;
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> V8DataModel::jsIn(const v8::Arguments& args) {
+ V8DataModel* INSTANCE = static_cast<V8DataModel*>(v8::External::Unwrap(args.Data()));
+ for (unsigned int i = 0; i < args.Length(); i++) {
+ if (args[i]->IsString()) {
+ std::string stateName(*v8::String::AsciiValue(args[i]->ToString()));
+ if (Interpreter::isMember(INSTANCE->_interpreter->getState(stateName), INSTANCE->_interpreter->getConfiguration())) {
+ continue;
+ }
+ }
+ return v8::Boolean::New(false);
+ }
+ return v8::Boolean::New(true);
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventName(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(event->name.c_str());
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventType(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ switch (event->type) {
+ case Event::PLATFORM:
+ return v8::String::New("platform");
+ break;
+ case Event::INTERNAL:
+ return v8::String::New("internal");
+ break;
+ case Event::EXTERNAL:
+ return v8::String::New("external");
+ break;
+ default:
+ return v8::String::New("");
+ break;
+ }
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventSendId(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(event->sendid.c_str());
+
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventOrigin(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(event->origin.c_str());
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventOriginType(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(event->origintype.c_str());
+}
+
+v8::Handle<v8::Value> V8DataModel::jsGetEventInvokeId(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info) {
+ Event* event = static_cast<Event*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(event->invokeid.c_str());
+}
+
+bool V8DataModel::validate(const std::string& location, const std::string& schema) {
+ return true;
+}
+
+uint32_t V8DataModel::getLength(const std::string& expr) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.back());
+ v8::Handle<v8::Array> result = evalAsValue(expr).As<v8::Array>();
+ return result->Length();
+}
+
+void V8DataModel::eval(const std::string& expr) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.back());
+ evalAsValue(expr);
+}
+
+bool V8DataModel::evalAsBool(const std::string& expr) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.back());
+ v8::Handle<v8::Value> result = evalAsValue(expr);
+ return(result->ToBoolean()->BooleanValue());
+}
+
+std::string V8DataModel::evalAsString(const std::string& expr) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.back());
+ v8::Handle<v8::Value> result = evalAsValue(expr);
+ v8::String::AsciiValue data(result->ToString());
+ return std::string(*data);
+}
+
+void V8DataModel::assign(const std::string& location, const Data& data) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+
+ std::stringstream ssJSON;
+ ssJSON << data;
+ assign(location, ssJSON.str());
+// v8::Handle<v8::Object> variable = evalAsValue(location).As<v8::Object>();
+// assert(!variable.IsEmpty());
+// if (data.compound.size() > 0) {
+// std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
+// while(compoundIter != data.compound.end()) {
+// variable->Set(v8::String::New(compoundIter->first.c_str()), getDataAsValue(compoundIter->second));
+// compoundIter++;
+// }
+// return;
+// } else if (data.array.size() > 0) {
+// std::list<Data>::const_iterator arrayIter = data.array.begin();
+// uint32_t index = 0;
+// while(arrayIter != data.array.end()) {
+// variable->Set(index++, getDataAsValue(*arrayIter));
+// arrayIter++;
+// }
+// } else if (data.type == Data::VERBATIM) {
+// assign(location, "'" + data.atom + "'");
+// } else {
+// assign(location, data.atom);
+// }
+
+}
+
+void V8DataModel::assign(const std::string& location, const std::string& expr) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.back());
+ evalAsValue((location + " = " + expr).c_str());
+}
+
+v8::Handle<v8::Value> V8DataModel::evalAsValue(const std::string& expr) {
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::String> source = v8::String::New(expr.c_str());
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
+
+ v8::Handle<v8::Value> result;
+ if (!script.IsEmpty())
+ result = script->Run();
+
+ if (script.IsEmpty() || result.IsEmpty()) {
+ // throw an exception
+ assert(tryCatch.HasCaught());
+ Event exceptionEvent;
+ exceptionEvent.name = "error.execution";
+
+ std::string exceptionString(*v8::String::AsciiValue(tryCatch.Exception()));
+ exceptionEvent.compound["exception"] = Data(exceptionString, Data::VERBATIM);;
+
+ v8::Handle<v8::Message> message = tryCatch.Message();
+ if (!message.IsEmpty()) {
+ std::string filename(*v8::String::AsciiValue(message->GetScriptResourceName()));
+ exceptionEvent.compound["filename"] = Data(filename, Data::VERBATIM);
+
+ std::string sourceLine(*v8::String::AsciiValue(message->GetSourceLine()));
+ exceptionEvent.compound["sourceline"] = Data(sourceLine, Data::VERBATIM);
+
+ std::stringstream ssLineNumber;
+ int lineNumber = message->GetLineNumber();
+ ssLineNumber << lineNumber;
+ exceptionEvent.compound["linenumber"] = Data(ssLineNumber.str());
+
+ int startColumn = message->GetStartColumn();
+ int endColumn = message->GetEndColumn();
+ std::stringstream ssUnderline;
+ for (int i = 0; i < startColumn; i++)
+ ssUnderline << " ";
+ for (int i = startColumn; i < endColumn; i++)
+ ssUnderline << "^";
+ exceptionEvent.compound["sourcemark"] = Data(ssUnderline.str(), Data::VERBATIM);
+
+ std::string stackTrace(*v8::String::AsciiValue(tryCatch.StackTrace()));
+ exceptionEvent.compound["stacktrace"] = Data(stackTrace, Data::VERBATIM);
+
+ }
+
+ _interpreter->receiveInternal(exceptionEvent);
+ throw(exceptionEvent);
+ }
+
+ return result;
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
new file mode 100644
index 0000000..994ed18
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
@@ -0,0 +1,92 @@
+#ifndef V8DATAMODEL_H_KN8TWG0V
+#define V8DATAMODEL_H_KN8TWG0V
+
+#include "uscxml/Interpreter.h"
+#include <list>
+#include <v8.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+namespace uscxml {
+ class Event;
+ class Data;
+ class V8SCXMLDOM;
+}
+
+namespace uscxml {
+
+class V8DataModel : public DataModel {
+public:
+ V8DataModel();
+ virtual ~V8DataModel();
+ virtual DataModel* create(Interpreter* interpreter);
+
+ virtual std::set<std::string> getNames() {
+ std::set<std::string> names;
+ names.insert("ecmascript");
+ return names;
+ }
+
+ virtual void initialize();
+ virtual void setSessionId(const std::string& sessionId);
+ virtual void setName(const std::string& name);
+ virtual void setEvent(const Event& event);
+
+ virtual bool validate(const std::string& location, const std::string& schema);
+
+ virtual uint32_t getLength(const std::string& expr);
+ virtual void pushContext();
+ virtual void popContext();
+
+ virtual void eval(const std::string& expr);
+ virtual void assign(const std::string& location, const std::string& expr);
+ virtual void assign(const std::string& location, const Data& data);
+
+ virtual Data getStringAsData(const std::string& content);
+ virtual Data getValueAsData(const v8::Handle<v8::Value>& value);
+
+ virtual std::string evalAsString(const std::string& expr);
+ virtual bool evalAsBool(const std::string& expr);
+
+ static v8::Handle<v8::Value> jsGetEventName(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsGetEventType(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsGetEventSendId(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsGetEventOrigin(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsGetEventOriginType(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsGetEventInvokeId(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+
+ static v8::Handle<v8::Value> jsIn(const v8::Arguments& args);
+ static v8::Handle<v8::Value> jsPrint(const v8::Arguments& args);
+
+
+protected:
+ std::list<v8::Persistent<v8::Context> > _contexts;
+ Interpreter* _interpreter;
+
+ std::string _sessionId;
+ std::string _name;
+
+ Event _event;
+ v8::Persistent<v8::ObjectTemplate> _globalTemplate;
+ v8::Persistent<v8::ObjectTemplate> _eventTemplate;
+
+ v8::Handle<v8::Value> evalAsValue(const std::string& expr);
+ virtual v8::Handle<v8::Value> getDataAsValue(const Data& data);
+
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(V8DataModel, DataModel);
+#endif
+
+}
+
+#endif /* end of include guard: V8DATAMODEL_H_KN8TWG0V */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp
new file mode 100644
index 0000000..6452330
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp
@@ -0,0 +1,219 @@
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+#include "V8SCXMLDOM.h"
+
+#define ASSERT_ARGS1(args, type1) \
+assert(args.Length() == 1); \
+assert(args[0]->type1());
+
+#define ASSERT_ARGS2(args, type1, type2) \
+assert(args.Length() == 2); \
+assert(args[0]->type1()); \
+assert(args[1]->type2());
+
+namespace uscxml {
+
+ using namespace Arabica::DOM;
+ using namespace Arabica::XPath;
+
+ V8SCXMLDOM::V8SCXMLDOM() {
+ }
+
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getDocument(Arabica::DOM::Document<std::string>& document) {
+ v8::Handle<v8::ObjectTemplate> documentTmpl = v8::ObjectTemplate::New();
+ documentTmpl->Set(v8::String::New("createElement"), v8::FunctionTemplate::New(jsDocumentCreateElement, v8::External::New(reinterpret_cast<void*>(&document))));
+ documentTmpl->Set(v8::String::New("evaluate"), v8::FunctionTemplate::New(jsDocumentEvaluate, v8::External::New(reinterpret_cast<void*>(&document))));
+ return documentTmpl;
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsDocumentCreateElement(const v8::Arguments& args) {
+ assert(!args.Data().IsEmpty());
+ assert(args.Data()->IsExternal());
+
+ ASSERT_ARGS1(args, IsString)
+
+ Document<std::string>* document = static_cast<Document<std::string>*>(v8::External::Unwrap(args.Data()));
+ v8::Persistent<v8::Object> elementJS = v8::Persistent<v8::Object>::New(getElementTmpl()->NewInstance());
+
+ v8::String::AsciiValue tagName(args[0]);
+ Element<std::string>* element = new Element<std::string>(document->createElement(*tagName));
+
+ elementJS->SetInternalField(0, v8::External::New(element));
+ elementJS.MakeWeak(NULL, jsElementDestructor);
+ return elementJS;
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsDocumentEvaluate(const v8::Arguments& args) {
+ assert(!args.Data().IsEmpty());
+ assert(args.Data()->IsExternal());
+
+ assert(args.Length() > 0);
+ assert(args[0]->IsString());
+
+
+ Document<std::string>* document = static_cast<Document<std::string>*>(v8::External::Unwrap(args.Data()));
+ Node<std::string> context;
+ if (args.Length() > 1) {
+ assert(args[1]->ToObject()->InternalFieldCount() == 1);
+ context = *static_cast<Node<std::string>*>(v8::Local<v8::External>::Cast(args[1]->ToObject()->GetInternalField(0))->Value());
+ } else {
+ context = *document;
+ }
+ v8::String::AsciiValue xpathExpr(args[0]);
+ XPath<std::string> xpath;
+ XPathValue<std::string>* xpathValue = new XPathValue<std::string>(xpath.evaluate(*xpathExpr, context));
+
+ v8::Persistent<v8::Object> xpathValueJS = v8::Persistent<v8::Object>::New(getXPathValueTmpl()->NewInstance());
+ xpathValueJS->SetInternalField(0, v8::External::New(xpathValue));
+ xpathValueJS.MakeWeak(NULL, jsXPathValueDestructor);
+ return xpathValueJS;
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsElementTagName(v8::Local<v8::String> property, const v8::AccessorInfo &info) {
+ Element<std::string>* element = static_cast<Element<std::string>*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+ return v8::String::New(element->getTagName().c_str());
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsElementGetAttribute(const v8::Arguments& args) {
+ assert(!args.Data().IsEmpty());
+ assert(args.Data()->IsExternal());
+
+ ASSERT_ARGS1(args, IsString);
+
+ Element<std::string>* element = static_cast<Element<std::string>*>(v8::External::Unwrap(args.Data()));
+
+ v8::String::AsciiValue attribute(args[0]);
+ if (element->hasAttribute(*attribute)) {
+ return v8::String::New(element->getAttribute(*attribute).c_str());
+ }
+ return v8::String::New("");
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsElementSetAttribute(const v8::Arguments& args) {
+ v8::Local<v8::Object> self = args.Holder();
+ assert(self->InternalFieldCount() == 1);
+
+ ASSERT_ARGS2(args, IsString, IsString);
+
+ v8::String::AsciiValue attribute(args[0]);
+ v8::String::AsciiValue value(args[1]);
+
+ Element<std::string>* element = static_cast<Element<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
+ element->setAttribute(*attribute, *value);
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsXPathValueAsNodeSet(const v8::Arguments& args) {
+ v8::Local<v8::Object> self = args.Holder();
+ assert(self->InternalFieldCount() == 1);
+ XPathValue<std::string>* xPathValue = static_cast<XPathValue<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
+
+ v8::Persistent<v8::Object> nodeSetJS = v8::Persistent<v8::Object>::New(getNodeSetTmpl()->NewInstance());
+ nodeSetJS->SetInternalField(0, v8::External::New(new NodeSet<std::string>(xPathValue->asNodeSet())));
+ nodeSetJS.MakeWeak(NULL, jsNodeSetDestructor);
+ return nodeSetJS;
+
+ }
+
+ void V8SCXMLDOM::jsNodeSetDestructor(v8::Persistent<v8::Value> object, void* data) {
+ NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
+ delete nodeSet;
+ }
+
+ void V8SCXMLDOM::jsNodeDestructor(v8::Persistent<v8::Value> object, void* data) {
+ Node<std::string>* node = static_cast<Node<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
+ delete node;
+ }
+
+ void V8SCXMLDOM::jsXPathValueDestructor(v8::Persistent<v8::Value> object, void* data) {
+ XPathValue<std::string>* xPathValue = static_cast<XPathValue<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
+ delete xPathValue;
+ }
+
+ void V8SCXMLDOM::jsElementDestructor(v8::Persistent<v8::Value> object, void* data) {
+ Element<std::string>* element = static_cast<Element<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
+ delete element;
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsNodeSetGetIndex(uint32_t index, const v8::AccessorInfo &info) {
+ v8::Local<v8::Object> self = info.Holder();
+ assert(self->InternalFieldCount() == 1);
+ NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
+
+ if (nodeSet->size() >= index) {
+ Node<std::string>* node = new Node<std::string>((*nodeSet)[index]);
+ v8::Persistent<v8::Object> nodeJS = v8::Persistent<v8::Object>::New(getNodeTmpl()->NewInstance());
+ nodeJS->SetInternalField(0, v8::External::New(node));
+ nodeJS.MakeWeak(NULL, jsNodeDestructor);
+ return nodeJS;
+ }
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsNodeSetLength(const v8::Arguments& args) {
+ v8::Local<v8::Object> self = args.Holder();
+ assert(self->InternalFieldCount() == 1);
+ NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
+ return v8::Integer::New(nodeSet->size());
+ }
+
+ v8::Handle<v8::Value> V8SCXMLDOM::jsNodeAppendChild(const v8::Arguments& args) {
+ v8::Local<v8::Object> self = args.Holder();
+ assert(self->InternalFieldCount() == 1);
+ Node<std::string>* node = static_cast<Node<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
+
+ assert(args.Length() == 1);
+ assert(args[0]->IsObject());
+
+ Node<std::string>* childToAppend = static_cast<Node<std::string>*>(v8::External::Unwrap(args[0]->ToObject()->GetInternalField(0)));
+ node->appendChild(*childToAppend);
+
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::xPathValueTmpl;
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getXPathValueTmpl() {
+ if (xPathValueTmpl.IsEmpty()) {
+ xPathValueTmpl = v8::ObjectTemplate::New();
+ xPathValueTmpl->SetInternalFieldCount(1);
+ xPathValueTmpl->Set(v8::String::New("asNodeSet"), v8::FunctionTemplate::New(jsXPathValueAsNodeSet));
+ }
+ return xPathValueTmpl;
+ }
+
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::nodeSetTmpl;
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getNodeSetTmpl() {
+ if (nodeSetTmpl.IsEmpty()) {
+ nodeSetTmpl = v8::ObjectTemplate::New();
+ nodeSetTmpl->SetInternalFieldCount(1);
+ nodeSetTmpl->SetIndexedPropertyHandler(jsNodeSetGetIndex);
+ nodeSetTmpl->Set(v8::String::New("length"), v8::FunctionTemplate::New(jsNodeSetLength));
+ }
+ return nodeSetTmpl;
+ }
+
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::nodeTmpl;
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getNodeTmpl() {
+ if (nodeTmpl.IsEmpty()) {
+ nodeTmpl = v8::ObjectTemplate::New();
+ nodeTmpl->SetInternalFieldCount(1);
+ nodeTmpl->Set(v8::String::New("appendChild"), v8::FunctionTemplate::New(jsNodeAppendChild));
+ }
+ return nodeTmpl;
+ }
+
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::elementTmpl;
+ v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getElementTmpl() {
+ if (elementTmpl.IsEmpty()) {
+ elementTmpl = v8::ObjectTemplate::New();
+ elementTmpl->SetAccessor(v8::String::New("tagName"), V8SCXMLDOM::jsElementTagName);
+ elementTmpl->Set(v8::String::New("getAttribute"), v8::FunctionTemplate::New(jsElementGetAttribute));
+ elementTmpl->Set(v8::String::New("setAttribute"), v8::FunctionTemplate::New(jsElementSetAttribute));
+ elementTmpl->SetInternalFieldCount(1);
+ }
+ return elementTmpl;
+ }
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h
new file mode 100644
index 0000000..c513e48
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h
@@ -0,0 +1,61 @@
+#ifndef V8SCXMLDOM_H_AREM0ZC4
+#define V8SCXMLDOM_H_AREM0ZC4
+
+#include "uscxml/Interpreter.h"
+
+#include <DOM/Document.hpp>
+#include <v8.h>
+
+#include <list>
+
+namespace uscxml {
+
+class V8SCXMLDOM {
+public:
+ V8SCXMLDOM();
+ virtual ~V8SCXMLDOM() {};
+
+ static v8::Handle<v8::ObjectTemplate> getDocument(Arabica::DOM::Document<std::string>& document);
+ static v8::Handle<v8::Value> jsDocumentCreateElement(const v8::Arguments& args);
+ static v8::Handle<v8::Value> jsDocumentEvaluate(const v8::Arguments& args);
+
+ static v8::Handle<v8::Value> jsElementTagName(v8::Local<v8::String> property, const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsElementGetAttribute(const v8::Arguments& args);
+ static v8::Handle<v8::Value> jsElementSetAttribute(const v8::Arguments& args);
+ static void jsElementDestructor(v8::Persistent<v8::Value> object, void* data);
+
+ static v8::Handle<v8::Value> jsXPathValueAsNodeSet(const v8::Arguments& args);
+ static void jsXPathValueDestructor(v8::Persistent<v8::Value> object, void* data);
+
+ static v8::Handle<v8::Value> jsNodeSetGetIndex(uint32_t index, const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> jsNodeSetLength(const v8::Arguments& args);
+ static void jsNodeSetDestructor(v8::Persistent<v8::Value> object, void* data);
+
+ static v8::Handle<v8::Value> jsNodeAppendChild(const v8::Arguments& args);
+ static void jsNodeDestructor(v8::Persistent<v8::Value> object, void* data);
+
+ static v8::Handle<v8::ObjectTemplate> getXPathValueTmpl();
+ static v8::Handle<v8::ObjectTemplate> getNodeSetTmpl();
+ static v8::Handle<v8::ObjectTemplate> getNodeTmpl();
+ static v8::Handle<v8::ObjectTemplate> getElementTmpl();
+
+ static v8::Handle<v8::ObjectTemplate> xPathValueTmpl;
+ static v8::Handle<v8::ObjectTemplate> nodeSetTmpl;
+ static v8::Handle<v8::ObjectTemplate> nodeTmpl;
+ static v8::Handle<v8::ObjectTemplate> elementTmpl;
+
+};
+
+class V8Node {
+};
+
+class V8DOMDocument {
+ V8DOMDocument();
+ virtual ~V8DOMDocument();
+
+ v8::Handle<v8::Array> jsChildNodes();
+};
+
+}
+
+#endif /* end of include guard: V8SCXMLDOM_H_AREM0ZC4 */