gov.medicaid.screening.dao.impl.ChiropracticLicenseDAOBean.java Source code

Java tutorial

Introduction

Here is the source code for gov.medicaid.screening.dao.impl.ChiropracticLicenseDAOBean.java

Source

/*
 * Copyright (C) 2012 TopCoder Inc., All Rights Reserved.
 */
package gov.medicaid.screening.dao.impl;

import gov.medicaid.entities.Address;
import gov.medicaid.entities.ChiropracticLicenseSearchCriteria;
import gov.medicaid.entities.License;
import gov.medicaid.entities.LicenseStatus;
import gov.medicaid.entities.LicenseType;
import gov.medicaid.entities.ProviderProfile;
import gov.medicaid.entities.SearchResult;
import gov.medicaid.entities.Sex;
import gov.medicaid.entities.User;
import gov.medicaid.screening.dao.ChiropracticLicenseDAO;
import gov.medicaid.screening.services.ErrorCode;
import gov.medicaid.screening.services.ParsingException;
import gov.medicaid.screening.services.PersistenceException;
import gov.medicaid.screening.services.ServiceException;
import gov.medicaid.screening.services.impl.LogUtil;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * This defines the logic for searching for Chiropractic Licenses.
 * 
 * @author sampath01, j3_guile
 * @version 1.0
 */
