boxalino.client.SDK.BxClient.java Source code

Java tutorial

Introduction

Here is the source code for boxalino.client.SDK.BxClient.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package boxalino.client.SDK;

import Exception.BoxalinoException;
import Helper.HttpContext;

import com.boxalino.p13n.api.thrift.AutocompleteRequest;
import com.boxalino.p13n.api.thrift.AutocompleteRequestBundle;
import com.boxalino.p13n.api.thrift.AutocompleteResponse;
import com.boxalino.p13n.api.thrift.ChoiceInquiry;
import com.boxalino.p13n.api.thrift.ChoiceRequest;
import com.boxalino.p13n.api.thrift.ChoiceResponse;
import com.boxalino.p13n.api.thrift.P13nService.Client;
import com.boxalino.p13n.api.thrift.RequestContext;
import com.boxalino.p13n.api.thrift.UserRecord;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.transport.THttpClient;
import org.apache.thrift.transport.TTransportException;

/**
 * @author HASHIR
 */
public class BxClient {

    private final String account;
    private final String password;
    private final String apiKey;
    private final String apiSecret;
    private final boolean isDev;
    private String host;
    private Integer port;
    private String uri;
    private String schema;
    private String p13n_username;
    private String p13n_password;
    private final String domain;

    private ArrayList<BxAutocompleteRequest> autocompleteRequests = null;
    private ArrayList<BxAutocompleteResponse> autocompleteResponses = null;

    private ArrayList<BxRequest> chooseRequests;
    private ChoiceResponse chooseResponses = null;

    int _VISITOR_COOKIE_TIME = 31536000;
    private int _timeout = 2;
    private Map<String, ArrayList<String>> requestContextParameters;

    private Map<String, String> requestMap;
    private HttpContext httpContext;

    public BxClient(String account, String password, String domain, boolean isDev, String host, int port,
            String uri, String schema, String p13n_username, String p13n_password, HttpContext httpContext,
            String apiKey, String apiSecret) throws BoxalinoException {
        //default value start
        if (host == null || host.equals(Helper.Common.EMPTY_STRING)) {
            host = null;
        }
        if (port == 0) {
            port = 0;
        }
        if (uri == null || uri.equals(Helper.Common.EMPTY_STRING)) {
            uri = null;
        }
        if (schema == null || schema.equals(Helper.Common.EMPTY_STRING)) {
            schema = null;
        }
        if (p13n_username == null || p13n_username.equals(Helper.Common.EMPTY_STRING)) {
            p13n_username = null;
        }
        if (p13n_password == null || p13n_password.equals(Helper.Common.EMPTY_STRING)) {
            p13n_password = null;
        }

        this.chooseRequests = new ArrayList<>();
        this.requestMap = new HashMap<>();
        this._timeout = 2;
        this.requestContextParameters = new HashMap<>();

        this.account = account;
        this.password = password;
        this.isDev = isDev;

        this.host = host;
        if (host == null) {
            this.host = "main.bx-cloud.com";
        }
        if (apiKey == null || apiKey.equals(Helper.Common.EMPTY_STRING)) {
            this.host = "cdn.bx-cloud.com";
        }
        this.port = port;
        if (this.port == 0) {
            this.port = 443;
        }
        this.uri = uri;
        if (this.uri == null) {
            this.uri = "/p13n.web/p13n";
        }
        this.schema = schema;
        if (this.schema == null) {
            this.schema = "https";
        }
        this.p13n_username = p13n_username;
        if (this.p13n_username == null) {
            this.p13n_username = "boxalino";
        }
        this.p13n_password = p13n_password;
        if (this.p13n_password == null) {
            this.p13n_password = "tkZ8EXfzeZc6SdXZntCU";
        }
        this.domain = domain;
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        //default value end

        this.httpContext = httpContext;

    }

    public void setRequestMap(Map<String, String> requestMap) {
        this.requestMap = requestMap;
    }

    public String getAccount(boolean checkDev) {
        //default start            
        checkDev = true;
        //default end

        if (checkDev && this.isDev) {
            return this.account + "_dev";
        }
        return this.account;
    }

    public String getUsername() {
        return this.getAccount(false);
    }

