void TJsonVal::GetArrStrV(TStrV& StrV) const { EAssert(IsArr()); for (int StrN = 0; StrN < GetArrVals(); StrN++) { PJsonVal ArrVal = GetArrVal(StrN); EAssert(ArrVal->IsStr()); StrV.Add(ArrVal->GetStr()); } }
// parse from json configuration file TJsParam(const TStr& RootFNm, const PJsonVal& JsVal) { EAssertR(JsVal->IsObj(), "Unsupported type: " + TJsonVal::GetStrFromVal(JsVal)); // we must have at least the script name EAssert(JsVal->IsObjKey("file")); // get script name FNm = JsVal->GetObjStr("file"); // get namespace (get from script name if not available) Nm = JsVal->IsObjKey("name") ? JsVal->GetObjStr("name") : FNm.GetFMid(); // get initialization parameters (if available) InitVal = JsVal->IsObjKey("init") ? JsVal->GetObjKey("init") : TJsonVal::NewObj(); // get library include folders if (JsVal->IsObjKey("include")) { PJsonVal IncludesVal = JsVal->GetObjKey("include"); EAssertR(IncludesVal->IsArr(), "Expected array of strings, not: " + TJsonVal::GetStrFromVal(IncludesVal)); for (int IncludeN = 0; IncludeN < IncludesVal->GetArrVals(); IncludeN++) { PJsonVal IncludeVal = IncludesVal->GetArrVal(IncludeN); EAssertR(IncludeVal->IsStr(), "Expected string, not: " + TJsonVal::GetStrFromVal(IncludeVal)); IncludeFPathV.Add(IncludeVal->GetStr()); } } // handle default includes AddLocalLibFPath(); AddQMinerLibFPath(); // get folders with access permissions if (JsVal->IsObjKey("dirs")) { PJsonVal DirsVal = JsVal->GetObjKey("dirs"); EAssertR(DirsVal->IsArr(), "Expected array of strings, not: " + TJsonVal::GetStrFromVal(DirsVal)); for (int DirN = 0; DirN < DirsVal->GetArrVals(); DirN++) { PJsonVal DirVal = DirsVal->GetArrVal(DirN); EAssertR(DirVal->IsStr(), "Expected string, not: " + TJsonVal::GetStrFromVal(DirVal)); AccessFPathV.Add(DirVal->GetStr()); } } // add sandbox access AddSandboxAccessFPath(RootFNm); }
v8::Local<v8::Value> TNodeJsUtil::ParseJson(v8::Isolate* Isolate, const PJsonVal& JsonVal) { v8::EscapableHandleScope HandleScope(Isolate); if (!JsonVal->IsDef()) { return v8::Undefined(Isolate); } else if (JsonVal->IsBool()) { return v8::Boolean::New(Isolate, JsonVal->GetBool()); } else if (JsonVal->IsNull()) { return v8::Null(Isolate); } else if (JsonVal->IsNum()) { return HandleScope.Escape(v8::Number::New(Isolate, JsonVal->GetNum())); } else if (JsonVal->IsStr()) { return HandleScope.Escape(v8::String::NewFromUtf8(Isolate, JsonVal->GetStr().CStr())); } else if (JsonVal->IsArr()) { const uint Len = JsonVal->GetArrVals(); v8::Local<v8::Array> ResArr = v8::Array::New(Isolate, Len); for (uint i = 0; i < Len; i++) { ResArr->Set(i, ParseJson(Isolate, JsonVal->GetArrVal(i))); } return HandleScope.Escape(ResArr); } else if (JsonVal->IsObj()) { v8::Local<v8::Object> ResObj = v8::Object::New(Isolate); const int NKeys = JsonVal->GetObjKeys(); for (int i = 0; i < NKeys; i++) { TStr Key; PJsonVal Val; JsonVal->GetObjKeyVal(i, Key, Val); ResObj->Set(v8::String::NewFromUtf8(Isolate, Key.CStr()), ParseJson(Isolate, Val)); } return HandleScope.Escape(ResObj); } else { throw TExcept::New("Invalid JSON!", "TNodeJsUtil::ParseJson"); } }
void TNodeJsSA::New(const v8::FunctionCallbackInfo<v8::Value>& Args) { v8::Isolate* Isolate = v8::Isolate::GetCurrent(); v8::HandleScope HandleScope(Isolate); if (Args.Length() == 0) { return; } // EAssertR(!constructor.IsEmpty(), "TNodeJsSA::New: constructor is empty. Did you call TNodeJsSA::Init(exports); in this module's init function?"); QmAssertR(Args.Length() <= 3 && Args.Length() >= 2, "stream aggregator constructor expects at least two parameters"); QmAssertR(Args[0]->IsObject() && Args[1]->IsObject(), "stream aggregator constructor expects first two arguments as objects"); // new sa(...) if (Args.IsConstructCall()) { TQm::PStreamAggr StreamAggr; TNodeJsBase* JsBase = TNodeJsUtil::UnwrapCheckWatcher<TNodeJsBase>(Args[0]->ToObject()); // get aggregate type TStr TypeNm = TNodeJsUtil::GetArgStr(Args, 1, "type", "javaScript"); if (TypeNm == "javaScript") { // we have a javascript stream aggregate TStr AggrName = TNodeJsUtil::GetArgStr(Args, 1, "name", ""); // we need a name, if not give just generate one if (AggrName.Empty()) { AggrName = TGuid::GenSafeGuid(); } // create aggregate StreamAggr = TNodeJsStreamAggr::New(JsBase->Base, AggrName, Args[1]->ToObject()); } else if (TypeNm == "ftrext") { TStr AggrName = TNodeJsUtil::GetArgStr(Args, 1, "name", ""); QmAssertR(Args[1]->ToObject()->Has(v8::String::NewFromUtf8(Isolate, "featureSpace")), "addStreamAggr: featureSpace property missing!"); // we need a name, if not give just generate one if (AggrName.Empty()) { AggrName = TGuid::GenSafeGuid(); } throw TQm::TQmExcept::New("ftrext stream aggr not implemented yet! (needs feature space implementation)"); // TODO //TQm::PFtrSpace FtrSpace = TJsFtrSpace::GetArgFtrSpace(Args[1]->ToObject()->Get(v8::String::NewFromUtf8(Isolate, "featureSpace"))); //StreamAggr = TStreamAggrs::TFtrExtAggr::New(JsBase->Base, AggrName, FtrSpace); } else if (TypeNm == "stmerger") { // create new aggregate PJsonVal ParamVal = TNodeJsUtil::GetArgJson(Args, 1); StreamAggr = TQm::TStreamAggr::New(JsBase->Base, TypeNm, ParamVal); PJsonVal FieldArrVal = ParamVal->GetObjKey("fields"); TStrV InterpNmV; QmAssertR(ParamVal->IsObjKey("fields"), "Missing argument 'fields'!"); // automatically register the aggregate for addRec callbacks for (int FieldN = 0; FieldN < FieldArrVal->GetArrVals(); FieldN++) { PJsonVal FieldVal = FieldArrVal->GetArrVal(FieldN); PJsonVal SourceVal = FieldVal->GetObjKey("source"); TStr StoreNm = ""; if (SourceVal->IsStr()) { // we have just store name StoreNm = SourceVal->GetStr(); } else if (SourceVal->IsObj()) { // get store StoreNm = SourceVal->GetObjStr("store"); } JsBase->Base->AddStreamAggr(JsBase->Base->GetStoreByStoreNm(StoreNm)->GetStoreId(), StreamAggr); } } else { // we have a GLib stream aggregate, translate parameters to PJsonVal PJsonVal ParamVal = TNodeJsUtil::GetArgJson(Args, 1); if (Args.Length() >= 3 && Args[2]->IsString()) { ParamVal->AddToObj("store", TNodeJsUtil::GetArgStr(Args, 2)); } // check if it's one stream aggregate or composition if (TQm::TStreamAggrs::TCompositional::IsCompositional(TypeNm)) { // we have a composition of aggregates, call code to assemble it TQm::TStreamAggrs::TCompositional::Register(JsBase->Base, TypeNm, ParamVal); } else { // create new aggregate StreamAggr = TQm::TStreamAggr::New(JsBase->Base, TypeNm, ParamVal); } } if (!TQm::TStreamAggrs::TCompositional::IsCompositional(TypeNm)) { if (Args.Length() > 2) { TStrV Stores(0); if (Args[2]->IsString()) { Stores.Add(TNodeJsUtil::GetArgStr(Args, 2)); } if (Args[2]->IsArray()) { PJsonVal StoresJson = TNodeJsUtil::GetArgJson(Args, 2); QmAssertR(StoresJson->IsDef(), "stream aggr constructor : Args[2] should be a string (store name) or a string array (store names)"); StoresJson->GetArrStrV(Stores); } for (int StoreN = 0; StoreN < Stores.Len(); StoreN++) { QmAssertR(JsBase->Base->IsStoreNm(Stores[StoreN]), "stream aggr constructor : Args[2] : store does not exist!"); JsBase->Base->AddStreamAggr(Stores[StoreN], StreamAggr); } } else { JsBase->Base->AddStreamAggr(StreamAggr); } // non-compositional aggregates are returned TNodeJsSA* JsSA = new TNodeJsSA(StreamAggr); v8::Local<v8::Object> Instance = Args.This(); JsSA->Wrap(Instance); Args.GetReturnValue().Set(Instance); return; } } // sa(...) -> calls new sa(...) else { if (Args.Length() == 2) { const int Argc = 2; v8::Local<v8::Value> Argv[Argc] = { Args[0], Args[1] }; v8::Local<v8::Function> cons = v8::Local<v8::Function>::New(Isolate, constructor); v8::Local<v8::Object> Instance = cons->NewInstance(Argc, Argv); Args.GetReturnValue().Set(Instance); return; } if (Args.Length() == 3) { const int Argc = 3; v8::Local<v8::Value> Argv[Argc] = { Args[0], Args[1], Args[2] }; v8::Local<v8::Function> cons = v8::Local<v8::Function>::New(Isolate, constructor); v8::Local<v8::Object> Instance = cons->NewInstance(Argc, Argv); Args.GetReturnValue().Set(Instance); return; } else { // sa()->calls new sa() v8::Local<v8::Function> cons = v8::Local<v8::Function>::New(Isolate, constructor); v8::Local<v8::Object> Instance = cons->NewInstance(); Args.GetReturnValue().Set(Instance); return; } } }