@Stateless
@Local(ChiropracticLicenseDAO.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ChiropracticLicenseDAOBean extends BaseDAO implements ChiropracticLicenseDAO {

    /**
     * Host used for denied list.
     */
    @Resource(name = "mita/config/disciplineURL")
    private String disciplineURL;

    /**
     * Default empty constructor.
     */
    public ChiropracticLicenseDAOBean() {
    }

    /**
     * The supported columns for this implementation.
     */
    private static final Map<String, String> SORT_COLUMNS = new HashMap<String, String>() {
        {
            put("firstName", "profile.user.firstName");
            put("middleName", "profile.user.middleName");
            put("lastName", "profile.user.lastName");
            put("type", "type.name");
            put("originalIssueDate", "originalIssueDate");
            put("expireDate", "expireDate");
            put("renewalDate", "renewalDate");
            put("licenseNumber", "licenseNumber");
        }
    };

    /**
     * The supported license type mappings for this source.
     */
    private static final Map<String, String> TYPES = new HashMap<String, String>() {
        {
            put("byLname", "Search By Name");
            put("bySoundex", "   Sounding Like   ");
            put("byCity", "   Search By City  ");
            put("byZIP", "   Search By ZIP   ");
        }
    };

    /**
     * Date format used by this source.
     */
    private static final String DATE_FORMAT = "M/d/yy";

    /**
     * Searches for providers with Chiropractic license using the name filter.
     * 
     * @param criteria
     *            the search criteria
     * @return the matched results
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    public SearchResult<License> searchByLastName(ChiropracticLicenseSearchCriteria criteria)
            throws ParsingException, ServiceException {
        String signature = "ChiropracticLicenseDataAccessImpl#searchByLastName";
        LogUtil.traceEntry(getLog(), signature, new String[] { "criteria" }, new Object[] { criteria });

        if (criteria == null) {
            throw new ServiceException(ErrorCode.MITA10005.getDesc());
        }

        if (Util.isBlank(criteria.getLastName())) {
            throw new ServiceException(ErrorCode.MITA10001.getDesc());
        }

        SearchResult<License> results = search(criteria, "byLname");
        return LogUtil.traceExit(getLog(), signature, results);
    }

    /**
     * Searches for providers with Chiropractic license using the city filter.
     * 
     * @param criteria
     *            the search criteria
     * @return the matched results
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    public SearchResult<License> searchByCity(ChiropracticLicenseSearchCriteria criteria)
            throws ParsingException, ServiceException {
        String signature = "ChiropracticLicenseDataAccessImpl#searchByCity";
        LogUtil.traceEntry(getLog(), signature, new String[] { "criteria" }, new Object[] { criteria });

        if (criteria == null) {
            throw new ServiceException(ErrorCode.MITA10005.getDesc());
        }

        if (Util.isBlank(criteria.getCity())) {
            throw new ServiceException(ErrorCode.MITA10013.getDesc());
        }

        SearchResult<License> results = search(criteria, "byCity");
        return LogUtil.traceExit(getLog(), signature, results);
    }

    /**
     * Searches for providers with Chiropractic license using the zipcode filter.
     * 
     * @param criteria
     *            the search criteria
     * @return the matched results
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    public SearchResult<License> searchByZipCode(ChiropracticLicenseSearchCriteria criteria)
            throws ParsingException, ServiceException {
        String signature = "ChiropracticLicenseDataAccessImpl#searchByZipCode";
        LogUtil.traceEntry(getLog(), signature, new String[] { "criteria" }, new Object[] { criteria });

        if (criteria == null) {
            throw new ServiceException(ErrorCode.MITA10005.getDesc());
        }

        if (Util.isBlank(criteria.getZipCode())) {
            throw new ServiceException(ErrorCode.MITA10014.getDesc());
        }

        SearchResult<License> results = search(criteria, "byZIP");
        return LogUtil.traceExit(getLog(), signature, results);
    }

    /**
     * Searches for providers with Chiropractic license using the sounds like name filter.
     * 
     * @param criteria
     *            the search criteria
     * @return the matched results
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    public SearchResult<License> searchBySoundingLikeLastName(ChiropracticLicenseSearchCriteria criteria)
            throws ParsingException, ServiceException {
        String signature = "ChiropracticLicenseDataAccessImpl#searchBySoundingLikeLastName";
        LogUtil.traceEntry(getLog(), signature, new String[] { "criteria" }, new Object[] { criteria });

        if (criteria == null) {
            throw new ServiceException(ErrorCode.MITA10005.getDesc());
        }

        if (Util.isBlank(criteria.getLastName())) {
            throw new ServiceException(ErrorCode.MITA10001.getDesc());
        }

        SearchResult<License> results = search(criteria, "bySoundex");
        return LogUtil.traceExit(getLog(), signature, results);
    }

    /**
     * Retrieves all licensees that have disciplinary action record from the source site.
     * 
     * @param criteria
     *            the pagination criteria
     * @return the matched results
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    public SearchResult<License> getDeniedList(ChiropracticLicenseSearchCriteria criteria)
            throws ParsingException, ServiceException {

        if (criteria == null) {
            // pagination info should be included
            throw new ServiceException(ErrorCode.MITA10002.getDesc());
        }

        try {
            SearchResult<License> allResults = getAllDisciplinedResults();
            trimResults(allResults, criteria.getPageSize(), criteria.getPageNumber(), null, null);
            return allResults;
        } catch (ClientProtocolException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc());
        } catch (URISyntaxException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc());
        } catch (IOException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc());
        } catch (ParseException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc());
        }
    }

    /**
     * Executes the search of the given type.
     * 
     * @param criteria
     *            the search criteria
     * @param type
     *            the search type
     * @return the search results
     * @throws PersistenceException
     *             if any data access
     * @throws ParsingException
     *             if any parsing errors are encountered
     * @throws ServiceException
     *             for any other exceptions encountered
     */
    private SearchResult<License> search(ChiropracticLicenseSearchCriteria criteria, String type)
            throws ParsingException, ServiceException, PersistenceException {

        validateSortOptions(criteria, SORT_COLUMNS);

        try {

            SearchResult<License> allResults = getAllResults(criteria, type);
            SearchResult<License> results = trimResults(allResults, criteria.getPageSize(),
                    criteria.getPageNumber(), SORT_COLUMNS.get(criteria.getSortColumn()), criteria.getSortOrder());

            logSearchEntry(criteria);
            return results;
        } catch (ClientProtocolException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc(), e);
        } catch (URISyntaxException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc(), e);
        } catch (IOException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc(), e);
        } catch (ParseException e) {
            throw new ServiceException(ErrorCode.MITA50001.getDesc(), e);
        }
    }

    /**
     * Performs a search for all possible results.
     * 
     * @param criteria
     *            The search criteria.
     * @param searchType
     *            the type of search to execute.
     * @return the search result for licenses
     * 
     * @throws URISyntaxException
     *             if an error occurs while building the URL.
     * @throws ClientProtocolException
     *             if client does not support protocol used.
     * @throws IOException
     *             if an error occurs while parsing response.
     * @throws ParseException
     *             if an error occurs while parsing response.
     * @throws ServiceException
     *             for any other problems encountered
     */
    private SearchResult<License> getAllResults(ChiropracticLicenseSearchCriteria criteria, String searchType)
            throws URISyntaxException, ClientProtocolException, IOException, ParseException, ServiceException {
        DefaultHttpClient client = new DefaultHttpClient();
        client.setRedirectStrategy(new LaxRedirectStrategy());

        URIBuilder uriBuilder = new URIBuilder(getSearchURL());
        uriBuilder.addParameter("strName", Util.defaultString(criteria.getLastName()));
        uriBuilder.addParameter("strSoundex", Util.defaultString(criteria.getLastName()));
        uriBuilder.addParameter("strCity", Util.defaultString(criteria.getCity()));
        uriBuilder.addParameter("strZIP", Util.defaultString(criteria.getZipCode()));
        uriBuilder.addParameter(searchType, TYPES.get(searchType));

        HttpGet search = new HttpGet(uriBuilder.build());
        HttpResponse response = client.execute(search);
        verifyAndAuditCall(getSearchURL(), response);

        Document page = Jsoup.parse(EntityUtils.toString(response.getEntity()));
        List<License> allLicenses = new ArrayList<License>();

        Elements rows = page.select("tr:gt(0)");
        for (Element row : rows) {
            String href = row.select("a").first().attr("href"); // detail link
            String licenseType = row.select("td:eq(2)").text();

            HttpGet getDetails = new HttpGet(Util.replaceLastURLPart(uriBuilder.build().toString(), href));
            response = client.execute(getDetails);
            verifyAndAuditCall(getSearchURL(), response);

            page = Jsoup.parse(EntityUtils.toString(response.getEntity()));
            allLicenses.add(parseLicense(page, licenseType));
        }

        SearchResult<License> searchResult = new SearchResult<License>();
        searchResult.setItems(allLicenses);
        return searchResult;
    }

    /**
     * Retrieves all the practioners from the disciplined list.
     * 
     * @return the list of practitioners in the disciplined list
     * 
     * @throws URISyntaxException
     *             if an error occurs while building the URL.
     * @throws ClientProtocolException
     *             if client does not support protocol used.
     * @throws IOException
     *             if an error occurs while parsing response.
     * @throws ParseException
     *             if an error occurs while parsing response.
     * @throws ServiceException
     *             for any other problems encountered
     */
    private SearchResult<License> getAllDisciplinedResults()
            throws URISyntaxException, ClientProtocolException, IOException, ParseException, ServiceException {
        DefaultHttpClient client = new DefaultHttpClient();
        client.setRedirectStrategy(new LaxRedirectStrategy());

        HttpGet search = new HttpGet(new URIBuilder(getDisciplineURL()).build());
        HttpResponse response = client.execute(search);
        verifyAndAuditCall(getDisciplineURL(), response);

        Document page = Jsoup.parse(EntityUtils.toString(response.getEntity()));
        List<License> allLicenses = new ArrayList<License>();

        Elements rows = page.select("blockquote table tr:gt(0)");
        for (Element row : rows) {
            String fullname = row.select("td:eq(0)").text();
            License license = new License();
            ProviderProfile profile = new ProviderProfile();
            license.setProfile(profile);
            profile.setUser(parseDeniedListFullname(fullname));
            LicenseStatus status = new LicenseStatus();
            String action = row.select("td:eq(1)").text();
            status.setName(action);
            String date = row.select("td:eq(2)").text();
            status.setDate(parseDate(date, DATE_FORMAT));
            license.setStatus(status);
            allLicenses.add(license);
        }

        SearchResult<License> searchResult = new SearchResult<License>();
        searchResult.setItems(allLicenses);
        return searchResult;
    }

    /**
     * This parses the given fullname with specific rules to the denied list.
     * 
     * @param fullname
     *            the fullname to parse
     * @return the person name entity.
     */
    private static User parseDeniedListFullname(String fullname) {
        User user = new User();
        fullname = fullname.replaceAll("\\(.*\\)", ""); // remove extra comments
        String[] nameParts = fullname.split(",");
        if (nameParts.length > 0) {
            user.setLastName(nameParts[0].trim());
        }
        if (nameParts.length > 1) {
            String firstName = nameParts[1].trim();
            String[] firstNameParts = firstName.split(" ");
            StringBuilder sb = new StringBuilder();
            for (String string : firstNameParts) {
                if (string.endsWith(".")) {
                    user.setMiddleName(string);
                } else {
                    if (sb.length() > 0) {
                        sb.append(" ");
                    }
                    sb.append(string);
                }
            }
            user.setFirstName(sb.toString());
        }

        return user;
    }

    /**
     * Parses the Chiropractic license details page.
     * 
     * @param page
     *            the details page
     * @param licenseType
     *            if user has multiple licenses, this one will be used
     * @return the parsed license details
     * @throws ParsingException
     *             if the expected tags were not found
     */
    private License parseLicense(Document page, String licenseType) throws ParsingException {
        License license = new License();
        ProviderProfile profile = new ProviderProfile();
        license.setProfile(profile);

        User user = new User();
        profile.setUser(user);
        Elements tables = page.select("table");
        for (Element cell : tables.get(0).select("td")) {
            if (cell.text().equals("First Name")) {
                user.setFirstName(cell.nextElementSibling().text());
            } else if (cell.text().equals("Middle Name")) {
                user.setMiddleName(cell.nextElementSibling().text());
            } else if (cell.text().equals("Last Name")) {
                user.setLastName(cell.nextElementSibling().text());
            } else if (cell.text().equals("Gender")) {
                String gender = cell.nextElementSibling().text();
                if (Util.isNotBlank(gender)) {
                    if ("M".equalsIgnoreCase(gender)) {
                        profile.setSex(Sex.MALE);
                    } else {
                        profile.setSex(Sex.FEMALE);
                    }
                }
            }
        }

        List<Address> addresses = new ArrayList<Address>();
        Address address = new Address();
        addresses.add(address);
        profile.setAddresses(addresses);
        StringBuffer locBuffer = new StringBuffer();
        for (Element cell : tables.get(1).select("td")) {
            if (cell.text().equals("Address Line1")) {
                locBuffer.insert(0, cell.nextElementSibling().text() + " ");
            } else if (cell.text().equals("Address Line2")) {
                locBuffer.append(cell.nextElementSibling().text());
            } else if (cell.text().equals("City")) {
                address.setCity(cell.nextElementSibling().text());
            } else if (cell.text().equals("State")) {
                address.setState(cell.nextElementSibling().text());
            } else if (cell.text().equals("ZIP")) {
                address.setZipcode(cell.nextElementSibling().text());
            } else if (cell.text().equals("Phone Number")) {
                profile.setContactPhoneNumber(cell.nextElementSibling().text());
            }
        }
        address.setLocation(locBuffer.toString().trim());

        for (Element row : tables.get(2).select("tr")) {
            String lType = row.select("td:eq(0)").text();
            if (licenseType != null && !lType.startsWith(licenseType)) {
                // user has multiple licenses, the results will show this user twice (search by name)
                continue;
            }

            LicenseType type = new LicenseType();
            type.setName(row.select("td:eq(0)").text());
            license.setType(type);
            license.setLicenseNumber(row.select("td:eq(1)").text());

            LicenseStatus status = new LicenseStatus();
            status.setName(row.select("td:eq(2)").text());
            license.setStatus(status);

            String issueDate = row.select("td:eq(3)").text();
            if (Util.isNotBlank(issueDate)) {
                license.setOriginalIssueDate(parseDate(issueDate, DATE_FORMAT));
            }

            String renewalDate = row.select("td:eq(4)").text();
            if (Util.isNotBlank(renewalDate)) {
                license.setRenewalDate(parseDate(renewalDate, DATE_FORMAT));
            }

            String expirationDate = row.select("td:eq(5)").text();
            if (Util.isNotBlank(expirationDate)) {
                license.setExpireDate(parseDate(expirationDate, DATE_FORMAT));
            }
        }
        return license;
    }

    public String getDisciplineURL() {
        return disciplineURL != null ? disciplineURL : jndiGet("java:comp/env/mita/config/disciplineURL");
    }
}