    public String getPassword() {
        return this.password;
    }

    public String getApiKey() {
        return this.apiKey;
    }

    public String getApiSecret() {
        return this.apiSecret;
    }

    public void setSessionAndProfile(String sessionId, String profileId) {
        this.httpContext.setSessionAndProfile(sessionId, profileId);
    }

    private String[] getSessionAndProfile() throws BoxalinoException {
        return this.httpContext.getSessionAndProfile(null, null, this.domain);
    }

    private UserRecord getUserRecord() {
        UserRecord userRecord = new UserRecord();
        userRecord.username = this.getAccount(true);
        userRecord.apiKey = this.getApiKey();
        userRecord.apiSecret = this.getApiSecret();
        return userRecord;
    }

    private Client getP13n(int timeout, boolean useCurlIfAvailable) throws IOException,
            UnsupportedEncodingException, TTransportException, URISyntaxException, MalformedURLException {
        try {
            //default start
            if (timeout == 0) {
                timeout = 2;
            }
            //default end
            useCurlIfAvailable = false;
            THttpClient transport = null;
            if (useCurlIfAvailable) {

            } else {
                try {
                    transport = new THttpClient(
                            new URI(String.format("%s://%s%s", this.schema, this.host, this.uri)).toURL()
                                    .toString());
                } catch (TTransportException ex) {
                    throw ex;
                }
            }
            transport.setCustomHeader("Authorization", "Basic " + Base64.getEncoder()
                    .encodeToString((this.p13n_username + ':' + this.p13n_password).getBytes("UTF-8")));
            Client client = new Client(new TCompactProtocol(transport));
            transport.open();
            return client;
        } catch (UncheckedIOException ex) {
            throw ex.getCause();
        }
    }

    private Map<String, ArrayList<String>> getRequestContextParameters() {
        Map<String, ArrayList<String>> parameters = this.requestContextParameters;
        chooseRequests.forEach((request) -> {
            request.getRequestContextParameters().entrySet().forEach((v) -> {
                parameters.put(v.getKey(), new ArrayList<String>(v.getValue()));
            });
        });
        return parameters;
    }

    public RequestContext getRequestContext() throws URISyntaxException, BoxalinoException {
        String[] list;
        list = this.getSessionAndProfile();
        setSessionAndProfile(list[0], list[1]);
        RequestContext requestContext = new RequestContext();
        String sessionIdd = this.httpContext.getSessionId(this.domain);
        requestContext.parameters = new HashMap<String, List<String>>() {
            {
                put("User-Agent", new ArrayList<String>() {
                    {
                        add(httpContext.getUserAgent());
                    }
                });
                put("User-Host", new ArrayList<String>() {
                    {
                        add(httpContext.getIP());
                    }
                });
                put("User-SessionId", new ArrayList<String>() {
                    {
                        add(sessionIdd);
                    }
                });
                put("User-Referer", new ArrayList<String>() {
                    {

                        add(httpContext.getReferer());
                    }
                });
                put("User-URL", new ArrayList<String>() {
                    {
                        add(httpContext.getCurrentUrl());
                    }
                });

            }
        };
        this.getRequestContextParameters().entrySet().forEach((k) -> {
            requestContext.parameters.put(k.getKey(), k.getValue());
        });
        if (this.requestMap != null && requestMap.containsKey("p13nRequestContext")) {
            Map<String, String> requestMapp = this.requestMap;
            requestContext.parameters = new HashMap<String, List<String>>() {
                {
                    put(requestMapp.get("p13nRequestContext"), new ArrayList<String>() {
                        {
                            add(requestContext.parameters.get("p13nRequestContext").toString());
                        }
                    });

                }
            };
        }
        return requestContext;
    }

    public ChoiceRequest getChoiceRequest(ArrayList<ChoiceInquiry> inquiries, RequestContext requestContext)
            throws URISyntaxException, BoxalinoException {
        ChoiceRequest choiceRequest = new ChoiceRequest();
        String[] list;
        list = this.getSessionAndProfile();

        choiceRequest.userRecord = this.getUserRecord();
        choiceRequest.profileId = this.httpContext.getProfileId(this.domain);
        choiceRequest.inquiries = inquiries;
        if (requestContext == null) {
            requestContext = this.getRequestContext();
        }
        choiceRequest.requestContext = requestContext;
        return choiceRequest;
    }

