com.formkiq.core.equifax.service.EquifaxServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.equifax.service.EquifaxServiceImpl.java

Source

/*
 * Copyright (C) 2017 FormKiQ Inc.
 *
 * Licensed 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 com.formkiq.core.equifax.service;

import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.CACHED;
import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.ERROR;
import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.NEW;
import static com.formkiq.core.form.FormFinder.findValueByKey;
import static com.formkiq.core.util.Strings.extractLabelAndValue;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.formkiq.core.form.dto.FormJSON;
import com.formkiq.core.form.dto.FormJSONField;
import com.formkiq.core.util.DateService;

/**
 * Equifax Services Implementation.
 *
 */
public class EquifaxServiceImpl implements EquifaxService {

    /** {@link EntityManager}. */
    private EntityManager em;

    /** {@link DateService}. */
    @Autowired
    private DateService dateService;

    /** TransactionManager. */
    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * constructor.
     * @param entityManager {@link EntityManager}
     */
    public EquifaxServiceImpl(final EntityManager entityManager) {
        this.em = entityManager;
    }

    @Override
    public List<EquifaxCreditCheck> findAll(final Date start, final Date end) {
        String sql = "select e.request, e.response, e.request_type, " + " e.url, e.requester, e.inserted_date "
                + "from equifax_credit_checks e " + " where e.inserted_date between :start and :end"
                + " order by inserted_date desc";

        Calendar c = Calendar.getInstance();
        c.setTime(end);
        c.add(Calendar.DAY_OF_MONTH, 1);

        Query query = this.em.createNativeQuery(sql).setParameter("start", this.dateService.removeTime(start))
                .setParameter("end", this.dateService.removeTime(c.getTime()));

        return transform(query);
    }

    @Override
    public EquifaxCreditCheck getCachedResponse(final String request, final Date date) {

        String sql = "select e.request, e.response, e.request_type, " + " e.url, e.requester, e.inserted_date "
                + "from equifax_credit_checks e " + " where e.request=:request and e.inserted_date >= :date "
                + " order by inserted_date desc";

        Query query = this.em.createNativeQuery(sql).setParameter("request", request).setParameter("date", date);

        List<EquifaxCreditCheck> results = transform(query);
        return !results.isEmpty() ? results.get(0) : null;
    }

    /**
     * Get Equifax Credit Check URL.
     * @param form {@link FormJSON}
     * @return {@link String}
     */
    private String getCreditCheckUrl(final FormJSON form) {
        String host = extractLabelAndValue(findValueByKey(form, "host").get().getValue()).getRight();
        return host + "/sts/processinquiry.asp";
    }

    /**
     * Get Request Cache.
     * @param form {@link FormJSON}
     * @return int
     */
    private int getRequestCache(final FormJSON form) {
        int cache = 0;
        Optional<FormJSONField> op = findValueByKey(form, "requestcache");
        if (op.isPresent()) {
            cache = NumberUtils.toInt(op.get().getValue(), 0);
        }

        return cache;
    }

    /**
     * Save Equifax Response.
     * @param cc {@link EquifaxCreditCheck}
     */
    private void saveResponse(final EquifaxCreditCheck cc) {

        TransactionTemplate transactionTemplate = new TransactionTemplate(this.transactionManager);

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(final TransactionStatus status) {
                EquifaxServiceImpl.this.em
                        .createNativeQuery("insert into equifax_credit_checks"
                                + "(equifax_credit_check_id, url, request, response, "
                                + "request_type,requester, inserted_date) "
                                + "values (:id,:url,:req,:resp,:type,:requester,:date)")
                        .setParameter("id", UUID.fromString(cc.getCreditcheckid())).setParameter("url", cc.getUrl())
                        .setParameter("req", cc.getRequest()).setParameter("resp", cc.getResponse())
                        .setParameter("type", cc.getRequesttype().name())
                        .setParameter("requester", cc.getRequester()).setParameter("date", new Date())
                        .executeUpdate();
            }
        });
    }

    @Override
    public EquifaxCreditCheck sendCreditCheck(final FormJSON form, final String request) {

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -1 * getRequestCache(form));

        EquifaxCreditCheck resp = getCachedResponse(request, calendar.getTime());

        if (resp == null) {

            EquifaxCreditCheckRequestType status = NEW;
            String url = getCreditCheckUrl(form);

            resp = new EquifaxCreditCheck();
            resp.setRequest(request);
            resp.setUrl(url);

            try {
                String response = sendToEquifax(url, request);
                resp.setResponse(response);
            } catch (Exception e) {
                resp.setResponse(e.getMessage());
                status = ERROR;
            }

            resp.setRequesttype(status);

        } else {
            resp.setRequesttype(CACHED);
        }

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        resp.setRequester(auth.getName());
        resp.setRequest(request);
        resp.setInserteddate(new Date());
        resp.setCreditcheckid(UUID.randomUUID().toString());

        saveResponse(resp);

        return resp;
    }

    /**
     * Sends request to Equifax.
     * @param server {@link String}
     * @param send {@link String}
     * @return {@link String}
     * @throws IOException IOException
     */
    public String sendToEquifax(final String server, final String send) throws IOException {

        String params = "InputSegments=" + URLEncoder.encode(send, "UTF-8") + "&cmdSubmit=Submit";

        byte[] postData = params.getBytes(StandardCharsets.UTF_8);
        int postDataLength = postData.length;

        URL url = new URL(server);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setInstanceFollowRedirects(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

        conn.setRequestProperty("charset", "utf-8");
        conn.setRequestProperty("Content-Length", Integer.toString(postDataLength));
        conn.setUseCaches(false);

        Reader in = null;
        DataOutputStream wr = null;

        try {
            wr = new DataOutputStream(conn.getOutputStream());
            wr.write(postData);

            StringBuilder sb = new StringBuilder();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

            for (int c = in.read(); c != -1; c = in.read()) {
                sb.append((char) c);
            }

            String receive = sb.toString();

            return receive;

        } finally {

            if (in != null) {
                in.close();
            }

            if (wr != null) {
                wr.close();
            }
        }
    }

    /**
     * Transforms Database query to {@link EquifaxCreditCheck}.
     * @param vals Object[]
     * @return {@link EquifaxCreditCheck}
     */
    private EquifaxCreditCheck transform(final Object[] vals) {
        int i = 0;

        EquifaxCreditCheck response = new EquifaxCreditCheck();

        response.setRequest(vals[i++].toString());
        response.setResponse(vals[i++].toString());
        response.setRequesttype(EquifaxCreditCheckRequestType.valueOf(vals[i++].toString()));
        response.setUrl(vals[i++].toString());
        response.setRequester(vals[i++].toString());
        response.setInserteddate((Date) vals[i++]);

        return response;
    }

    /**
     * Transform {@link Query} to {@link List} of {@link EquifaxCreditCheck}.
     * @param query {@link Query}
     * @return {@link List} of {@link EquifaxCreditCheck}
     */
    @SuppressWarnings("unchecked")
    private List<EquifaxCreditCheck> transform(final Query query) {
        List<Object[]> responses = query.getResultList();
        List<EquifaxCreditCheck> results = new ArrayList<>(responses.size());

        for (Object[] vals : responses) {
            EquifaxCreditCheck response = transform(vals);
            results.add(response);
        }
        return results;
    }
}