[NMT] native node module for NMT so wrapping 06/256206/30
authorjaekuk, lee <juku1999@samsung.com>
Wed, 31 Mar 2021 01:41:20 +0000 (10:41 +0900)
committerjaekuk, lee <juku1999@samsung.com>
Tue, 14 Sep 2021 05:07:18 +0000 (14:07 +0900)
It uses NMT shared libraries provided by On Device AI F/W.
Using API set provided by this module, it can translate the contents of web app.

Supportive API Set
- init
- uninit
- setPath
- translate
- getAvailableSourceLanguage
- getAvailableTargetLanguageList
- isDirectionAvailable
- getModelList

nmt feature is supported by default for public profile.
If using nmt feature for the other profiles, use nmt option.
$ ./tizen/build/build_tv.sh --nmt

Related patch:
https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/253460

Change-Id: I0aaa9d822b89c1632ac09a29623b88c5eeb3c554
Signed-off-by: jaekuk, lee <juku1999@samsung.com>
14 files changed:
BUILD.gn [changed mode: 0644->0755]
packaging/wrtjs.spec
tizen/build/common.sh
wrt_app/common/config-search-paths.ts [changed mode: 0644->0755]
wrt_feature/nmt_service/BUILD.gn [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/inc/translator.h [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/nmt.cpp [new file with mode: 0755]
wrt_feature/nmt_service/node_modules/nmt/nmt.h [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 1a9e212..62f9de2
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -27,10 +27,22 @@ toolchain("gcc") {
     command = "touch {{output}}"
     description = "STAMP {{output}}"
   }
+  tool("solink") {
+    soname = "{{target_output_name}}{{output_extension}}"
+    rpath = "-Wl,-soname,$soname"
+    command = "g++ -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
+    outputs = [
+      "{{root_out_dir}}/$soname",
+    ]
+    output_prefix = "lib"
+    default_output_extension = ".so"
+    description = "link {{output}}"
+  }
 }
 
 group("wrt_group") {
   deps = [
     "//loader:wrt-loader",
+    "//wrt_feature/nmt_service:nmt",
   ]
 }
index 4d6c1e7..1e5a941 100755 (executable)
@@ -19,9 +19,14 @@ Source:     %{name}-%{version}.tar.gz
   %define _use_d2d 1
 %endif
 
+# The nmt is public feature
+%if "%{?profile}" != "tv" && "%{?profile}" != "wearable" && "%{?_with_da_profile}" != "1"
+  %define _use_nmt 1
+%endif
+
 BuildRequires: pkgconfig(chromium-efl)
 
-%if "%{?profile}" != "tv"
+%if "%{?profile}" != "tv" || 0%{?_use_nmt}
 BuildRequires: ninja
 BuildRequires: pkgconfig(dlog)
 %endif
@@ -81,6 +86,14 @@ Web Runtime Engine based on Electron
   ninja -C %{_outdir} wrt-loader
 %endif
 
+%if 0%{?_use_nmt}
+%if "%{?profile}" == "tv"
+  %define _outdir $PWD/out
+  ./build/tools/gn gen %{_outdir}
+%endif
+  ninja -C %{_outdir} nmt
+%endif
+
 ./build/tools/node ./node_modules/.bin/tsc
 absolute_appdir=$PWD/%{app_dir}
 (cd wrt_app/ && find . -type f ! -name '*.ts' -exec cp --parents {} ${absolute_appdir} \;)
@@ -180,6 +193,12 @@ cp -r %{app_dir}/* %{buildroot}%{_resourcedir}/
   rm -f %{buildroot}/%{_d2d_wgt_file_name}
 %endif
 
+%if 0%{?_use_nmt}
+  install -m 0644 wrt_feature/nmt_service/node_modules/nmt/lib/%{ARCHITECTURE}/*    "%{buildroot}"%{_libdir}/
+  install -d %{buildroot}%{_datadir}/wrt/feature/nmt_service/node_modules
+  install -m 0644 "%{_outdir}"/libnmt.node                            %{buildroot}%{_datadir}/wrt/feature/nmt_service/node_modules/
+%endif
+
 %pre
 export CHROMIUM_REVISION=
 if [ -f "%{_datadir}/chromium-efl/version" ]; then
@@ -238,6 +257,17 @@ rm -fr %{buildroot}
 %endif
 %{_datadir}/wrtjs/version
 %{_libdir}/%{crosswalk_extensions_service}/plugins.json
+
+%if 0%{?_use_nmt}
+  %{_libdir}/libmanager.so
+  %{_libdir}/libsentencepiece.so.0
+  %{_libdir}/libsr_odnmt.so
+  %{_libdir}/libsrcb_bpe.so
+  %{_libdir}/libsrcb_langid.so
+  %{_libdir}/libtransformer.so
+  %{_datadir}/wrt/feature/nmt_service/node_modules/libnmt.node
+%endif
+
 %{_resourcedir}/*
 %if 0%{?__package_signing}
   %{WRTJS_APP_DIR}/author-signature.xml
index c62935a..15c4f84 100755 (executable)
@@ -29,6 +29,7 @@ function setupAndExecuteTargetBuild() {
   local LOCAL_BUILD=1
   local PROFILE
   local USE_D2D
+  local USE_NMT
   local USE_TPK
   local -a ARGS
 
@@ -42,6 +43,9 @@ function setupAndExecuteTargetBuild() {
     --d2d)
       USE_D2D=1
     ;;
+    --nmt)
+      USE_NMT=1
+    ;;
     --standard*)
       PROFILE=tz_$(echo $1 | sed 's/--//g')
     ;;
@@ -73,6 +77,9 @@ function setupAndExecuteTargetBuild() {
   if [ "$USE_D2D" == "1" ]; then
     ARGS+=(--define "_use_d2d 1")
   fi
+  if [ "$USE_NMT" == "1" ]; then
+    ARGS+=(--define "_use_nmt 1")
+  fi
   if [ "$USE_TPK" == "1" ]; then
     ARGS+=(--define "_use_tpk 1")
     if [ "$USE_TPK_UPGRADE" == "1" ] && [ $platform == "tv" ]; then
old mode 100644 (file)
new mode 100755 (executable)
index 20be308..8555917
@@ -7,6 +7,8 @@ const originalResolveFilename = Module._resolveFilename;
 Module._resolveFilename = function (request: string, parent: NodeModule, isMain: boolean) {
   if (request === 'addonapi' && process.type)
     return path.join(__dirname, '..', 'addon', process.type as string, 'addonapi.js');
+  else if (request === 'node-nmt')
+    return path.join(__dirname, '..', '..', 'feature/nmt_service/node_modules', 'libnmt.node');
   else
     return originalResolveFilename(request, parent, isMain);
 }
diff --git a/wrt_feature/nmt_service/BUILD.gn b/wrt_feature/nmt_service/BUILD.gn
new file mode 100755 (executable)
index 0000000..607558b
--- /dev/null
@@ -0,0 +1,32 @@
+shared_library("nmt") {
+  output_name = "nmt"
+  output_extension = "node"
+  libs = [
+    "dlog",
+    "chromium-impl",
+    "manager",
+    "sr_odnmt",
+    "srcb_bpe",
+    "srcb_langid",
+    "transformer",
+  ]
+  lib_dirs = [
+    "/usr/share/chromium-efl/lib",
+    "node_modules/nmt/lib/armv7l"
+  ]
+  include_dirs = [
+    "/usr/include/node",
+    "/usr/include/v8",
+    "node_modules/nmt/inc",
+  ]
+  sources = [
+    "node_modules/nmt/nmt.cpp",
+    "node_modules/nmt/nmt.h",
+    "node_modules/nmt/inc/translator.h",
+  ]
+  ldflags = [
+    "-shared",
+    "-Wl,--export-dynamic"
+  ]
+  cflags = ["-fPIC"]
+}
diff --git a/wrt_feature/nmt_service/node_modules/nmt/inc/translator.h b/wrt_feature/nmt_service/node_modules/nmt/inc/translator.h
new file mode 100755 (executable)
index 0000000..225e72f
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+class Manager;
+
+namespace SrOnDeviceNmt {
+
+class Translator {
+   public:
+    Translator();
+    Translator(vector<string> path);
+
+    ~Translator() { clear(); };
+    void setPath(vector<string> modelpath);
+    void setDetectorPath(string modelpath);
+    string translate(string inputSequence, string srcLang, string tgtLang);
+    string detectLanguage(string tgtLang, string inputSequence, bool verbose);
+    vector<string> getAvailableSourceLanguageList();
+    vector<string> getAvailableTargetLanguageList(string srcLang);
+    int isDirectionAvailable(string srcLang, string tgtLang);
+   private:
+    void clear();
+    vector<string> path;
+    std::shared_ptr<Manager> manager;
+    bool check_model();
+};
+
+}  // namespace SrOnDeviceNmt
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so
new file mode 100755 (executable)
index 0000000..2c926fc
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0
new file mode 100755 (executable)
index 0000000..2cb5987
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so
new file mode 100755 (executable)
index 0000000..8743df0
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so
new file mode 100755 (executable)
index 0000000..5a75dea
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so
new file mode 100755 (executable)
index 0000000..82a618d
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so
new file mode 100755 (executable)
index 0000000..020e318
Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so differ
diff --git a/wrt_feature/nmt_service/node_modules/nmt/nmt.cpp b/wrt_feature/nmt_service/node_modules/nmt/nmt.cpp
new file mode 100755 (executable)
index 0000000..c71ec8e
--- /dev/null
@@ -0,0 +1,253 @@
+/*\r
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ *    Licensed under the Apache License, Version 2.0 (the "License");\r
+ *    you may not use this file except in compliance with the License.\r
+ *    You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ */\r
+\r
+#include <dlog/dlog.h>\r
+#include <map>\r
+#include <unistd.h>\r
+#include <v8.h>\r
+#include <node.h>\r
+#include "nmt.h"\r
+#include "translator.h"\r
+\r
+#ifdef LOG_TAG\r
+#undef LOG_TAG\r
+#endif\r
+#define LOG_TAG "WRT_SERVICE_NMT"\r
+\r
+using namespace node;\r
+using namespace v8;\r
+using namespace std;\r
+using namespace SrOnDeviceNmt;\r
+\r
+namespace wrt {\r
+namespace service {\r
+\r
+static void logd(const char* tag, const char* format, ...){\r
+  va_list args;\r
+  va_start(args, format);\r
+  LOG_VA(LOG_DEBUG, tag, format, args);\r
+  va_end(args);\r
+}\r
+\r
+static NMT *_nmt = NULL;\r
+static Translator translator;\r
+\r
+static map<string,pair<string, string>> model_list = {\r
+  {"bg", {"Bulgarian", "rmE8Va3gon"}},\r
+  {"cs", {"Czech", "o9i8ZKUGk4"}},\r
+  {"de", {"German", "cwzIAj3oJT"}},\r
+  {"es", {"Spanish", "4KKRqmCg5x"}},\r
+  {"fr", {"French", "0HEUtxuBp6"}},\r
+  {"it", {"Italian", "6io0TjUf1z"}},\r
+  {"ko", {"Korean", "UkFnQa8EAT"}},\r
+  {"nl", {"Dutch", "bjPxXxwt5E"}},\r
+  {"pl", {"Polish", "wgjC6UsLUJ"}},\r
+  {"pt", {"Portuguese", "356EJyAM9o"}},\r
+  {"ru", {"Russian", "mq7ZH7ehh0"}},\r
+  {"zh", {"Chinese", "OJ981RFTyA"}},\r
+};\r
+\r
+NMT::NMT(){\r
+}\r
+\r
+NMT::~NMT(){\r
+};\r
+\r
+void NMT::Init(){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+}\r
+\r
+void NMT::Uninit(){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+}\r
+\r
+void NMT::SetPath(){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    vector<string> data_paths;\r
+    for(map<string,pair<string, string>>::iterator iter = model_list.begin(); iter != model_list.end(); ++iter ){\r
+      string modelPath = "/opt/usr/globalapps/" + iter->second.second + "/shared/res/assets";\r
+      if(access(modelPath.c_str(), 0) != -1)\r
+        data_paths.push_back(modelPath);\r
+    }\r
+    translator.setPath(data_paths);\r
+}\r
+\r
+static void NMTinit(const FunctionCallbackInfo<Value>& /*args*/){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+        _nmt = new NMT();\r
+    }\r
+    _nmt->Init();\r
+    _nmt->SetPath();\r
+}\r
+\r
+static void NMTuninit(const FunctionCallbackInfo<Value>& /*args*/){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt != NULL) {\r
+        _nmt->Uninit();\r
+        delete _nmt;\r
+        _nmt = NULL;\r
+    }\r
+}\r
+\r
+static void NMTsetPath(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+    _nmt->SetPath();\r
+    args.GetReturnValue().Set(Undefined(isolate));\r
+\r
+}\r
+\r
+static void NMTtranslate(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+    if(args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() || !args[2]->IsString()) {\r
+      logd(LOG_TAG, "Invalid Argument");\r
+      return;\r
+    }\r
+\r
+    string str0(*String::Utf8Value(isolate, args[0]));\r
+    string str1(*String::Utf8Value(isolate, args[1]));\r
+    string str2(*String::Utf8Value(isolate, args[2]));\r
+\r
+    string transResult = translator.translate(str0, str1, str2);\r
+    args.GetReturnValue().Set(String::NewFromUtf8(isolate, transResult.c_str()).ToLocalChecked());\r
+}\r
+\r
+static void NMTgetAvailableSourceLanguageList(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+\r
+    vector<string> sourcelist = translator.getAvailableSourceLanguageList();\r
+    if (sourcelist.size()) {\r
+      Local<Array> array = Array::New(isolate, sourcelist.size());\r
+      int idx = 0;\r
+      for (auto it = sourcelist.begin(); it != sourcelist.end(); ++it) {\r
+        array->Set(isolate->GetCurrentContext(), Integer::New(isolate, idx++), String::NewFromUtf8(isolate, it->c_str()).ToLocalChecked());\r
+      }\r
+      args.GetReturnValue().Set(array);\r
+    }\r
+    else {\r
+      logd(LOG_TAG, "Invalid Result");\r
+      args.GetReturnValue().Set(Undefined(isolate));\r
+    }\r
+}\r
+\r
+static void NMTgetAvailableTargetLanguageList(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+    if(args.Length() != 1 || !args[0]->IsString()) {\r
+      logd(LOG_TAG, "Invalid Argument");\r
+      return;\r
+    }\r
+\r
+    string str(*String::Utf8Value(isolate, args[0]));\r
+    vector<string> targetlist = translator.getAvailableTargetLanguageList(str);\r
+    if (targetlist.size()) {\r
+      Local<Array> array = Array::New(isolate, targetlist.size());\r
+      int idx = 0;\r
+      for (auto it = targetlist.begin(); it != targetlist.end(); ++it) {\r
+        array->Set(isolate->GetCurrentContext(), Integer::New(isolate, idx++), String::NewFromUtf8(isolate, it->c_str()).ToLocalChecked());\r
+      }\r
+      args.GetReturnValue().Set(array);\r
+    }\r
+    else {\r
+      logd(LOG_TAG, "Invalid Result");\r
+      args.GetReturnValue().Set(Undefined(isolate));\r
+    }\r
+}\r
+\r
+static void NMTisDirectionAvailable(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+    if(args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {\r
+      logd(LOG_TAG, "Invalid Argument");\r
+      return;\r
+    }\r
+\r
+    string str0(*String::Utf8Value(isolate, args[0]));\r
+    string str1(*String::Utf8Value(isolate, args[1]));\r
+    int avail = translator.isDirectionAvailable(str0, str1);\r
+    args.GetReturnValue().Set(avail);\r
+\r
+}\r
+\r
+static void NMTgetModelList(const FunctionCallbackInfo<Value>& args){\r
+    logd(LOG_TAG, __PRETTY_FUNCTION__);\r
+    if (_nmt == NULL) {\r
+      _nmt = new NMT();\r
+      _nmt->Init();\r
+    }\r
+    Isolate* isolate = args.GetIsolate();\r
+    HandleScope scope(isolate);\r
+\r
+    if (model_list.size()) {\r
+      string modelListResult, modelData;\r
+      for (auto it = model_list.begin(); it != model_list.end(); ++it) {\r
+        if (it != model_list.begin())\r
+          modelData = modelData + ",";\r
+        modelData = modelData + "{\"model\":\""+it->first+"\",\"name\":\""+it->second.first+"\",\"pkgId\":\""+it->second.second+"\"}";\r
+      }\r
+      modelListResult = "{\"modelList\":[" +modelData + "]}";\r
+      args.GetReturnValue().Set(String::NewFromUtf8(isolate, modelListResult.c_str()).ToLocalChecked());\r
+    }\r
+    else {\r
+      logd(LOG_TAG, "Invalid Result");\r
+      args.GetReturnValue().Set(Undefined(isolate));\r
+    }\r
+}\r
+\r
+\r
+static void init(Handle<Object> target) {\r
+    NODE_SET_METHOD(target, "init", NMTinit);\r
+    NODE_SET_METHOD(target, "uninit", NMTuninit);\r
+    NODE_SET_METHOD(target, "setPath", NMTsetPath);\r
+    NODE_SET_METHOD(target, "translate", NMTtranslate);\r
+    NODE_SET_METHOD(target, "getAvailableSourceLanguageList", NMTgetAvailableSourceLanguageList);\r
+    NODE_SET_METHOD(target, "getAvailableTargetLanguageList", NMTgetAvailableTargetLanguageList);\r
+    NODE_SET_METHOD(target, "isDirectionAvailable", NMTisDirectionAvailable);\r
+    NODE_SET_METHOD(target, "getModelList", NMTgetModelList);\r
+}\r
+\r
+NODE_MODULE(nmt, init);\r
+\r
+} // namespace service\r
+} // namespace wrt\r
diff --git a/wrt_feature/nmt_service/node_modules/nmt/nmt.h b/wrt_feature/nmt_service/node_modules/nmt/nmt.h
new file mode 100755 (executable)
index 0000000..7a659eb
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ *    Licensed under the Apache License, Version 2.0 (the "License");\r
+ *    you may not use this file except in compliance with the License.\r
+ *    You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ */\r
+\r
+#ifndef WRT_SERVICE_NODE_NMT_H_\r
+#define WRT_SERVICE_NODE_NMT_H_\r
+\r
+#include <string>\r
+#include <vector>\r
+using namespace std;\r
+\r
+namespace wrt {\r
+namespace service {\r
+\r
+class NMT {\r
+public:\r
+    NMT();\r
+    virtual ~NMT();\r
+    void Init();\r
+    void Uninit();\r
+    void SetPath();\r
+private:\r
+};\r
+\r
+} // namespace service\r
+} // namespace wrt\r
+\r
+#endif // WRT_SERVICE_NODE_NMT_H_\r