    public void addRequestContextParameter(String name, ArrayList<String> value) {
        this.requestContextParameters.put(name, value);
    }

    public void resetRequestContextParameter() {
        this.requestContextParameters = new HashMap<>();
    }

    protected Map<String, ArrayList<String>> getBasicRequestContextParameters()
            throws URISyntaxException, BoxalinoException {
        String sessionId = this.httpContext.getSessionId(this.domain);
        String profileId = this.httpContext.getProfileId(this.domain);
        return new HashMap<String, ArrayList<String>>() {
            {
                put("User-Agent", new ArrayList<String>() {
                    {
                        add(httpContext.getUserAgent());
                    }
                });
                put("User-Host", new ArrayList<String>() {
                    {
                        add(httpContext.getIP());
                    }
                });
                put("User-SessionId", new ArrayList<String>() {
                    {
                        add(sessionId);
                    }
                });
                put("User-Referer", new ArrayList<String>() {
                    {

                        add(httpContext.getReferer());

                    }
                });
                put("User-URL", new ArrayList<String>() {
                    {
                        add(httpContext.getCurrentUrl());
                    }
                });

            }
        };

    }

    private void throwCorrectP13nException(BoxalinoException e) throws BoxalinoException {
        if (e.getMessage().indexOf("Could not connect ") <= 0) {
            throw new BoxalinoException(
                    "The connection to our server failed even before checking your credentials. This might be typically caused by 2 possible things: wrong values in host, port, schema or uri (typical value should be host=cdn.bx-cloud.com, port=443, uri =/p13n.web/p13n and schema=https, your values are : host=' . "
                            + this.host + ", port=" + this.port + ", schema=" + this.schema + ", uri=" + this.uri
                            + "). Another possibility, is that your server environment has a problem with ssl certificate (peer certificate cannot be authenticated with given ca certificates). Full error message= "
                            + e.getMessage());
        }

        if (e.getMessage().indexOf("Bad protocol id in TCompact message") <= 0) {
            throw new BoxalinoException(
                    "The connection to our server has worked, but your credentials were refused. Provided credentials username="
                            + this.p13n_username + ", password=" + this.p13n_password + ". Full error message="
                            + e.getMessage());
        }

        if (e.getMessage().indexOf("choice not found") <= 0) {
            String[] parts = e.getMessage().split("choice not found", -1);
            String[] pieces = parts[1].split("at", -1);
            String choiceId = pieces[0].replace(':', ' ');
            throw new BoxalinoException("Configuration not live on account " + this.getAccount(true) + ": choice "
                    + choiceId
                    + " doesn't exist. NB: If you get a message indicating that the choice doesn't exist, go to http://intelligence.bx-cloud.com, log in your account and make sure that the choice id you want to use is published.");
        }

        if (e.getMessage().indexOf("Solr returned status 404") <= 0) {
            throw new BoxalinoException("Data not live on account " + this.getAccount(true)
                    + ": index returns status 404. Please publish your data first, like in example backend_data_basic.php.");

        }

        if (e.getMessage().indexOf("undefined field") <= 0) {
            String[] parts = e.getMessage().split("undefined field", -1);
            String[] pieces = parts[1].split("at", -1);
            String field = pieces[0].replace(':', ' ');

            throw new BoxalinoException("You request in your filter or facets a non-existing field of your account "
                    + this.getAccount(true) + ": field " + field + " doesn't exist.");
        }

        if (e.getMessage().indexOf("All choice variants are excluded") <= 0) {
            throw new BoxalinoException(
                    "You have an invalid configuration for with a choice defined, but having no defined strategies. This is a quite unusual case, please contact support@boxalino.com to get support.");
        }

        throw e;
    }

