org.extensiblecatalog.ncip.v2.millennium.MillenniumLookupUserService.java Source code

Java tutorial

Introduction

Here is the source code for org.extensiblecatalog.ncip.v2.millennium.MillenniumLookupUserService.java

Source

/**
 * Copyright (c) 2010 eXtensible Catalog Organization
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the MIT/X11 license. The text of the license can be
 * found at http://www.opensource.org/licenses/mit-license.php.
 */

package org.extensiblecatalog.ncip.v2.millennium;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.extensiblecatalog.ncip.v2.service.*;

/**
 * This class implements the Lookup User service for the Dummy back-end
 * connector. Basically this just calls the DummyRemoteServiceManager to get
 * hard-coded data (e.g. title, call #, etc.).
 * <p/>
 * Note: If you're looking for a model of how to code your own ILS's NCIPService
 * classes, do not use this class as an example. See the NCIP toolkit Connector
 * developer's documentation for guidance.
 */
public class MillenniumLookupUserService implements LookupUserService {

    Config strConfig = new org.extensiblecatalog.ncip.v2.millennium.Config();

    String IIIClassicBaseUrl = strConfig.getProperty("millenniumUrl");

    String authenticatedUserId = "";

    UserId user = new UserId();

    String finesTable = "";

    /**
     * Construct a DummyRemoteServiceManager; this class is not configurable so
     * there are no parameters.
     */
    public MillenniumLookupUserService() {
    }

    /**
     * User / Password
     */
    String authenticatedUserName = strConfig.getProperty("tempUser");
    String authenticatedUserPassword = strConfig.getProperty("tempPass");

