Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.nlpcraft.client.impl.NCClientImpl Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nlpcraft.client.impl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.HttpEntity;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.nlpcraft.client.NCClient;
import org.apache.nlpcraft.client.NCClientException;
import org.apache.nlpcraft.client.NCCompany;
import org.apache.nlpcraft.client.NCElementSynonymsData;
import org.apache.nlpcraft.client.NCFeedback;
import org.apache.nlpcraft.client.NCModelInfo;
import org.apache.nlpcraft.client.NCNewCompany;
import org.apache.nlpcraft.client.NCProbe;
import org.apache.nlpcraft.client.NCResult;
import org.apache.nlpcraft.client.NCSuggestionData;
import org.apache.nlpcraft.client.NCUser;
import org.apache.nlpcraft.client.impl.beans.NCAskBean;
import org.apache.nlpcraft.client.impl.beans.NCAskSyncBean;
import org.apache.nlpcraft.client.impl.beans.NCCheckBean;
import org.apache.nlpcraft.client.impl.beans.NCCompanyBean;
import org.apache.nlpcraft.client.impl.beans.NCCompanyTokenResetBean;
import org.apache.nlpcraft.client.impl.beans.NCElementSynonymsDataBean;
import org.apache.nlpcraft.client.impl.beans.NCErrorMessageBean;
import org.apache.nlpcraft.client.impl.beans.NCFeedbackAddBean;
import org.apache.nlpcraft.client.impl.beans.NCFeedbackAllBean;
import org.apache.nlpcraft.client.impl.beans.NCModelInfoResultBean;
import org.apache.nlpcraft.client.impl.beans.NCProbesAllBean;
import org.apache.nlpcraft.client.impl.beans.NCRequestStateBean;
import org.apache.nlpcraft.client.impl.beans.NCSigninBean;
import org.apache.nlpcraft.client.impl.beans.NCStatusResponseBean;
import org.apache.nlpcraft.client.impl.beans.NCSuggestionResultBean;
import org.apache.nlpcraft.client.impl.beans.NCTokenCreationBean;
import org.apache.nlpcraft.client.impl.beans.NCUserAddBean;
import org.apache.nlpcraft.client.impl.beans.NCUserBean;
import org.apache.nlpcraft.client.impl.beans.NCUsersAllBean;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Client implementation.
*/
@SuppressWarnings("JavaDoc")
public class NCClientImpl implements NCClient {
private static final String STATUS_API_OK = "API_OK";
private static final Type MAP_TYPE = new TypeToken>(){}.getType();
private static final Gson gsonExt = new Gson();
private static final Gson gson =
new GsonBuilder().registerTypeAdapter(
NCRequestStateBean.class,
(JsonDeserializer) (e, type, ctx) -> {
JsonObject o = e.getAsJsonObject();
NCRequestStateBean b = new NCRequestStateBean();
b.setSrvReqId(o.get("srvReqId").getAsString());
b.setTxt(o.get("txt").getAsString());
b.setUsrId(o.get("usrId").getAsLong());
b.setMdlId(o.get("mdlId").getAsString());
b.setProbeId(convert(o, "probeId", JsonElement::getAsString));
b.setResultType(convert(o, "resType", JsonElement::getAsString));
b.setResultBody(
convert(o, "resBody", (resBody) -> resBody == null ?
null :
resBody.isJsonObject() ?
resBody.getAsJsonObject().toString() :
resBody.getAsString())
);
b.setResultMeta(convert(o, "resMeta", e1 -> {
Map m = gsonExt.fromJson(e1, MAP_TYPE);
return m == null || m.isEmpty() ? null : m;
}));
b.setStatus(o.get("status").getAsString());
b.setErrorCode(convert(o, "errorCode", JsonElement::getAsInt));
b.setError(convert(o, "error", JsonElement::getAsString));
b.setLogHolder(convert(o, "logHolder", (logHolder) -> logHolder.getAsJsonObject().toString()));
return b;
}).create();
private static final Logger log = LogManager.getLogger(NCClientImpl.class);
private static final String AUTH_ERR = "NC_INVALID_ACCESS_TOKEN";
private Supplier httpCliGen;
private RequestConfig reqCfg;
private String baseUrl;
private String email;
private String pwd;
private Boolean cancelOnExit;
private CloseableHttpClient httpCli;
private String acsTok;
private volatile boolean started = false;
private static T convert(JsonObject o, String name, Function converter) {
JsonElement e = o.get(name);
return e != null ? converter.apply(e) : null;
}
@Override
public String getClientUserEmail() {
return email;
}
@Override
public String getClientUserPassword() {
return pwd;
}
@Override
public boolean isClientCancelOnExit() {
return cancelOnExit;
}
@Override
public String getClientBaseUrl() {
return baseUrl;
}
/**
*
* @return
*/
public Supplier getClientSupplier() {
return httpCliGen;
}
/**
*
* @param httpCliGen
*/
public void setClientSupplier(Supplier httpCliGen) {
this.httpCliGen = httpCliGen;
}
/**
*
* @return
*/
public RequestConfig getRequestConfig() {
return reqCfg;
}
/**
*
* @param reqCfg
*/
public void setRequestConfig(RequestConfig reqCfg) {
this.reqCfg = reqCfg;
}
/**
*
* @return
*/
public String getBaseUrl() {
return baseUrl;
}
/**
*
* @param baseUrl
*/
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
/**
*
* @return
*/
public String getEmail() {
return email;
}
/**
*
* @param email
*/
public void setEmail(String email) {
this.email = email;
}
/**
*
* @return
*/
public String getPassword() {
return pwd;
}
/**
*
* @param pwd
*/
public void setPassword(String pwd) {
this.pwd = pwd;
}
/**
*
* @return
*/
public Boolean isCancelOnExit() {
return cancelOnExit;
}
/**
*
* @param cancelOnExit
*/
public void setCancelOnExit(Boolean cancelOnExit) {
this.cancelOnExit = cancelOnExit;
}
/**
*
* @throws IOException
* @throws NCClientException
*/
public void initialize() throws IOException, NCClientException {
httpCli = httpCliGen.get();
if (reqCfg == null)
reqCfg = RequestConfig.DEFAULT;
acsTok = restSignin();
started = true;
}
/**
*
* @param r
* @throws NCClientException
*/
private static void checkStatus(NCStatusResponseBean r) throws NCClientException {
checkStatus(r.getStatus());
}
/**
*
* @param status
*/
private static void checkStatus(String status) {
if (!status.equals(STATUS_API_OK))
throw new NCClientException(String.format("Unexpected message status: %s", status));
}
/**
*
* @param js
* @param type
* @param
* @return
* @throws NCClientException
*/
private T checkAndExtract(String js, Type type) throws NCClientException {
T t = gson.fromJson(js, type);
checkStatus(t.getStatus());
return t;
}
/**
*
* @param url
* @param ps
* @return
* @throws NCClientException
* @throws IOException
* @throws IllegalStateException
*/
@SafeVarargs
private String post(String url, Pair... ps) throws NCClientException, IOException {
if (!started)
throw new IllegalStateException("Client is not initialized.");
List> psList =
Arrays.stream(ps).filter(p -> p != null && p.getRight() != null).collect(Collectors.toList());
try {
return postPlain(url, psList);
}
catch (NCClientException e) {
if (!AUTH_ERR.equals(e.getServerCode()))
throw e;
try {
log.debug("Reconnect attempt because token is invalid.");
acsTok = restSignin();
log.debug("Reconnected OK.");
// Replaces token.
return postPlain(url, psList.stream().
map(p -> p.getLeft().equals("acsTok") ? Pair.of("acsTok", acsTok) : p).
collect(Collectors.toList()));
}
catch (NCClientException e1) {
throw e;
}
}
}
/**
*
* @param url
* @param ps
* @return
* @throws NCClientException
* @throws IOException
*/
private String postPlain(String url, List> ps) throws NCClientException, IOException {
HttpPost post = new HttpPost(baseUrl + url);
try {
post.setConfig(reqCfg);
StringEntity entity = new StringEntity(
gson.toJson(ps.stream().collect(Collectors.toMap(Pair::getKey, Pair::getValue))),
"UTF-8"
);
post.setHeader("Content-Type", "application/json");
post.setEntity(entity);
ResponseHandler h = resp -> {
int code = resp.getStatusLine().getStatusCode();
HttpEntity e = resp.getEntity();
String js = e != null ? EntityUtils.toString(e) : null;
if (js == null)
throw new NCClientException(String.format("Unexpected empty response [code=%d]", code));
if (code == 200)
return js;
NCErrorMessageBean err;
try {
err = gson.fromJson(js, NCErrorMessageBean.class);
}
catch (Exception e1) {
throw new NCClientException(String.format("Unexpected server error [code=%d]", code));
}
throw new NCClientException(err.getMessage(), err.getCode());
};
return httpCli.execute(post, h);
}
finally {
post.releaseConnection();
}
}
/**
* @param v
* @param name
* @throws IllegalArgumentException
*/
private void notNull(String v, String name) throws IllegalArgumentException {
if (v == null || v.trim().isEmpty())
throw new IllegalArgumentException(String.format("Parameter cannot be null or empty: '%s'", name));
}
/**
*
* @return
* @throws IOException
* @throws NCClientException
*/
private String restSignin() throws IOException, NCClientException {
NCSigninBean b =
checkAndExtract(
postPlain(
"/signin",
Arrays.asList(
Pair.of("email", email),
Pair.of("passwd", pwd)
)
),
NCSigninBean.class
);
return b.getAccessToken();
}
@Override
public long addUser(
String email,
String passwd,
String firstName,
String lastName,
String avatarUrl,
boolean isAdmin,
Map properties,
String extId
) throws NCClientException, IOException {
notNull(email, "email");
notNull(passwd, "passwd");
notNull(firstName, "firstName");
notNull(lastName, "lastName");
NCUserAddBean b =
checkAndExtract(
post(
"user/add",
Pair.of("acsTok", acsTok),
Pair.of("email", email),
Pair.of("passwd", passwd),
Pair.of("firstName", firstName),
Pair.of("lastName", lastName),
Pair.of("isAdmin", isAdmin),
Pair.of("avatarUrl", avatarUrl),
Pair.of("properties", properties),
Pair.of("extId", extId)
),
NCUserAddBean.class
);
return b.getId();
}
@Override
public void deleteUser(Long id, String extId) throws NCClientException, IOException {
checkStatus(
gson.fromJson(
post(
"user/delete",
Pair.of("acsTok", acsTok),
Pair.of("id", id),
Pair.of("extId", extId)
),
NCStatusResponseBean.class
)
);
}
@Override
public void updateUser(
long id, String firstName, String lastName, String avatarUrl, Map properties
) throws NCClientException, IOException {
notNull(firstName, "firstName");
notNull(lastName, "lastName");
checkStatus(
gson.fromJson(
post(
"user/update",
Pair.of("acsTok", acsTok),
Pair.of("id", id),
Pair.of("firstName", firstName),
Pair.of("lastName", lastName),
Pair.of("avatarUrl", avatarUrl),
Pair.of("properties", properties)
),
NCStatusResponseBean.class
)
);
}
@Override
public void updateUserAdmin(Long id, boolean admin) throws NCClientException, IOException {
checkStatus(
gson.fromJson(
post(
"user/admin",
Pair.of("acsTok", acsTok),
Pair.of("id", id),
Pair.of("admin", admin)
),
NCStatusResponseBean.class
)
);
}
@Override
public NCUser getUser(Long id, String extId) throws NCClientException, IOException {
return
checkAndExtract(
post(
"user/get",
Pair.of("acsTok", acsTok),
Pair.of("id", id),
Pair.of("usrExtId", extId)
),
NCUserBean.class
);
}
@Override
public void resetUserPassword(Long id, String newPasswd) throws NCClientException, IOException {
notNull(newPasswd, "newPasswd");
checkStatus(
gson.fromJson(
post(
"user/passwd/reset",
Pair.of("acsTok", acsTok),
Pair.of("id", id),
Pair.of("newPasswd", newPasswd)
),
NCStatusResponseBean.class
)
);
}
@Override
public List getAllUsers() throws NCClientException, IOException {
NCUsersAllBean b =
checkAndExtract(
post(
"user/all",
Pair.of("acsTok", acsTok)
),
NCUsersAllBean.class
);
return new ArrayList<>(b.getUsers());
}
@Override
public List getProbes() throws NCClientException, IOException {
NCProbesAllBean b =
checkAndExtract(
post(
"probe/all",
Pair.of("acsTok", acsTok)
),
NCProbesAllBean.class
);
return new ArrayList<>(b.getProbes());
}
@Override
public void clearConversation(String mdlId, Long usrId, String usrExtId) throws NCClientException, IOException {
notNull(mdlId, "mdlId");
checkStatus(
gson.fromJson(
post(
"clear/conversation",
Pair.of("acsTok", acsTok),
Pair.of("mdlId", mdlId),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCStatusResponseBean.class
)
);
}
@Override
public void clearDialog(String mdlId, Long usrId, String usrExtId) throws NCClientException, IOException {
notNull(mdlId, "mdlId");
checkStatus(
gson.fromJson(
post(
"clear/dialog",
Pair.of("acsTok", acsTok),
Pair.of("mdlId", mdlId),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCStatusResponseBean.class
)
);
}
@Override
public void close() throws IOException, NCClientException {
if (cancelOnExit)
cancel(null, null, null);
checkStatus(
gson.fromJson(
post(
"signout",
Pair.of("acsTok", acsTok)
),
NCStatusResponseBean.class
)
);
started = false;
}
@Override
public String ask(String mdlId, String txt, Map data, boolean enableLog, Long usrId, String usrExtId) throws NCClientException, IOException {
notNull(mdlId, "mdlId");
notNull(txt, "txt");
NCAskBean b =
checkAndExtract(
post(
"ask",
Pair.of("acsTok", acsTok),
Pair.of("txt", txt),
Pair.of("mdlId", mdlId),
Pair.of("data", data),
Pair.of("enableLog", enableLog),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCAskBean.class
);
return b.getServerRequestId();
}
@Override
public NCResult askSync(String mdlId, String txt, Map data, boolean enableLog, Long usrId, String usrExtId) throws NCClientException, IOException {
notNull(mdlId, "mdlId");
notNull(txt, "txt");
NCAskSyncBean b =
checkAndExtract(
post(
"ask/sync",
Pair.of("acsTok", acsTok),
Pair.of("txt", txt),
Pair.of("mdlId", mdlId),
Pair.of("data", data),
Pair.of("enableLog", enableLog),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCAskSyncBean.class
);
return b.getState();
}
@Override
public long addFeedback(String srvReqId, double score, String comment, Long usrId, String usrExtId)
throws NCClientException, IOException {
notNull(srvReqId, "srvReqId");
NCFeedbackAddBean b =
checkAndExtract(
post(
"feedback/add",
Pair.of("acsTok", acsTok),
Pair.of("srvReqId", srvReqId),
Pair.of("score", score),
Pair.of("comment", comment),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCFeedbackAddBean.class
);
return b.getId();
}
@Override
public void deleteFeedback(Long id) throws NCClientException, IOException {
checkStatus(
gson.fromJson(
post(
"feedback/delete",
Pair.of("acsTok", acsTok),
Pair.of("id", id)
),
NCStatusResponseBean.class
)
);
}
@Override
public List getAllFeedback(String srvReqId, Long usrId, String usrExtId) throws NCClientException, IOException {
NCFeedbackAllBean b =
checkAndExtract(
post(
"feedback/all",
Pair.of("acsTok", acsTok),
Pair.of("srvReqId", srvReqId),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCFeedbackAllBean.class
);
return new ArrayList<>(b.getFeedback());
}
@Override
public List check(Set srvReqIds, Integer maxRows, Long usrId, String usrExtId) throws NCClientException, IOException {
NCCheckBean b =
checkAndExtract(
post(
"check",
Pair.of("acsTok", acsTok),
Pair.of("srvReqIds", srvReqIds),
Pair.of("maxRows", maxRows),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCCheckBean.class
);
return new ArrayList<>(b.getStates());
}
@Override
public void cancel(Set srvReqIds, Long usrId, String usrExtId) throws NCClientException, IOException {
checkStatus(
gson.fromJson(
post(
"cancel",
Pair.of("acsTok", acsTok),
Pair.of("srvReqIds", srvReqIds),
Pair.of("usrId", usrId),
Pair.of("usrExtId", usrExtId)
),
NCStatusResponseBean.class
)
);
}
@Override
public NCNewCompany addCompany(String name, String website, String country, String region, String city,
String address, String postalCode, String adminEmail, String adminPasswd, String adminFirstName,
String adminLastName, String adminAvatarUrl, Map props) throws IOException, NCClientException {
notNull(name, "name");
notNull(adminEmail, "adminEmail");
notNull(adminPasswd, "adminPasswd");
notNull(adminFirstName, "adminFirstName");
notNull(adminLastName, "adminLastName");
return
checkAndExtract(
post(
"company/add",
Pair.of("acsTok", acsTok),
Pair.of("name", name),
Pair.of("website", website),
Pair.of("country", country),
Pair.of("region", region),
Pair.of("city", city),
Pair.of("address", address),
Pair.of("postalCode", postalCode),
Pair.of("adminEmail", adminEmail),
Pair.of("adminPasswd", adminPasswd),
Pair.of("adminFirstName", adminFirstName),
Pair.of("adminLastName", adminLastName),
Pair.of("postalCode", adminAvatarUrl),
Pair.of("properties", props)
),
NCTokenCreationBean.class
);
}
@Override
public NCCompany getCompany() throws IOException, NCClientException {
return
checkAndExtract(
post(
"company/get",
Pair.of("acsTok", acsTok)
),
NCCompanyBean.class
);
}
@Override
public void updateCompany(
String name,
String website,
String country,
String region,
String city,
String address,
String postalCode,
Map props
) throws IOException, NCClientException {
notNull(name, "name");
checkStatus(
gson.fromJson(
post(
"company/update",
Pair.of("acsTok", acsTok),
Pair.of("name", name),
Pair.of("website", website),
Pair.of("country", country),
Pair.of("region", region),
Pair.of("city", city),
Pair.of("address", address),
Pair.of("postalCode", postalCode),
Pair.of("properties", props)
),
NCStatusResponseBean.class
)
);
}
@Override
public String resetCompanyToken() throws IOException, NCClientException {
NCCompanyTokenResetBean b =
checkAndExtract(
post(
"company/token/reset",
Pair.of("acsTok", acsTok)
),
NCCompanyTokenResetBean.class
);
return b.getToken();
}
@Override
public void deleteCompany() throws IOException, NCClientException {
checkStatus(
gson.fromJson(
post(
"company/delete",
Pair.of("acsTok", acsTok)
),
NCStatusResponseBean.class
)
);
}
@Override
public NCSuggestionData suggestSynonyms(String mdlId, Double minScore) throws NCClientException, IOException {
NCSuggestionResultBean res = checkAndExtract(
post(
"model/sugsyn",
Pair.of("acsTok", acsTok),
Pair.of("mdlId", mdlId),
Pair.of("minScore", minScore)
),
NCSuggestionResultBean.class
);
return res.getResult();
}
@Override
public NCElementSynonymsData getSynonyms(String mdlId, String elmId) throws NCClientException, IOException {
return checkAndExtract(
post(
"model/syns",
Pair.of("acsTok", acsTok),
Pair.of("mdlId", mdlId),
Pair.of("elmId", elmId)
),
NCElementSynonymsDataBean.class
);
}
@Override
public NCModelInfo getModelInfo(String mdlId) throws NCClientException, IOException {
NCModelInfoResultBean res = checkAndExtract(
post(
"model/info",
Pair.of("acsTok", acsTok),
Pair.of("mdlId", mdlId)
),
NCModelInfoResultBean.class
);
return res.getModel();
}
}