    private ChoiceResponse p13nchoose(ChoiceRequest choiceRequest)
            throws UnsupportedEncodingException, TException, IOException, URISyntaxException {
        //ChoiceResponse choiceResponse = this.getP13n(this._timeout, false).choose(choiceRequest);

        ChoiceResponse choiceResponse = pooledClient(choiceRequest);
        if (this.requestMap.size() > 0 && this.requestMap.get("dev_bx_disp") != null
                && this.requestMap.get("dev_bx_disp").equals("true")) {

            httpContext.responseWrite("<pre><h1>Choice Request</h1>");
            httpContext.responseWrite(choiceRequest.getClass().getName());
            httpContext.responseWrite("Inquiries" + choiceRequest.inquiries);
            httpContext.responseWrite("ProfileId" + choiceRequest.profileId);
            httpContext.responseWrite("RequestContext" + choiceRequest.requestContext);
            httpContext.responseWrite("UserRecord" + choiceRequest.userRecord);

            httpContext.responseWrite("<br><h1>Choice Response</h1>");
            httpContext.responseWrite(choiceRequest.getClass().getName());
            httpContext.responseWrite("Variants" + choiceResponse.variants);
            httpContext.responseWrite("</pre>");
        }
        return choiceResponse;
    }

    public void addRequest(BxRequest request) {
        request.setDefaultIndexId(this.getAccount(true));
        request.setDefaultRequestMap(this.requestMap);
        this.chooseRequests.add(request);
    }

    public void resetRequests() {
        this.chooseRequests = new ArrayList<>();
    }

    public BxRequest getRequest(int index) {
        if (this.chooseRequests.size() <= index) {
            return null;
        }
        return this.chooseRequests.get(index);
    }

    public BxRequest getChoiceIdRecommendationRequest(String choiceId) {
        for (BxRequest request : chooseRequests) {
            if (request.getChoiceId().equals(choiceId)) {
                return request;
            }
        }
        return null;
    }

    public ArrayList<BxRequest> getRecommendationRequests() {
        ArrayList<BxRequest> requests = new ArrayList<>();

        chooseRequests.stream().filter((request) -> (request instanceof BxRecommendationRequest))
                .forEachOrdered((request) -> {
                    requests.add((BxRequest) request);
                });
        return requests;
    }

    public ChoiceRequest getThriftChoiceRequest() throws BoxalinoException {
        try {
            ArrayList<ChoiceInquiry> choiceInquiries = new ArrayList<>();

            for (BxRequest request : this.chooseRequests) {
                ChoiceInquiry choiceInquiry = new ChoiceInquiry();
                choiceInquiry.choiceId = request.getChoiceId();
                choiceInquiry.simpleSearchQuery = request.getSimpleSearchQuery();
                choiceInquiry.contextItems = request.getContextItems();
                choiceInquiry.minHitCount = (int) request.getMin();
                choiceInquiry.withRelaxation = request.getWithRelaxation();
                choiceInquiries.add(choiceInquiry);
            }

            ChoiceRequest choiceRequest = this.getChoiceRequest(choiceInquiries, this.getRequestContext());
            return choiceRequest;
        } catch (URISyntaxException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        }
    }

    protected void choose() throws BoxalinoException {
        try {
            this.chooseResponses = this.p13nchoose(this.getThriftChoiceRequest());
        } catch (TException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        } catch (UnsupportedEncodingException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        } catch (IOException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        } catch (URISyntaxException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        }
    }

    public BxChooseResponse getResponse() throws BoxalinoException {
        if (this.chooseResponses == null) {
            this.choose();

        }
        return new BxChooseResponse(this.chooseResponses, this.chooseRequests);
    }

    private void enhanceAutoCompleterequest(BxAutocompleteRequest request) {
        request.setDefaultIndexId(this.getAccount(true));
    }

    public void setAutocompleteRequests(ArrayList<BxAutocompleteRequest> requests) {
        for (BxAutocompleteRequest request : requests) {
            this.enhanceAutoCompleterequest(request);
        }
        this.autocompleteRequests = requests;
    }

    public void setAutocompleteRequest(ArrayList<BxAutocompleteRequest> request) {
        this.setAutocompleteRequests(request);
    }