    /**
     * HttpClient used for screen scraping the web opac
     */
    private HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager());

    /**
     * Handles a NCIP LookupUser service by returning hard-coded data.
     * 
     * @param initData
     *            the LookupUserInitiationData
     * @param serviceManager
     *            provides access to remote services
     * @return LookupUserResponseData
     */
    @Override
    public LookupUserResponseData performService(LookupUserInitiationData initData,
            RemoteServiceManager serviceManager) {

        String baseUrl = "https://" + IIIClassicBaseUrl + "/patroninfo%7ES0/";

        final LookupUserResponseData responseData = new LookupUserResponseData();

        String userId = initData.getUserId().getUserIdentifierValue();

        MillenniumRemoteServiceManager millenniumSvcMgr = (MillenniumRemoteServiceManager) serviceManager;

        String strSessionId = millenniumSvcMgr.getIIISessionId(baseUrl);

        String redirectedUrl = millenniumSvcMgr.authenticate(authenticatedUserName, authenticatedUserPassword,
                baseUrl, strSessionId);

        // if the returned logIntoWebForm isn't null
        if (redirectedUrl != null) {
            // extract the iii id from the URL
            int start = redirectedUrl.indexOf("~S0/");

            // Check to see if we're not redirected to the "top"
            int end = redirectedUrl.indexOf("/top");
            if (end == -1) {
                end = redirectedUrl.indexOf("/items");
            }

            String urid = redirectedUrl.substring(start, end).replace("~S0/", "");

            authenticatedUserId = urid;
        }

        boolean getBlockOrTrap = false;
        boolean getAddress = true;
        boolean getVisibleUserID = true;
        boolean getFines = true;
        boolean getHolds = false;
        boolean getLoans = false;
        boolean getRecalls = false;
        boolean getMessages = false;

        // System.out.println("xcLookupUser authID: " + authenticatedUserId);
        // System.out.println("xcLookupUser redirUrl: " + redirectedUrl);

        // setup lookup method
        GetMethod lookupMethod = new GetMethod(redirectedUrl);
        lookupMethod.addRequestHeader("Cookie", "III_SESSION_ID=" + strSessionId);

        try {
            try {
                client.executeMethod(lookupMethod);
            } catch (HttpException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            String html = lookupMethod.getResponseBodyAsString();
            // log.error(html);

            /**
             * Boolean Values to Return as objects
             */

            // TODO xcLookupUser: Finish getBlockOrTrap
            // If getBlockOrTrap is true, the returned users list of blocks
            // must contain all blocks currently placed on the user represented
            // by the userId field.
            if (getBlockOrTrap) {
                // log.debug("Get Block or Trap");
                System.out.println("Todo: Get Block or Trap");
            }

            // TODO xcLookupUser: Finish getAddres (Temp Address) if possible
            // If getMessages is true, the returned users list of messages must
            // contain all messages applying the user represented by the userId

            if (getAddress) {
                // log.debug("Get Address");
                Pattern address = Pattern.compile(
                        "^<span(.*?)class=\"large\">(?s)(.*?)</form>(?s)(.*?)<p>(?s)(.*?)<br />(?s)(.*?)<p>(?s)(.*?)</span>$",
                        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
                Matcher addressMatch = address.matcher(html);

                addressMatch.find();
                // System.out.println(addressMatch.group(5));

                String strAddress = addressMatch.group(5).replaceAll("<br />", "|").replaceAll("\\n", "")
                        .replaceAll("||", "");
                strAddress = strAddress.replace("||", "");

                // returnUser.setAddress(strAddress);
                System.out.println("Found the home address " + strAddress);
                // + " for the patron with patron ID " + patronId)
                // log.debug("Found the home address " + returnUser.getAddress()
                // + " for the patron with patron ID " + patronId);

            }

            // if true, the user's fullName must be set to the correct value for
            // the user represented by the userId field if this value is known.
            if (getVisibleUserID) {
                // log.debug("get Visible User Id");

                // If there were any results, build the full name string
                Pattern visibleId = Pattern.compile(
                        "^<span(.*?)class=\"large\">(?s)(.*?)</form>(?s)(.*?)<p>(?s)(.*?)<br />(?s)(.*?)<p>(?s)(.*?)</span>$",
                        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
                Matcher visibleIdMatch = visibleId.matcher(html);

                visibleIdMatch.find();
                // System.out.println(visibleIdMatch.group(4));

                // Clean up strName, removing tags
                String strName = visibleIdMatch.group(4).replace("<strong>", "").replace("</strong>", "");

                // set full name to strName, removing any unneded whitespaces
                String fullName = strName.trim();

                // Check to make sure it exists
                if (fullName.length() > 1) {

                    // setFullName(fullName);
                    System.out.println(fullName);

                    // log.debug("Found the user's full name to be "
                    // + returnUser.getFullName());
                } else {
                    // log
                    // .info("Could not find the name information for the patron with patron ID "
                    // + patronId);
                }

            }

            // TODO xcLookupUser: Finish getFines
            // if true the user's totalFinesCurrencyCode and totalFines fields
            // must be set to the correct values for the user represented by the
            // userId field if these values are known. In addition, the list of
            // fines must contain NCIPUserFine Objects for all fines the user
            // owes.
            if (getFines) {
                // log.debug("get Fines");
                // https://jasmine.uncc.edu/patroninfo~S0/1205433/overdues
                System.out.println("Get Fines");
                // System.out.println("Auth: " + authenticatedUserId);

                html = millenniumSvcMgr.getFines(authenticatedUserId, strSessionId);

                Pattern fines = Pattern.compile(
                        "^(?s)(.*?)<table(.*?)class=\"patFunc\">(?s)(.*?)</table>(?s)(.*?)$",
                        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);

                Matcher finesMatch = fines.matcher(html);

                if (finesMatch.matches()) {

                    finesTable = finesMatch.group(3).toString();

                }

                System.out.println(finesTable);

                System.out.println("==================");

                fines = Pattern.compile("^(?s)(.*?)<tr class=\"patFuncFinesEntryTitle\">(?s)(.*?)</tr>(?s)(.*?)$",
                        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);

                finesMatch = fines.matcher(finesTable);

                Pattern title = Pattern.compile("^(?s)(.*?)<em>(?s)(.*?)</em></td>(?s)(.*?)$",
                        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);

                while (finesMatch.find()) {

                    //for (int i=0; i < finesMatch.groupCount(); i++) {

                    System.out.println(finesMatch.group(2));

                    Matcher titleMatch = title.matcher(finesMatch.group(2));
                    // Grab the title out of the finesMatch string
                    System.out.println("=====");

                    if (titleMatch.matches()) {
                        System.out.println(titleMatch.group(2));
                    }

                    System.out.println("=====");

                    //}

                }

                System.out.println("==================");

                /*
                 * <table border="1" width="100%" class="patFunc"> <tbody>
                 * 
                 * </tbody> </table>
                 */

                // TODO Parse out fines, and add them to objects

            }

            // TODO xcLookupUser: Finish getHolds
            // If getHolds is true, the returned users list of holds must
            // contain NCIPUserRequestedItem Objects for all holds and callslips
            // the user represented by the userId field has placed.
            if (getHolds) {
                System.out.println("Todo: get holds");

                /*
                 * NCIPUserRequestedItem item = new
                 * NCIPUserRequestedItem(results .getDate("date_hold_placed"),
                 * // The date the request // was placed null, // The date the
                 * request is expected to become // available newItem); // The
                 * bibliographic ID of the item the // request is for
                 * 
                 * // Add the item to the list of requested items
                 * returnUser.addRequestedItem(item);
                 */
            }
            // If getLoans is true, the returned users list of checkedOutItems
            // must contain NCIPUserLoanedItem Objects for all items the user
            // represented by the userId field has checked out.
            if (getLoans) {
                System.out.println("get Loans");

                // Setup Request URL
                String requestUrl = redirectedUrl.substring(0, redirectedUrl.lastIndexOf("/")) + "/items";

                // setup getLoans method
                GetMethod getLoansMethod = new GetMethod(requestUrl);
                getLoansMethod.addRequestHeader("Cookie", "III_SESSION_ID=" + strSessionId);

                // Grab items page
                try {
                    client.executeMethod(getLoansMethod);

                    String loansHtml = getLoansMethod.getResponseBodyAsString();
                    // Parse out the second page

                    // System.out.println(loansHtml);

                    // If there were any results, build the full name string
                    Pattern loans = Pattern.compile(
                            "^(?s)(.*?)<table(.*?)class=\"patFunc\">(?s)(.*?)<th(.*?)>(?s)(.*?)</th>(?s)(.*?)</tr>(?s)(.*?)</table>(?s)(.*?)$",
                            Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);

                    Matcher loansMatch = loans.matcher(loansHtml);

                    if (loansMatch.matches()) {
                        // System.out.println("Matches");
                        // System.out.println(loansMatch.groupCount());

                        // for (int i=0; i < loansMatch.groupCount(); i++) {
                        // Add to String Buffer
                        // System.out.println(loansMatch.group(7));
                        // }
                        String loansTable = loansMatch.group(7).toString();
                        // loansTable = loansTable.replaceAll("\n\n","");

                        Pattern loansTwo = Pattern.compile(
                                "^(.*?)<tr(.*?)class=\"patFuncEntry\">(?s)(.*?)</tr>(?s)(.*?)$",
                                Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);

                        Matcher loansTwoMatch = loansTwo.matcher(loansTable);

                        // initialize variables
                        StringBuffer sb = new StringBuffer();
                        String lineMatch;
                        String strCleanup;

                        /*
                         * Pattern loansThree = Pattern.compile(
                         * "^(.*?)value=\"(.*?)\"(.*?)$",
                         * Pattern.CASE_INSENSITIVE);
                         */

                        // loop over each iteration
                        while (loansTwoMatch.find()) {

                            // Replacements to get pipe delmited output
                            lineMatch = loansTwoMatch.group(3).replaceAll("\n", "");

                            lineMatch = lineMatch.replaceAll(
                                    "<td align=\"left\" class=\"patFuncMark\"><input type=\"checkbox\" name=\"renew(.*?)\" value=\"",
                                    "");
                            lineMatch = lineMatch.replaceAll("\"(.*?)href=\"(.*?)&", "'|'");
                            lineMatch = lineMatch.replaceAll("</a>(.*?)Barcode\">", "'|'");
                            lineMatch = lineMatch.replaceAll("</td>(.*?)patFuncStatus\">", "'|'");
                            lineMatch = lineMatch.replaceAll("</td>(.*?)patFuncCallNo\">", "'|'");
                            lineMatch = lineMatch.replaceAll("\"> ", "'|'");
                            lineMatch = lineMatch.replaceAll(" </td>", "");

                            // Append Pipe delimited to string buffer
                            sb.append(lineMatch + "\n");

                        }
                        // Convert to string for output
                        strCleanup = sb.toString();

                        String aryTest[] = stringToArray(strCleanup, "\n");

                        // System.out.println(aryTest[1]);

                        // Loop Over Loans
                        for (int i = 0; i < aryTest.length; i++) {

                            // Split up, and turn into array / assign to object
                            String aryVal[] = aryTest[i].split("'|'");

                            /*
                             * This is all we can get, itemid, bib, title,
                             * barcode duedate and call number
                             * System.out.println("--" + i);
                             * System.out.print("| item: " + aryVal[0] +
                             * "| bib: b" + aryVal[2] + "| title " + aryVal[4] +
                             * "| barcode: " + aryVal[6] + "| due: " + aryVal[8]
                             * + "| CN: " + aryVal[10]);
                             * 
                             * System.out.println("--");
                             */

                            // set variables for loaned object
                            String strAgencyId = strConfig.getProperty("defaultAgency");/*
                                                                                        * configuration
                                                                                        * .getProperty(
                                                                                        * Constants.
                                                                                        * CONFIG_ILS_DEFAULT_AGENCY
                                                                                        * );
                                                                                        */

                            // Start Date Format
                            Date dateDue = null; // set to null
                            DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT); // create
                            // formatter

                            String strDate = aryVal[8].replaceAll("DUE ", "").replace("-", "/"); // format string

                            // System.out.println(strDate); // for testing

                            // parse the date
                            try {
                                dateDue = dateFormatter.parse(strDate);
                            } catch (ParseException pe) {
                                System.out.println("LookupUser ERROR: Cannot parse \"" + strDate + "\"");
                            }

                            // add b to the value for the bib
                            String bibId = "b" + aryVal[2];

                            // Create a new item for each loaned item
                            /*
                             * NCIPUserLoanedItem item = new NCIPUserLoanedItem(
                             * dateDue, new NCIPItem(new NCIPAgency(
                             * strAgencyId), bibId));
                             */
                            // add object to returnUser
                            // returnUser.addLoanedItem(item);

                            System.out.println(
                                    "Added the user's loaned item with item ID " + bibId + " Due: " + dateDue);

                        }

                    } // end matches

                    // Error handling
                } catch (HttpException e) {
                    e.printStackTrace();
                    /*
                     * throw new ILSException("HttpException thrown, exiting.",
                     * Constants.ERROR_INTERNAL_ERROR, new StrictNcipError(true,
                     * "NCIP General Processing Error",
                     * "Temporary Processing Failure", "NCIPMessage", null));
                     */
                } catch (IOException e) {
                    e.printStackTrace();
                    /*
                     * throw new ILSException("IOException thrown, exiting.",
                     * Constants.ERROR_INTERNAL_ERROR, new StrictNcipError(true,
                     * "NCIP General Processing Error",
                     * "Temporary Processing Failure", "NCIPMessage", null));
                     */
                }

            }

            // TODO xcLookupUser: Finish Recalls
            // If getRecalls is true, the returned users list of recalls must
            // contain XCUserRecalledItem Objects for all recalls the user
            // represented by the userId field has placed.
            if (getRecalls) {
                System.out.println("Todo: get Recalls");
            }

            // TODO xcLookupUser: Finish getMessages
            // If getMessages is true, the returned users list of messages must
            // contain all messages applying the user represented by the userId.
            if (getMessages) {
                System.out.println("Todo: get Messages");
            }

            // return returnUser;

        } catch (HttpException e) {
            e.printStackTrace();
            /*
             * throw new ILSException( "HttpException thrown, exiting.",
             * Constants.ERROR_INTERNAL_ERROR, new StrictNcipError(true,
             * "NCIP General Processing Error", "Temporary Processing Failure",
             * "NCIPMessage", null));
             */
        } catch (IOException e) {
            e.printStackTrace();
            /*
             * throw new ILSException( "IOException thrown, exiting.",
             * Constants.ERROR_INTERNAL_ERROR, new StrictNcipError(true,
             * "NCIP General Processing Error", "Temporary Processing Failure",
             * "NCIPMessage", null));
             */
        }

        user.setUserIdentifierValue(userId);
        responseData.setUserId(user);
        // Echo back the same item id that came in
        // responseData.setUserId(initData.getUserId());
        return responseData;
    }

    /***
     * Converts a delimited string into an array of string tokens.
     * 
     * @param String
     *            [] The 'separator' separated string.
     * @param String
     *            The string separator.
     * @return String A string array of the original tokens.
     */
    public static final String[] stringToArray(String str, String separators) {
        StringTokenizer tokenizer;
        String[] array = null;
        int count = 0;

        if (str == null)
            return array;

        if (separators == null)
            separators = ",";

        tokenizer = new StringTokenizer(str, separators);
        if ((count = tokenizer.countTokens()) <= 0) {
            return array;
        }

        array = new String[count];

        int ix = 0;
        while (tokenizer.hasMoreTokens()) {
            array[ix] = tokenizer.nextToken();
            ix++;
        }

        return array;
    }
}