コード例 #1
0
ファイル: qm_nodejs_streamaggr.cpp プロジェクト: Zala/qminer
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;
		}
	}
}