    private AutocompleteResponse p13nautocomplete(AutocompleteRequest autocompleteRequest) throws IOException,
            UnsupportedEncodingException, TException, URISyntaxException, MalformedURLException {
        try {
            return this.getP13n(this._timeout, false).autocomplete(autocompleteRequest);
        } catch (UncheckedIOException ex) {
            throw ex.getCause();
        }
    }

    public ArrayList<AutocompleteRequest> use(ArrayList<BxAutocompleteRequest> request, String profileId,
            UserRecord userRecord) {
        ArrayList<AutocompleteRequest> listAutocompleteRequest = new ArrayList<>();
        request.forEach((req) -> {
            listAutocompleteRequest.add(req.getAutocompleteThriftRequest(profileId, userRecord));
        });
        return listAutocompleteRequest;
    }

    public ArrayList<BxAutocompleteResponse> use(ArrayList<BxAutocompleteResponse> response, int i) {
        BxAutocompleteRequest request = this.autocompleteRequests.get(++i);
        ArrayList<BxAutocompleteResponse> bxAutocompleteResponse = new ArrayList<>();
        for (Object req : response) {
            bxAutocompleteResponse.add(new BxAutocompleteResponse((AutocompleteResponse) req, request));
        }
        return bxAutocompleteResponse;

    }

    public ArrayList<BxAutocompleteResponse> use1(List<AutocompleteResponse> response, int i) {
        BxAutocompleteRequest request = this.autocompleteRequests.get(++i);
        ArrayList<BxAutocompleteResponse> bxAutocompleteResponse = new ArrayList<>();
        for (Object req : response) {
            bxAutocompleteResponse.add(new BxAutocompleteResponse((AutocompleteResponse) req, request));
        }
        return bxAutocompleteResponse;

    }

    private List<AutocompleteResponse> p13nautocompleteAll(ArrayList<AutocompleteRequest> requests)
            throws IOException, UnsupportedEncodingException, TException, URISyntaxException,
            MalformedURLException {
        try {
            AutocompleteRequestBundle requestBundle = new AutocompleteRequestBundle();
            requestBundle.requests = requests;
            return this.getP13n(this._timeout, false).autocompleteAll(requestBundle).responses;
        } catch (UncheckedIOException ex) {
            throw ex.getCause();
        }
    }

    public void autocomplete() throws IOException, UnsupportedEncodingException, TException, URISyntaxException,
            MalformedURLException, BoxalinoException {
        try {

            UserRecord userRecord = this.getUserRecord();

            ArrayList<AutocompleteRequest> p13nrequests = use(this.autocompleteRequests,
                    this.httpContext.getSessionId(this.domain), userRecord);
            int i = -1;
            this.autocompleteResponses = use1(this.p13nautocompleteAll(p13nrequests), i);
        } catch (UncheckedIOException ex) {
            throw ex.getCause();
        }

    }

    public ArrayList<BxAutocompleteResponse> getAutocompleteResponses() throws BoxalinoException {
        try {
            if (this.autocompleteResponses == null) {
                this.autocomplete();
            }
            return this.autocompleteResponses;
        } catch (IOException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        } catch (TException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        } catch (URISyntaxException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        }
    }

    public void setTimeout(int timeout) {
        this._timeout = timeout;
    }

    public BxAutocompleteResponse getAutocompleteResponse() throws BoxalinoException {
        try {
            List<BxAutocompleteResponse> responses = null;

            responses = this.getAutocompleteResponses();

            if (responses.get(0) != null) {
                return responses.get(0);
            }
            return null;
        } catch (UncheckedIOException ex) {
            throw new BoxalinoException(ex.getMessage(), ex.getCause());
        }
    }

    public ChoiceResponse pooledClient(ChoiceRequest choiceRequest)
            throws URISyntaxException, MalformedURLException {

        String url = null;
        url = new URI(String.format("%s://%s%s", this.schema, this.host, this.uri)).toURL().toString();

        String username = this.p13n_username, pwd = this.p13n_password;

        ClientPool pool = PoolProvider.getDefault(url, username, pwd);

        ChoiceResponse response = pool.withClient(client -> {
            ChoiceResponse choiceResponse = client.choose(choiceRequest);
            return choiceResponse;
        });
        return response;

    }

}