oscar.oscarRx.util.RxUtil.java Source code

Java tutorial

Introduction

Here is the source code for oscar.oscarRx.util.RxUtil.java

Source

/**
 * Copyright (c) 2001-2002. Department of Family Medicine, McMaster University. All Rights Reserved.
 * This software is published under the GPL GNU General Public License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version. 
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * This software was written for the
 * Department of Family Medicine
 * McMaster University
 * Hamilton
 * Ontario, Canada
 */

package oscar.oscarRx.util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcClientLite;
import org.oscarehr.common.dao.UserPropertyDAO;
import org.oscarehr.common.model.UserProperty;
import org.oscarehr.util.DbConnectionFilter;
import org.oscarehr.util.MiscUtils;

import oscar.OscarProperties;
import oscar.oscarDB.DBHandler;
import oscar.oscarRx.data.RxCodesData;
import oscar.oscarRx.data.RxPrescriptionData;
import oscar.oscarRx.pageUtil.RxMyDrugrefInfoAction;
import oscar.oscarRx.pageUtil.RxSessionBean;
import oscar.oscarRx.util.TimingOutCallback.TimeoutException;

public class RxUtil {

    private static String defaultPattern = "yyyy/MM/dd";
    private static Locale locale = Locale.CANADA;
    private static String defaultQuantity = "30";
    private static final Logger logger = MiscUtils.getLogger();
    private static String[] zeroToTen = { "(?i)zero", "(?i)one", "(?i)two", "(?i)three", "(?i)four", "(?i)five",
            "(?i)six", "(?i)seven", "(?i)eight", "(?i)nine", "(?i)ten" };

    public static void setDefaultQuantity(String quantity) {
        defaultQuantity = quantity;
    }

    public static String getDefaultQuantity() {
        return defaultQuantity;
    }

    public static Date StringToDate(String Expression) {
        return StringToDate(Expression, defaultPattern);
    }

    public static Date StringToDate(String Expression, String pattern) {
        try {
            SimpleDateFormat df = new SimpleDateFormat(pattern, locale);

            return df.parse(Expression);
        } catch (Exception e) {
            return null;
        }
    }

    public static String DateToString(Date Expression) {
        return DateToString(Expression, defaultPattern);
    }

    public static String DateToString(Calendar Expression) {
        if (Expression == null)
            return DateToString(null, defaultPattern);
        return DateToString(Expression.getTime(), defaultPattern);
    }

    public static String DateToString(Date Expression, String pattern) {
        if (Expression != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern, locale);

            return df.format(Expression);
        } else {
            return "";
        }
    }

    public static String DateToString(Date Expression, String pattern, Locale locale2) {
        if (Expression != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern, locale2);

            return df.format(Expression);
        } else {
            return "";
        }
    }

    public static Date Today() {
        return (java.util.GregorianCalendar.getInstance().getTime());
    }

    public static int BoolToInt(boolean Expression) {
        if (Expression == true) {
            return 1;
        } else {
            return 0;
        }
    }

    public static boolean IntToBool(int Expression) {
        return (Expression != 0);
    }

    public static String FloatToString(float value) {
        Float f = new Float(value);

        java.text.NumberFormat fmt = java.text.NumberFormat.getNumberInstance();

        String s = fmt.format(f.doubleValue());

        return s;
    }

    public static float StringToFloat(String value) {
        return Float.parseFloat(value);
    }

    public static Object IIf(boolean Expression, Object TruePart, Object FalsePart) {
        if (Expression == true) {
            return TruePart;
        } else {
            return FalsePart;
        }
    }

    public static String joinArray(Object[] array) {
        String ret = "";
        int i;
        for (i = 0; i < array.length; i++) {
            ret += "'" + String.valueOf(array[i]) + "'";
            if (i < array.length - 1) {
                ret += ", ";
            }
        }

        return ret;
    }

    public static String replace(String expression, String searchFor, String replaceWith) {
        if (expression != null) {
            StringBuilder buf = new StringBuilder(expression);

            int pos = -1;

            while (true) {
                pos = buf.indexOf(searchFor, pos);

                if (pos > -1) {
                    buf.delete(pos, pos + searchFor.length());
                    buf.insert(pos, replaceWith);

                    pos += replaceWith.length();
                } else {
                    break;
                }
            }

            return buf.toString();
        } else {
            return null;
        }
    }

    /**
     * Method for calculating creatinine clearance takes age, weight in kg and CREATININE values an returns Clcr
     * age must be greater than zero.
     * weight must be greater than zero
     */
    public static int getClcr(int age, double weight, double sCr, boolean female) throws Exception {
        if (age < 0) {
            throw new Exception("age must be greater than 0");
        }
        if (weight < 0) {
            throw new Exception("weight must be greater than 0");
        }
        if (sCr < 0) {
            throw new Exception("sCr must be greater than 0");
        }

        double Clcr = (140 - age) * weight / (sCr * 0.8);
        if (female) {
            Clcr = Clcr * 0.85;
        }

        return (int) Math.round(Clcr);
    }

    public static double findNDays(String durationUnit) {
        double nDays = 0d;
        if (durationUnit.equalsIgnoreCase("D")) {
            nDays = 1;
        } else if (durationUnit.equalsIgnoreCase("W")) {
            nDays = 7;
        } else if (durationUnit.equalsIgnoreCase("M")) {
            nDays = 30;
        }
        return nDays;
    }

    public static Double findNPerDay(String frequency) {
        double nPerDay = 0d;
        if (frequency.equalsIgnoreCase("od")) {
            nPerDay = 1;
        } else if (frequency.equalsIgnoreCase("bid")) {
            nPerDay = 2;
        } else if (frequency.equalsIgnoreCase("tid")) {
            nPerDay = 3;
        } else if (frequency.equalsIgnoreCase("qid")) {
            nPerDay = 4;
        } else if (frequency.equalsIgnoreCase("Q1H")) {
            nPerDay = 24;
        } else if (frequency.equalsIgnoreCase("Q2H")) {
            nPerDay = 12;
        } else if (frequency.equalsIgnoreCase("Q1-2H")) {
            nPerDay = 24;
        } else if (frequency.equalsIgnoreCase("Q3-4H")) {
            nPerDay = 8;
        } else if (frequency.equalsIgnoreCase("Q4H")) {
            nPerDay = 6;
        } else if (frequency.equalsIgnoreCase("Q4-6H")) {
            nPerDay = 6;
        } else if (frequency.equalsIgnoreCase("Q6H")) {
            nPerDay = 4;
        } else if (frequency.equalsIgnoreCase("Q8H")) {
            nPerDay = 3;
        } else if (frequency.equalsIgnoreCase("Q12H")) {
            nPerDay = 2;
        } else if (frequency.equalsIgnoreCase("QAM")) {
            nPerDay = 1;
        } else if (frequency.equalsIgnoreCase("QPM")) {
            nPerDay = 1;
        } else if (frequency.equalsIgnoreCase("QHS")) {
            nPerDay = 1;
        } else if (frequency.equalsIgnoreCase("Q1Week")) {
            nPerDay = 0.14285714285714285;
        } else if (frequency.equalsIgnoreCase("Q2Week")) {
            nPerDay = 0.07142857142857142;
        } else if (frequency.equalsIgnoreCase("Q1Month")) {
            nPerDay = 0.03333333333333333;
        } else if (frequency.equalsIgnoreCase("Q3Month")) {
            nPerDay = 0.011111111111111112;
        }
        return nPerDay;
    }

    public static String getUnitNameFromQuantityText(String qStr) {
        if (qStr != null) {
            Pattern p1 = Pattern.compile("\\d+");
            Matcher m1 = p1.matcher(qStr);
            if (m1.find()) {
                String qNum = qStr.substring(m1.start(), m1.end());
                //get the quantity unit
                String qUnit = qStr.replace(qNum, "").trim();
                if (qUnit != null && qUnit.length() > 0) {
                    return qUnit;
                }
            }
        }
        return null;
    }

    public static String getQuantityFromQuantityText(String qStr) {
        if (qStr != null) {
            Pattern p1 = Pattern.compile("\\d+");
            Matcher m1 = p1.matcher(qStr);
            if (m1.find()) {
                String qNum = qStr.substring(m1.start(), m1.end());
                return qNum;
            }
        }
        return null;
    }

    public static boolean isMitte(String qStr) {
        boolean isMitte = false;
        String[] durationUnits = { "[0-9]+\\s+(?i)days\\s", "[0-9]+\\s+(?i)weeks\\s", "[0-9]+\\s+(?i)months\\s",
                "[0-9]+\\s+(?i)day\\s", "[0-9]+\\s+(?i)week\\s", "[0-9]+\\s+(?i)month\\s", "[0-9]+\\s+(?i)d\\s",
                "[0-9]+\\s+(?i)w\\s", "[0-9]+\\s+(?i)m\\s", "[0-9]+\\s+(?i)mo\\s", "[0-9]+\\s+(?i)days$",
                "[0-9]+\\s+(?i)weeks$", "[0-9]+\\s+(?i)months$", "[0-9]+\\s+(?i)day$", "[0-9]+\\s+(?i)week$",
                "[0-9]+\\s+(?i)month$", "[0-9]+\\s+(?i)d$", "[0-9]+\\s+(?i)w$", "[0-9]+\\s+(?i)m$",
                "[0-9]+\\s+(?i)mo$", "\\s[0-9]+(?i)days\\s", "\\s[0-9]+(?i)weeks\\s", "\\s[0-9]+(?i)months\\s",
                "\\s[0-9]+(?i)day\\s", "\\s[0-9]+(?i)week\\s", "\\s[0-9]+(?i)month\\s", "\\s[0-9]+(?i)d\\s",
                "\\s[0-9]+(?i)w\\s", "\\s[0-9]+(?i)m\\s", "\\s[0-9]+(?i)mo\\s", "\\s[0-9]+(?i)days$",
                "\\s[0-9]+(?i)weeks$", "\\s[0-9]+(?i)months$", "\\s[0-9]+(?i)day$", "\\s[0-9]+(?i)week$",
                "\\s[0-9]+(?i)month$", "\\s[0-9]+(?i)d$", "\\s[0-9]+(?i)w$", "\\s[0-9]+(?i)m$", "\\s[0-9]+(?i)mo$",
                "^[0-9]+(?i)days$", "^[0-9]+(?i)weeks$", "^[0-9]+(?i)months$", "^[0-9]+(?i)day$",
                "^[0-9]+(?i)week$", "^[0-9]+(?i)month$", "^[0-9]+(?i)d$", "^[0-9]+(?i)w$", "^[0-9]+(?i)m$",
                "^[0-9]+(?i)mo$", "^[0-9]+\\s+(?i)days$", "^[0-9]+\\s+(?i)weeks$", "^[0-9]+\\s+(?i)months$",
                "^[0-9]+\\s+(?i)day$", "^[0-9]+\\s+(?i)week$", "^[0-9]+\\s+(?i)month$", "^[0-9]+\\s+(?i)d$",
                "^[0-9]+\\s+(?i)w$", "^[0-9]+\\s+(?i)m$", "^[0-9]+\\s+(?i)mo$" };
        for (String s : durationUnits) {
            Pattern p = Pattern.compile(s);
            Matcher m = p.matcher(qStr);
            if (m.find()) {
                String foundStr = (qStr.substring(m.start(), m.end())).trim();
                qStr = qStr.replace(foundStr, "");
                qStr = qStr.trim();
                if (qStr.length() == 0) {
                    isMitte = true;
                    break;
                }
            }
        }
        return isMitte;
    }

    public static String getDurationFromQuantityText(String qStr) {
        String retStr = "";
        String[] durationUnits = { "[0-9]+\\s+(?i)days\\s", "[0-9]+\\s+(?i)weeks\\s", "[0-9]+\\s+(?i)months\\s",
                "[0-9]+\\s+(?i)day\\s", "[0-9]+\\s+(?i)week\\s", "[0-9]+\\s+(?i)month\\s", "[0-9]+\\s+(?i)d\\s",
                "[0-9]+\\s+(?i)w\\s", "[0-9]+\\s+(?i)m\\s", "[0-9]+\\s+(?i)mo\\s", "[0-9]+\\s+(?i)days$",
                "[0-9]+\\s+(?i)weeks$", "[0-9]+\\s+(?i)months$", "[0-9]+\\s+(?i)day$", "[0-9]+\\s+(?i)week$",
                "[0-9]+\\s+(?i)month$", "[0-9]+\\s+(?i)d$", "[0-9]+\\s+(?i)w$", "[0-9]+\\s+(?i)m$",
                "[0-9]+\\s+(?i)mo$", "\\s[0-9]+(?i)days\\s", "\\s[0-9]+(?i)weeks\\s", "\\s[0-9]+(?i)months\\s",
                "\\s[0-9]+(?i)day\\s", "\\s[0-9]+(?i)week\\s", "\\s[0-9]+(?i)month\\s", "\\s[0-9]+(?i)d\\s",
                "\\s[0-9]+(?i)w\\s", "\\s[0-9]+(?i)m\\s", "\\s[0-9]+(?i)mo\\s", "\\s[0-9]+(?i)days$",
                "\\s[0-9]+(?i)weeks$", "\\s[0-9]+(?i)months$", "\\s[0-9]+(?i)day$", "\\s[0-9]+(?i)week$",
                "\\s[0-9]+(?i)month$", "\\s[0-9]+(?i)d$", "\\s[0-9]+(?i)w$", "\\s[0-9]+(?i)m$",
                "\\s[0-9]+(?i)mo$", };
        for (String s : durationUnits) {
            Pattern p = Pattern.compile(s);
            Matcher m = p.matcher(qStr);
            if (m.find()) {
                String foundStr = (qStr.substring(m.start(), m.end())).trim();
                Pattern p2 = Pattern.compile("[0-9]+");
                Matcher m2 = p2.matcher(foundStr);
                if (m2.find()) {
                    String duration = (foundStr.substring(m2.start(), m2.end())).trim();
                    retStr = duration;
                }
                break;
            }
        }
        return retStr;
    }

    public static String getDurationUnitFromQuantityText(String qStr) {
        String retStr = "";
        String[] durationUnits = { "[0-9]+\\s+(?i)days\\s", "[0-9]+\\s+(?i)weeks\\s", "[0-9]+\\s+(?i)months\\s",
                "[0-9]+\\s+(?i)day\\s", "[0-9]+\\s+(?i)week\\s", "[0-9]+\\s+(?i)month\\s", "[0-9]+\\s+(?i)d\\s",
                "[0-9]+\\s+(?i)w\\s", "[0-9]+\\s+(?i)m\\s", "[0-9]+\\s+(?i)mo\\s", "[0-9]+\\s+(?i)days$",
                "[0-9]+\\s+(?i)weeks$", "[0-9]+\\s+(?i)months$", "[0-9]+\\s+(?i)day$", "[0-9]+\\s+(?i)week$",
                "[0-9]+\\s+(?i)month$", "[0-9]+\\s+(?i)d$", "[0-9]+\\s+(?i)w$", "[0-9]+\\s+(?i)m$",
                "[0-9]+\\s+(?i)mo$", "\\s[0-9]+(?i)days\\s", "\\s[0-9]+(?i)weeks\\s", "\\s[0-9]+(?i)months\\s",
                "\\s[0-9]+(?i)day\\s", "\\s[0-9]+(?i)week\\s", "\\s[0-9]+(?i)month\\s", "\\s[0-9]+(?i)d\\s",
                "\\s[0-9]+(?i)w\\s", "\\s[0-9]+(?i)m\\s", "\\s[0-9]+(?i)mo\\s", "\\s[0-9]+(?i)days$",
                "\\s[0-9]+(?i)weeks$", "\\s[0-9]+(?i)months$", "\\s[0-9]+(?i)day$", "\\s[0-9]+(?i)week$",
                "\\s[0-9]+(?i)month$", "\\s[0-9]+(?i)d$", "\\s[0-9]+(?i)w$", "\\s[0-9]+(?i)m$",
                "\\s[0-9]+(?i)mo$", };
        for (String s : durationUnits) {
            Pattern p = Pattern.compile(s);
            Matcher m = p.matcher(qStr);
            if (m.find()) {
                String foundStr = (qStr.substring(m.start(), m.end())).trim();
                Pattern p2 = Pattern.compile("[0-9]+");
                Matcher m2 = p2.matcher(foundStr);
                if (m2.find()) {
                    String duration = (foundStr.substring(m2.start(), m2.end())).trim();
                    String durationUnit = foundStr.replace(duration, "").trim();
                    if (durationUnit.startsWith("d") || durationUnit.startsWith("D"))
                        retStr = "D";
                    else if (durationUnit.startsWith("w") || durationUnit.startsWith("W"))
                        retStr = "W";
                    else if (durationUnit.startsWith("m") || durationUnit.startsWith("M"))
                        retStr = "M";
                    else
                        retStr = "";
                    break;
                }
            }
        }
        return retStr;
    }

    public static String findDuration(RxPrescriptionData.Prescription rx) {//calculate duration based on quantity, takemax,takemin,frequency,durationUnit.
        //get frequency,takemax,takemin,durationUnit by parsing special.
        instrucParser(rx);
        MiscUtils.getLogger().debug("after  instrucParser,quantity=" + rx.getQuantity());
        String qStr = rx.getQuantity();
        if (rx.getUnitName() == null) {
            qStr = qStr.trim();
            double qtyD;
            Pattern p1 = Pattern.compile("\\d+");
            Matcher m1 = p1.matcher(qStr);
            if (m1.find()) {
                String qNum = qStr.substring(m1.start(), m1.end());
                qtyD = Double.parseDouble(qNum);
                //get the quantity unit
                String qUnit = qStr.replace(qNum, "").trim();
                if (qUnit != null && qUnit.length() > 0) {
                    rx.setUnitName(qUnit);
                    return null; //if a quantity unit is specified, can't calculate duration.
                } else {
                    double takeMax = rx.getTakeMax();
                    double nPerDay = findNPerDay(rx.getFrequencyCode());
                    double nDays = findNDays(rx.getDurationUnit());
                    p("qtyD--takeMax--nPerDay--nDays--" + qtyD + " " + takeMax + " " + nPerDay + " " + nDays);
                    if (takeMax != 0d) {
                        double durD = qtyD / (takeMax) * nPerDay * nDays;
                        int durInt = (int) durD;
                        p("durInt", Integer.toString(durInt));
                        return Integer.toString(durInt);
                    } else {
                        return null;
                    }
                }
            } else {
                logger.error("quantity is not specified");
                return null;
            }
        } else {
            return null;
        }
    }

    private static void setEmptyValues(RxPrescriptionData.Prescription rx) {
        rx.setRoute("");
        rx.setTakeMax(Float.parseFloat("0"));
        rx.setTakeMin(Float.parseFloat("0"));
        rx.setMethod("");
        rx.setFrequencyCode("");
        rx.setDuration("0");
        rx.setDurationUnit("");
        rx.setPrn(false);
        rx.setQuantity(Integer.toString(0));
        rx.setSpecial("");
    }

    private static String changeToStandardFrequencyCode(String str) {
        String retVal = str;
        if (str.equalsIgnoreCase("daily")) {
            retVal = "OD";
        } else if (str.equalsIgnoreCase("once daily")) {
            retVal = "OD";
        } else if (str.equalsIgnoreCase("twice daily")) {
            retVal = "BID";
        } else if (str.equalsIgnoreCase("3x day")) {
            retVal = "TID";
        } else if (str.equalsIgnoreCase("3x daily")) {
            retVal = "TID";
        } else if (str.equalsIgnoreCase("4x day")) {
            retVal = "QID";
        } else if (str.equalsIgnoreCase("4x daily")) {
            retVal = "QID";
        } else if (str.equalsIgnoreCase("weekly")) {
            retVal = "Q1Week";
        } else if (str.equalsIgnoreCase("monthly")) {
            retVal = "Q1Month";
        }
        return retVal;
    }

    private static String convertWordToNumerical(String s) {

        s = s.trim();
        String retVal = s;
        if (s != null && !s.equalsIgnoreCase("null")) {
            if (s.equalsIgnoreCase("zero")) {
                retVal = "0";
            } else if (s.equalsIgnoreCase("one")) {
                retVal = "1";
            } else if (s.equalsIgnoreCase("two")) {
                retVal = "2";
            } else if (s.equalsIgnoreCase("three")) {
                retVal = "3";
            } else if (s.equalsIgnoreCase("four")) {
                retVal = "4";
            } else if (s.equalsIgnoreCase("five")) {
                retVal = "5";
            } else if (s.equalsIgnoreCase("six")) {
                retVal = "6";
            } else if (s.equalsIgnoreCase("seven")) {
                retVal = "7";
            } else if (s.equalsIgnoreCase("eight")) {
                retVal = "8";
            } else if (s.equalsIgnoreCase("nine")) {
                retVal = "9";
            } else if (s.equalsIgnoreCase("ten")) {
                retVal = "10";
            } else {
                if (!isStringToNumber(retVal))
                    retVal = "0";
            }
        } else
            retVal = "0";

        return retVal;
    }

    private static String checkInstructionStr(String str) {//replace if instruction contains certain string which may confuse the text parser
        String retVal = str;
        if (str.contains("3x day")) {
            retVal = retVal.replace("3x day", "");
        } else if (str.contains("4x day")) {
            retVal = retVal.replace("4x day", "");
        }
        return retVal;
    }

    public static void instrucParser(RxPrescriptionData.Prescription rx) {
        if (rx == null) {
            return;
        }
        String instructions = rx.getSpecial();
        if (instructions == null) {
            instructions = "";
        }
        String route = "";
        String frequency = "";
        String duration = "0";
        String method = "";
        String durationUnit = "";
        String durationUnitSpec = "";
        boolean prn = false;
        String amountFrequency = "";
        String amountMethod = "";
        String takeMinFrequency = "";
        String takeMaxFrequency = "";
        String takeMinMethod = "";
        String takeMaxMethod = "";
        String takeMin = "0";
        String takeMax = "0";
        String durationSpec = "";
        int quantity = 0;
        List<String> policyViolations = new ArrayList<String>();

        if (instructions.trim().length() == 0) {
            setEmptyValues(rx);
        } else {
            //do we have some policies/restrictions we want to run?
            policyViolations.addAll(RxInstructionPolicy.checkInstructions(instructions.trim()));

            String[] prns = { "\\s(?i)prn$", "^(?i)prn\\s+", "\\s+(?i)prn\\s+" };
            for (String s : prns) {
                Pattern prnP = Pattern.compile(s);
                Matcher prnM = prnP.matcher(instructions);
                if (prnM.find()) {
                    //            p("prn is true");
                    prn = true;
                }
            }

            String[] routes = { "\\s(?i)PO$", "\\s(?i)SL$", "\\s(?i)IM$", "\\s(?i)SC$", "\\s(?i)PATCH$",
                    "\\s(?i)TOP\\.$", "\\s(?i)INH$", "\\s(?i)SUPP$", "\\s(?i)O.D.$", "\\s(?i)O.S.$", "\\s(?i)O.U.$",
                    "\\s(?i)OD$", "\\s(?i)OS$", "\\s(?i)OU$", "\\s(?i)PO\\s", "\\s(?i)SL\\s", "\\s(?i)IM\\s",
                    "\\s(?i)SC\\s", "\\s(?i)PATCH\\s", "\\s(?i)TOP\\.\\s", "\\s(?i)INH\\s", "\\s(?i)SUPP\\s",
                    "\\s(?i)O.D.\\s", "\\s(?i)O.S.\\s", "\\s(?i)O.U.\\s", "\\s(?i)OD\\s", "\\s(?i)OS\\s",
                    "\\s(?i)OU\\s" };
            String[] frequences = { "\\s(?i)OD\\s", "\\s(?i)BID\\s", "\\s(?i)TID\\s", "\\s(?i)QID\\s",
                    "\\s(?i)Q1H\\s", "\\s(?i)Q2H\\s", "\\s(?i)Q1-2H\\s", "\\s(?i)Q3-4H\\s", "\\s(?i)Q4H\\s",
                    "\\s(?i)Q4-6H\\s", "\\s(?i)Q6H\\s", "\\s(?i)Q8H\\s", "\\s(?i)Q12H\\s", "\\s(?i)QAM\\s",
                    "\\s(?i)QPM\\s", "\\s(?i)QHS\\s", "\\s(?i)Q1Week\\s", "\\s(?i)weekly\\s", "\\s(?i)Q2Week\\s",
                    "\\s(?i)Q1Month\\s", "\\s(?i)Q3Month\\s", "\\s(?i)monthly\\s", "\\s(?i)once daily\\s",
                    "\\s(?i)twice daily\\s", "\\s(?i)3x day\\s", "\\s(?i)4x day\\s", "\\s(?i)3x daily\\s",
                    "\\s(?i)4x daily\\s", "\\s(?i)OD$", "\\s(?i)BID$", "\\s(?i)TID$", "\\s(?i)QID$", "\\s(?i)Q1H$",
                    "\\s(?i)Q2H$", "\\s(?i)Q1-2H$", "\\s(?i)Q3-4H$", "\\s(?i)Q4H$", "\\s(?i)Q4-6H$", "\\s(?i)Q6H$",
                    "\\s(?i)Q8H$", "\\s(?i)Q12H$", "\\s(?i)QAM$", "\\s(?i)QPM$", "\\s(?i)QHS$", "\\s(?i)Q1Week$",
                    "\\s(?i)weekly$", "\\s(?i)Q2Week$", "\\s(?i)Q1Month$", "\\s(?i)Q3Month$", "\\s(?i)monthly$",
                    "\\s(?i)once daily$", "\\s(?i)twice daily$", "\\s(?i)3x day$", "\\s(?i)4x day$",
                    "\\s(?i)3x daily$", "\\s(?i)4x daily$", "\\s(?i)daily\\s", "\\s(?i)daily$",// put at last because if frequency is 'twice daily', it will first be detected as 'daily'
            };
            String[] methods = { "(?i)Take", "(?i)Apply", "(?i)Rub well in" };
            String[] durationUnits = { "\\s+(?i)days\\s", "\\s+(?i)weeks\\s", "\\s+(?i)months\\s", "\\s+(?i)day\\s",
                    "\\s+(?i)week\\s", "\\s+(?i)month\\s", "\\s+(?i)d\\s", "\\s+(?i)w\\s", "\\s+(?i)m\\s",
                    "\\s+(?i)mo\\s", "\\s+(?i)days$", "\\s+(?i)weeks$", "\\s+(?i)months$", "\\s+(?i)day$",
                    "\\s+(?i)week$", "\\s+(?i)month$", "\\s+(?i)d$", "\\s+(?i)w$", "\\s+(?i)m$", "\\s+(?i)mo$" };
            String[] durUnits2 = { "\\s[0-9]+(?i)days\\s", "\\s[0-9]+(?i)weeks\\s", "\\s[0-9]+(?i)months\\s",
                    "\\s[0-9]+(?i)day\\s", "\\s[0-9]+(?i)week\\s", "\\s[0-9]+(?i)month\\s", "\\s[0-9]+(?i)d\\s",
                    "\\s[0-9]+(?i)w\\s", "\\s[0-9]+(?i)m\\s", "\\s[0-9]+(?i)mo\\s", "\\s[0-9]+(?i)days$",
                    "\\s[0-9]+(?i)weeks$", "\\s[0-9]+(?i)months$", "\\s[0-9]+(?i)day$", "\\s[0-9]+(?i)week$",
                    "\\s[0-9]+(?i)month$", "\\s[0-9]+(?i)d$", "\\s[0-9]+(?i)w$", "\\s[0-9]+(?i)m$",
                    "\\s[0-9]+(?i)mo$", };

            for (String s : routes) {
                Pattern p = Pattern.compile(s);
                Matcher matcher = p.matcher(instructions);
                if (matcher.find()) {
                    route = (instructions.substring(matcher.start(), matcher.end())).trim();
                    if (route.equalsIgnoreCase("OD")) {
                        p("route is OD");

                        //remove OD from instructions
                        String part = instructions.substring(0, matcher.start()) + " "
                                + instructions.substring(matcher.end());
                        //if route =od,check if there is a valid frequency, there is one, then route is od.
                        //if not , set the route="",keep looping. then set frequency to be od;
                        p("part is " + part);
                        Pattern fPattern = Pattern.compile("\\s(?i)OD\\s*");
                        Matcher fMatcher = fPattern.matcher(part);
                        String frequencyStr = "";
                        if (fMatcher.find()) {
                            frequencyStr = part.substring(fMatcher.start(), fMatcher.end());
                            break;
                        }
                        if (frequencyStr.equals("")) {
                            frequency = "OD";
                            route = "";
                            continue;
                        } else {
                            frequency = frequencyStr;
                            break;
                        }
                    } else {
                        break;
                    }

                }
            }

            p("route", route);
            if (route.equals("")) {
                MiscUtils.getLogger().debug("route is not set");
            }

            //find frequency
            for (String s : frequences) {
                Pattern p = Pattern.compile(s);
                Matcher matcher = p.matcher(instructions);
                if (matcher.find()) {
                    frequency = (instructions.substring(matcher.start(), matcher.end())).trim();
                    frequency = changeToStandardFrequencyCode(frequency);
                    String origFrequency = (instructions.substring(matcher.start(), matcher.end())).trim();

                    Pattern p2 = Pattern.compile("\\s*\\d*\\.*\\d+\\s+" + origFrequency); //allow to detect decimal number.
                    Matcher m2 = p2.matcher(instructions);

                    Pattern p4 = Pattern.compile("\\s*\\d*\\.*\\d+-\\s*\\d*\\.*\\d+\\s+" + frequency); //use * after the first \s because "1 OD", 1 doesn't have a space in front.
                    Matcher m4 = p4.matcher(instructions);
                    //     p("here11", instructions);
                    //since "\\s+[0-9]+-[0-9]+\\s+" is a case in "\\s+[0-9]+\\s+", check the latter regex first.
                    if (m4.find()) {
                        String str2 = instructions.substring(m4.start(), m4.end());
                        Pattern p5 = Pattern.compile("\\d*\\.*\\d+-\\s*\\d*\\.*\\d+");
                        Matcher m5 = p5.matcher(str2);
                        if (m5.find()) {
                            String str3 = str2.substring(m5.start(), m5.end());
                            //       p("here str3", str3);
                            takeMinFrequency = str3.split("-")[0];
                            takeMaxFrequency = str3.split("-")[1];
                        }
                    } else if (m2.find()) {
                        String str = instructions.substring(m2.start(), m2.end());
                        Pattern p3 = Pattern.compile("\\d*\\.*\\d+");
                        Matcher m3 = p3.matcher(str);
                        //     p("here22", str);
                        if (m3.find()) {
                            amountFrequency = str.substring(m3.start(), m3.end());
                        }
                    } else {
                        p("word amount");
                        for (String word : zeroToTen) {
                            String r1 = "\\s" + word + "\\s*" + frequency;
                            String r2 = "^" + word + "\\s*" + frequency;//start at the begin of instructions
                            Pattern p5 = Pattern.compile(r1);
                            Matcher m5 = p5.matcher(instructions);
                            p("pattern word =" + r1);
                            if (m5.find()) {
                                amountFrequency = instructions.substring(m5.start(), m5.end());
                                amountFrequency = amountFrequency.replace(frequency, "").trim();
                                p("amountFreq=" + amountFrequency);
                                amountFrequency = convertWordToNumerical(amountFrequency);
                                p("num amountFreq=" + amountFrequency);
                                break;
                            }
                            p5 = Pattern.compile(r2);
                            m5 = p5.matcher(instructions);
                            if (m5.find()) {
                                amountFrequency = instructions.substring(m5.start(), m5.end());
                                amountFrequency = amountFrequency.replace(frequency, "").trim();
                                p("amountFreq=" + amountFrequency);
                                amountFrequency = convertWordToNumerical(amountFrequency);
                                p("num amountFreq=" + amountFrequency);
                                break;
                            }
                        }
                    }
                    //the string before frequency maybe the amount of drug
                    //check if the string is a number,if it is, get the number
                    //if not a number, check if it has "min-max" pattern, if yes, get min and max, if not, ignore

                    break;
                }
            }
            //check if method is specified, if yes, check the number after method ,which maybe the number to take for a frequency.
            for (String s : methods) {
                Pattern p = Pattern.compile(s);
                Matcher m = p.matcher(instructions);
                if (m.find()) {
                    p("must be here");
                    method = instructions.substring(m.start(), m.end());

                    Pattern p2 = Pattern.compile(method + "\\s*\\d*\\.*\\d+\\s+");
                    Matcher m2 = p2.matcher(instructions);

                    Pattern p4 = Pattern.compile(method + "\\s*\\d*\\.*\\d+-\\s*\\d*\\.*\\d+\\s+");
                    Matcher m4 = p4.matcher(instructions);
                    //since "\\s+[0-9]+-[0-9]+\\s+" is a case in "\\s+[0-9]+\\s+", check the latter regex first.
                    if (m4.find()) {
                        p("else if 1");
                        String str2 = instructions.substring(m4.start(), m4.end());
                        Pattern p5 = Pattern.compile("\\d*\\.*\\d+-\\s*\\d*\\.*\\d+");
                        Matcher m5 = p5.matcher(str2);
                        if (m5.find()) {
                            String str3 = str2.substring(m5.start(), m5.end());
                            //           p("str3", str3);
                            takeMinMethod = str3.split("-")[0];
                            takeMaxMethod = str3.split("-")[1];
                        }
                    } else if (m2.find()) {
                        p("if 1");
                        String str = instructions.substring(m2.start(), m2.end());
                        p("str1 ", str);
                        Pattern p3 = Pattern.compile("\\d*\\.*\\d+");
                        Matcher m3 = p3.matcher(str);
                        if (m3.find()) {
                            p("found1");
                            amountMethod = str.substring(m3.start(), m3.end());
                            //      p("amountMethod", amountMethod);
                        }
                    } else {
                        p("word amount");
                        for (String word : zeroToTen) {
                            String r1 = method + "\\s+" + word + "\\s";
                            String r2 = method + "\\s+" + word + "$";
                            Pattern p5 = Pattern.compile(r1);
                            Matcher m5 = p5.matcher(instructions);
                            p("pattern word =" + r1);
                            if (m5.find()) {
                                amountMethod = instructions.substring(m5.start(), m5.end());
                                amountMethod = amountMethod.replace(method, "").trim();
                                p("amountMethod=" + amountMethod);
                                amountMethod = convertWordToNumerical(amountMethod);
                                p("num amountMethod=" + amountMethod);
                                break;
                            } else {
                                p5 = Pattern.compile(r2);
                                m5 = p5.matcher(instructions);
                                p("pattern word =" + r2);
                                if (m5.find()) {
                                    amountMethod = instructions.substring(m5.start(), m5.end());
                                    amountMethod = amountMethod.replace(method, "").trim();
                                    p("amountMethod=" + amountMethod);
                                    amountMethod = convertWordToNumerical(amountMethod);
                                    p("num amountMethod=" + amountMethod);
                                    break;
                                }
                            }
                        }
                    }
                    break;
                }
            }
            /*    p(takeMinMethod);
            p(takeMaxMethod);
            p(takeMinFrequency);
            p(takeMaxFrequency);*/
            if (!takeMinMethod.equals("") && takeMinFrequency.equals("")) {

                takeMin = takeMinMethod;
                takeMax = takeMaxMethod;
            } else if (takeMinMethod.equals("") && !takeMinFrequency.equals("")) {
                takeMin = takeMinFrequency;
                takeMax = takeMaxFrequency;
            } else if (!takeMinMethod.equals("") && !takeMinFrequency.equals("")) {// when method and frequency both gives values of takemin and takemax,
                //assume use the frequency one is correct.
                takeMin = takeMinFrequency;
                takeMax = takeMaxFrequency;
            }
            //check if a frequency is specified, if yes, check the number before the freq, which is the number to have, check if the number match the previous.
            //if yes, use that as the quantity per frequency, if not, use the frequency number as quantity.
            if (!amountMethod.equals("") && amountFrequency.equals("")) {
                takeMin = amountMethod;
                takeMax = takeMin;
            } else if (amountMethod.equals("") && !amountFrequency.equals("")) {
                takeMin = amountFrequency;
                takeMax = takeMin;
            } else if (!amountMethod.equals("") && !amountFrequency.equals("")) { // when method and frequency both gives values of takemin and takemax,
                //assume use the frequency one is correct.
                takeMin = amountFrequency;
                takeMax = amountFrequency;
            }

            //calculate the number of pills to have per frequency which is used to calculate the duration later on.
            //from frequency code we can deduce a duration unit.
            //check if a durationunit is already specified, if not, use that, if yes,check if they are equal,if not output an warning and use specified.
            for (String s : durationUnits) {
                // p(instructions);
                // p(s);
                String instructionToCheck = checkInstructionStr(instructions);
                Pattern p = Pattern.compile(s);
                Matcher m = p.matcher(instructionToCheck);

                if (m.find()) {
                    p("FOUND");
                    p("instructionToCheck==", instructionToCheck);
                    p(s);
                    durationUnitSpec = (instructionToCheck.substring(m.start(), m.end())).trim();
                    p("durationUnitSpec", durationUnitSpec);
                    //get the number before durationUnit
                    Pattern p1 = Pattern.compile("[0-9]+" + s);
                    Matcher m1 = p1.matcher(instructionToCheck);
                    if (m1.find()) {
                        p("" + m1.start(), "" + m.start());
                        durationSpec = instructionToCheck.substring(m1.start(), m.start());
                        duration = durationSpec.trim();
                        p("duration here1", duration);
                    }
                    break;
                }
            }

            //match the pattern when there is no space between number and durationUnit.
            if (durationUnitSpec.equals("")) {
                MiscUtils.getLogger().debug("no space between duration and duration unit.");
                for (String s : durUnits2) {
                    String instructionToCheck = checkInstructionStr(instructions);
                    Pattern p = Pattern.compile(s);
                    Matcher m = p.matcher(instructionToCheck);

                    if (m.find()) {
                        p("FOUND");
                        p("instructionToCheck=" + instructionToCheck);
                        p(s);
                        String str1 = instructionToCheck.substring(m.start(), m.end());
                        MiscUtils.getLogger().debug("str1=" + str1);
                        //get numUnit out
                        Pattern p1 = Pattern.compile("[0-9]+");
                        Matcher m1 = p1.matcher(str1);
                        if (m1.find()) {
                            duration = str1.substring(m1.start(), m1.end());
                            durationUnitSpec = (str1.substring(m1.end())).trim();
                            MiscUtils.getLogger().debug("duration=" + duration);
                            MiscUtils.getLogger().debug("durationUnitSpec=" + durationUnitSpec);
                            break;
                        }
                    }
                }
            }

            //if durationUnit is not specified, deduce it
            if (durationUnitSpec.equals("")) {
                //    p("here?? if");
                String[] freq1 = { "\\s*(?i)OD\\s*", "\\s*(?i)BID\\s*", "\\s*(?i)TID\\s*", "\\s*(?i)QID\\s*",
                        "\\s*(?i)Q1H\\s*", "\\s*(?i)Q2H\\s*", "\\s*(?i)Q1-2H\\s*", "\\s*(?i)Q3-4H\\s*",
                        "\\s*(?i)Q4H\\s*", "\\s*(?i)Q4-6H\\s*", "\\s*(?i)Q6H\\s*", "\\s*(?i)Q8H\\s*",
                        "\\s*(?i)Q12H\\s*", "\\s*(?i)QAM\\s*", "\\s*(?i)QPM\\s*", "\\s*(?i)QHS\\s*",
                        "\\s*(?i)once daily\\s*", "\\s*(?i)twice daily\\s*", "\\s*(?i)3x day\\s*",
                        "\\s*(?i)4x day\\s*", "\\s*(?i)3x daily\\s*", "\\s*(?i)4x daily\\s*", "\\s*(?i)daily\\s*"// put at last because if frequency is 'twice daily', it will first be detected as 'daily'
                };//QPM is once a day in the evening, qhs once a day at night.
                String[] freq2 = { "\\s*(?i)Q1Week\\s*", "\\s*(?i)Q2Week\\s*" };
                String[] freq3 = { "\\s*(?i)Q1Month\\s*", "\\s*(?i)Q3Month\\s*" };
                boolean found = false;
                for (String f1 : freq1) {
                    Pattern p = Pattern.compile(f1);
                    Matcher m = p.matcher(frequency);
                    // p(f1);
                    // p(frequency);
                    if (m.find()) {

                        durationUnit = "D";
                        found = true;
                    }
                }

                if (!found) {
                    for (String f2 : freq2) {
                        Pattern p2 = Pattern.compile(f2);
                        Matcher m2 = p2.matcher(frequency);
                        if (m2.find()) {
                            durationUnit = "W";
                            found = true;
                        }
                    }
                }

                if (!found) {
                    for (String f3 : freq3) {
                        Pattern p3 = Pattern.compile(f3);
                        Matcher m3 = p3.matcher(frequency);
                        if (m3.find()) {
                            durationUnit = "M";
                            found = true;
                        }
                    }
                }
            } else {

                //D, W,M
                if (durationUnitSpec.equalsIgnoreCase("week") || durationUnitSpec.equalsIgnoreCase("weeks")
                        || durationUnitSpec.equalsIgnoreCase("w")) {

                    durationUnit = "W";
                } else if (durationUnitSpec.equalsIgnoreCase("day") || durationUnitSpec.equalsIgnoreCase("days")
                        || durationUnitSpec.equalsIgnoreCase("d")) {

                    durationUnit = "D";
                } else if (durationUnitSpec.equalsIgnoreCase("month") || durationUnitSpec.equalsIgnoreCase("months")
                        || durationUnitSpec.equalsIgnoreCase("m") || durationUnitSpec.equalsIgnoreCase("mo")) {

                    durationUnit = "M";
                }
            }

            //make sure min is smaller than max
            if (takeMax.compareTo(takeMin) < 0) {
                //      p("max<min");
                String swap = takeMin;
                takeMin = takeMax;
                takeMax = swap;
            }

            double nPerDay = 0d;//number of drugs per day
            double nDays = 0d;//number of days per duration unit

            MiscUtils.getLogger().debug("in instrucParser,unitName=" + rx.getUnitName());
            boolean isUnitNameUsed = true;
            if (rx.getUnitName() == null || rx.getUnitName().trim().length() == 0)
                isUnitNameUsed = false;
            else if (rx.getUnitName().equalsIgnoreCase("null"))
                isUnitNameUsed = false;
            else
                isUnitNameUsed = true;
            MiscUtils.getLogger().debug("isUnitNameUsed=" + isUnitNameUsed);
            //if duration is 0 or null or length==0,it means duration is not specified by user
            //if quantity,frequency, durationUnit are valid values,isUnitNameUsed==false
            //yes,calculate duration based on quantity because duration is not specified
            //no,leave duration an invalid value
            //else if duration is a valid value
            //if frequency, durationUnit,takeMax are valid too
            //yes, calculate quantity
            //no, leave quantity intact.
            //--start new code
            rx.setQuantity(rx.getQuantity().trim());
            if (duration.equals("0") || duration.length() == 0 || duration == null) {//if duration is not specified, find duration based on quantity
                rx.setDurationSpecifiedByUser(false);
                if (!isUnitNameUsed && rx.getQuantity() != null && !rx.getQuantity().equalsIgnoreCase("null")
                        && !rx.getQuantity().equals("") && !durationUnit.equals("") && !frequency.equals("")
                        && !takeMax.equals("0")) {
                    quantity = Integer.parseInt(rx.getQuantity());
                    double quantityD = quantity;
                    nPerDay = findNPerDay(frequency);
                    nDays = findNDays(durationUnit);
                    double durationD = quantityD / ((Double.parseDouble(takeMax)) * nPerDay * nDays);
                    Integer durationI = (int) durationD;
                    duration = durationI.toString();
                    rx.setDuration(duration);
                } else
                    rx.setDuration("0");
            } else {//if duration is valid, find quantity based on duration
                rx.setDurationSpecifiedByUser(true);
                rx.setDuration(duration);
                if (!isUnitNameUsed && !durationUnit.equals("") && !takeMin.equals("0") && !takeMax.equals("0")
                        && !frequency.equals("")) {
                    nPerDay = findNPerDay(frequency);
                    nDays = findNDays(durationUnit);
                    MiscUtils.getLogger().debug("in instrucParser duration=" + duration);
                    //quantity=takeMax * nDays * duration * nPerDay
                    double quantityD = (Double.parseDouble(takeMax)) * nPerDay * nDays
                            * (Double.parseDouble(duration));
                    quantity = (int) quantityD;
                    MiscUtils.getLogger().debug("in instrucParser,else=" + quantity + "-- " + takeMax + " --"
                            + nPerDay + "-- " + nDays + "-- " + duration);
                }

            }

            //if drug route is in rx is different from specified, set it to specified.
            if (!route.equals("") && !route.equalsIgnoreCase(rx.getRoute())) {
                rx.setRoute(route);
            }

            rx.setTakeMax(Float.parseFloat(takeMax));
            rx.setTakeMin(Float.parseFloat(takeMin));
            rx.setMethod(method);
            rx.setFrequencyCode(frequency);
            rx.setDurationUnit(durationUnit);
            rx.setPrn(prn);
            MiscUtils.getLogger()
                    .debug("in instrucParser,quantity=" + quantity + " ; unitName=" + rx.getUnitName());
            if (!isUnitNameUsed && quantity != 0) {
                rx.setQuantity(Integer.toString(quantity));
            }
            rx.setSpecial(instructions);
        }
        if (rx.isCustomNote()) {
            rx.setQuantity(null);
            rx.setUnitName(null);
        }
        rx.setPolicyViolations(policyViolations);

        p("below set special");
        HashMap hm = new HashMap();
        hm.put("takeMin", rx.getTakeMin());
        hm.put("takeMax", rx.getTakeMax());
        hm.put("method", rx.getMethod());
        hm.put("route", rx.getRoute());
        hm.put("frequency", rx.getFrequencyCode());
        hm.put("duration", rx.getDuration());
        hm.put("durationUnit", rx.getDurationUnit());
        hm.put("prn", rx.getPrn());
        hm.put("quantity", rx.getQuantity());
        hm.put("policyViolations", policyViolations);
        //    p(instructions);
        MiscUtils.getLogger().debug("in parse instruction: " + hm);
        return;
    }

    public static boolean isStringToNumber(String s) {//see if string contains decimal or integer
        boolean retBool = false;
        Pattern p1 = Pattern.compile("\\d*\\.*\\d+");
        Matcher m1 = p1.matcher(s);
        if (m1.find()) {
            String numStr = s.substring(m1.start(), m1.end());
            String restStr = s.replace(numStr, "").trim();
            if (restStr != null && restStr.length() > 0)
                retBool = false;
            else
                retBool = true;
        } else
            retBool = false;

        return retBool;
    }

    public static String trimSpecial(RxPrescriptionData.Prescription rx) {
        String special = rx.getSpecial();
        if (special == null || special.trim().length() == 0)
            return "";

        //if rx has special instruction, remove it from special
        if (rx.getSpecialInstruction() != null && !rx.getSpecialInstruction().equalsIgnoreCase("null")
                && rx.getSpecialInstruction().trim().length() > 0) {
            special = special.replace(rx.getSpecialInstruction(), "");
        }

        //remove Qty:num
        String regex1 = "Qty:\\s*[0-9]*\\.?[0-9]*\\s*";
        String unitName = rx.getUnitName();
        if (unitName != null && special.indexOf(unitName) != -1) {
            regex1 += "\\Q" + unitName + "\\E";
        }
        Pattern p = Pattern.compile(regex1);
        Matcher m = p.matcher(special);
        special = m.replaceAll("");

        //remove Repeats:num from special
        String regex2 = "Repeats:\\s*[0-9]*\\.?[0-9]*\\s*";
        p = Pattern.compile(regex2);
        m = p.matcher(special);
        special = m.replaceAll("");

        //remove brand name
        String regex3 = rx.getBrandName();
        if (regex3 != null) {
            regex3 = regex3.trim();
            special = special.replace(regex3, "");
        }

        //remove generic name
        String regex4 = rx.getGenericName();
        if (regex4 != null) {
            regex4 = regex4.trim();
            special = special.replace(regex4, "");
        }

        //remove custom name
        String regex5 = rx.getCustomName();
        if (regex5 != null) {
            regex5 = regex5.trim();
            special = special.replace(regex5, "");
        }
        MiscUtils.getLogger().debug("before trimming mitte=" + special);
        String regex6 = "Mitte:\\s*[0-9]+\\s*\\w+";
        p = Pattern.compile(regex6);
        m = p.matcher(special);
        special = m.replaceAll("");
        MiscUtils.getLogger().debug("after trimming mitte special=" + special);
        //assume drug name is before method and drug name is the first part of the instruction.
        String rx_enhance = OscarProperties.getInstance().getProperty("rx_enhance");
        //rx_enhance changes the behavior by not deleting anything up to the words Take, apply..
        if (!(rx_enhance != null && rx_enhance.equals("true"))) {
            if (special.indexOf("Take") != -1) {
                special = special.substring(special.indexOf("Take"));
            } else if (special.indexOf("take") != -1) {
                special = special.substring(special.indexOf("take"));
            } else if (special.indexOf("TAKE") != -1) {
                special = special.substring(special.indexOf("TAKE"));
            } else if (special.indexOf("Apply") != -1) {
                special = special.substring(special.indexOf("Apply"));
            } else if (special.indexOf("apply") != -1) {
                special = special.substring(special.indexOf("apply"));
            } else if (special.indexOf("APPLY") != -1) {
                special = special.substring(special.indexOf("APPLY"));
            } else if (special.indexOf("Rub well in") != -1) {
                special = special.substring(special.indexOf("Rub well in"));
            } else if (special.indexOf("rub well in") != -1) {
                special = special.substring(special.indexOf("rub well in"));
            } else if (special.indexOf("RUB WELL IN") != -1) {
                special = special.substring(special.indexOf("RUB WELL IN"));
            } else if (special.indexOf("Rub Well In") != -1) {
                special = special.substring(special.indexOf("Rub Well In"));
            }
        }

        return special.trim();

    }

    public static void printStashContent(oscar.oscarRx.pageUtil.RxSessionBean bean) {
        p("***drugs in present stash,stash size", "" + bean.getStashSize());
        for (int j = 0; j < bean.getStashSize(); j++) {
            try {
                RxPrescriptionData.Prescription rxTemp = bean.getStashItem(j);
                p("stash index", "" + j);
                p("randomId", "" + rxTemp.getRandomId());
                p("generic name", rxTemp.getGenericName());
                p("special", rxTemp.getSpecial());
                p("quantity", rxTemp.getQuantity());
                p("repeat=" + rxTemp.getRepeat());
                p("atccode", rxTemp.getAtcCode());
                p("regional identifier", rxTemp.getRegionalIdentifier());
                p("---");
            } catch (Exception e) {
                MiscUtils.getLogger().error("Error", e);
            }
        }
        p("***done***");

    }

    public static void setDefaultSpecialQuantityRepeat(RxPrescriptionData.Prescription rx) {

        String defaultRx = OscarProperties.getInstance().getProperty("rx.default_instruction");
        if (defaultRx != null) {
            rx.setSpecial(defaultRx);
        } else {
            rx.setSpecial("");
        }
        rx.setQuantity(getDefaultQuantity());
        rx.setRepeat(0);

    }

    private static void setResultSpecialQuantityRepeat(RxPrescriptionData.Prescription rx, ResultSet rs) {
        try {
            String qStr = rs.getString("quantity");
            Pattern p1 = Pattern.compile("\\d+");
            Matcher m1 = p1.matcher(qStr);
            if (m1.find()) {
                String qNum = qStr.substring(m1.start(), m1.end());
                rx.setQuantity(qNum);
                //get the quantity unit
                String qUnit = qStr.replace(qNum, "").trim();
                if (qUnit != null && qUnit.length() > 0) {
                    MiscUtils.getLogger().debug("changing unitName in setResultSpecialQuantityRepeat ");
                    rx.setUnitName(qUnit);
                }
            }
            rx.setUnitName(rs.getString("unitName"));

            rx.setRepeat(rs.getInt("repeat"));
            rx.setSpecial(rs.getString("special"));
            rx.setSpecial(trimSpecial(rx));

        } catch (SQLException e) {
            MiscUtils.getLogger().error("Error", e);
        }
    }

    private static List<HashMap<String, String>> drugsTableQuery(String parameter, String value) {
        List<HashMap<String, String>> retList = new ArrayList();
        try {
            ResultSet rs;
            String sql = "select special ,special_instruction from drugs where " + parameter + " = '" + value
                    + "' order by drugid desc";
            MiscUtils.getLogger().debug("in drugsTableQuery,sql=" + sql);
            rs = DBHandler.GetSQL(sql);
            while (rs.next()) {
                HashMap hm = new HashMap();
                hm.put("instruction", rs.getString("special"));
                hm.put("special_instruction", rs.getString("special_instruction"));
                retList.add(hm);
            }
        } catch (Exception e) {
            MiscUtils.getLogger().error("Error", e);
        }
        MiscUtils.getLogger().debug("in drugsTableQuery,retList=" + retList);
        return retList;
    }

    private static List<HashMap<String, String>> getCustomNamePrevInstructions(String customName) {
        return drugsTableQuery("customName", customName);
    }

    private static List<HashMap<String, String>> getDinPrevInstructions(String din) {
        return drugsTableQuery("regional_identifier", din);
    }

    private static List<HashMap<String, String>> getBNPrevInstructions(String bn) {
        return drugsTableQuery("BN", bn);
    }

    private static List<HashMap<String, String>> getGNPrevInstructions(String gn) {
        return drugsTableQuery("GN", gn);
    }

    public static List<HashMap<String, String>> getPreviousInstructions(RxPrescriptionData.Prescription rx) {
        List<HashMap<String, String>> retList = new ArrayList();
        if (rx.isCustom()) {
            String cn = rx.getCustomName();
            if (cn != null && cn.trim().length() > 0)
                retList = getCustomNamePrevInstructions(cn);
        } else {
            String din = rx.getRegionalIdentifier();
            if (din != null && din.trim().length() > 0) {
                retList = getDinPrevInstructions(din);
                if (retList.size() == 0) {
                    retList = getBNPrevInstructions(rx.getBrandName());
                    //if(retList.size()==0)
                    //retList=getGNPrevInstructions(rx.getGenericName());
                }
            } else {
                String bn = rx.getBrandName();
                if (bn != null && bn.trim().length() > 0)
                    retList = getBNPrevInstructions(bn);
            }
        }
        if (retList.size() > 0)
            retList = trimMedHistoryList(rx, retList);
        return retList;
    }

    private static List<HashMap<String, String>> trimMedHistoryList(RxPrescriptionData.Prescription rx,
            List<HashMap<String, String>> l) {

        String customName = rx.getCustomName();
        String bn = rx.getBrandName();
        List<HashMap<String, String>> retList = new ArrayList();
        if (l.size() > 0 || rx != null) {
            try {
                for (HashMap hm : l) {
                    String ins = (String) hm.get("instruction");
                    String specIns = (String) hm.get("special_instruction");
                    if (ins != null && ins.length() > 0) {
                        if (customName != null && !customName.equalsIgnoreCase("null"))
                            ins = ins.replace(customName, "");
                        if (bn != null && !bn.equalsIgnoreCase("null"))
                            ins = ins.replace(bn, "");
                        if (specIns != null && !specIns.equalsIgnoreCase("null"))
                            ins = ins.replace(specIns, "");
                    }
                    if (ins != null)
                        ins = ins.replace("\n", " ").trim();
                    if (specIns != null)
                        specIns = specIns.replace("\n", " ").trim();
                    HashMap<String, String> h = new HashMap();
                    h.put("instruction", removeQuantityMitteRepeat(ins));
                    h.put("special_instruction", specIns);
                    retList.add(h);
                }
            } catch (Exception e) {
                MiscUtils.getLogger().error("Error", e);
            }
            retList = commonUniqueMedHistory(retList);
        } else
            ;

        return retList;
    }

    private static List<HashMap<String, String>> commonUniqueMedHistory(List<HashMap<String, String>> l) {
        MiscUtils.getLogger().debug("in commonUniqueMedHistory l=" + l);

        if (l != null && l.size() > 0) {
            HashMap elementCount = new HashMap();
            List<HashMap<String, String>> retList = new ArrayList();
            for (HashMap<String, String> hm : l) {
                if (!elementCount.containsKey(hm))
                    elementCount.put(hm, 1);
                else
                    elementCount.put(hm, (Integer) elementCount.get(hm) + 1);
            }
            List<Integer> count = new ArrayList(elementCount.values());
            HashMap[] arr = new HashMap[count.size()];
            Collections.sort(count);//ascending order
            try {
                for (int i = count.size() - 1; i >= 0; i--) {
                    Set set = elementCount.keySet();
                    Iterator iter = set.iterator();
                    while (iter.hasNext()) {
                        HashMap key = (HashMap) iter.next();
                        Integer value = (Integer) elementCount.get(key);
                        if (value == count.get(i)) {
                            retList.add(key);
                            elementCount.remove(key);
                            break;
                        } else
                            ;
                    }
                }
            } catch (Exception e) {
                MiscUtils.getLogger().error("Error", e);
            }
            MiscUtils.getLogger().debug("in commonUniqueMedHistory retList=" + retList);
            return retList;
        } else
            return l;
    }

    //return distinct hashmap
    /*private static List<HashMap<String,String>> distinctMedHistory(List<HashMap<String,String>> l){
    if(l!=null && l.size()>0){
        for(int i=0;i<l.size();i++){
            HashMap<String,String> hm1=l.get(i);
            String s1=hm1.toString();
            for(int h=i+1;h<l.size();h++){
                HashMap<String,String> hm2=l.get(h);
                String s2=hm2.toString();
                if(s2.equalsIgnoreCase(s1)){
                    l.remove(hm2);
                    --h;
                }
            }
        }
        return l;
    }else return l;
    }*/
    private static String removeQuantityMitteRepeat(String s) {
        Pattern p;
        Matcher m;
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat s=" + s);
        String regex2 = "Repeats:\\s*[0-9]*\\.?[0-9]*\\s*";
        p = Pattern.compile(regex2);
        m = p.matcher(s);
        s = m.replaceAll("");
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat regex=" + regex2);
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat after remove repeat s=" + s);

        String regex1 = "Qty:\\s*[0-9]*\\.?[0-9]*\\s*\\w*";
        p = Pattern.compile(regex1);
        m = p.matcher(s);
        s = m.replaceAll("");
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat regex=" + regex1);
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat after remove quantity =" + s);

        String regex6 = "Mitte:\\s*[0-9]*\\.?[0-9]*\\s*\\w*";
        p = Pattern.compile(regex6);
        m = p.matcher(s);
        s = m.replaceAll("");
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat regex=" + regex6);
        MiscUtils.getLogger().debug("in removeQuantityMitteRepeat after remove mitte =" + s);
        s = s.trim();
        return s;
    }

    public static void setSpecialQuantityRepeat(RxPrescriptionData.Prescription rx) {

        try {

            ResultSet rs;
            if (rx.getRegionalIdentifier() != null && rx.getRegionalIdentifier().length() > 1) {
                p("if1");
                p(rx.getRegionalIdentifier());
                //query the database to see if there is a rx with same din as this rx.
                // String sql = "SELECT * FROM drugs WHERE regional_identifier='" + rx.getRegionalIdentifier() + "' order by written_date desc"; //most recent is the first.
                String sql = "SELECT * FROM drugs WHERE regional_identifier='" + rx.getRegionalIdentifier()
                        + "' and BN='" + StringEscapeUtils.escapeSql(rx.getBrandName()) + "' AND demographic_no="
                        + rx.getDemographicNo() + " AND provider_no = '" + rx.getProviderNo()
                        + "' order by drugid desc"; //most recent is the first.
                MiscUtils.getLogger().debug("sql 1=" + sql);
                rs = DBHandler.GetSQL(sql);
                if (rs.first()) {//use the first result if there are multiple.
                    setResultSpecialQuantityRepeat(rx, rs);
                } else {
                    setDefaultSpecialQuantityRepeat(rx);
                }
            } else {
                p("else2");
                if (rx.getBrandName() != null && rx.getBrandName().length() > 1) {
                    p("if2");
                    //String sql2 = "SELECT * FROM drugs WHERE BN='" + StringEscapeUtils.escapeSql(rx.getBrandName()) + "' order by written_date desc"; //most recent is the first.
                    String sql2 = "SELECT * FROM drugs WHERE BN='" + StringEscapeUtils.escapeSql(rx.getBrandName())
                            + "' AND demographic_no=" + rx.getDemographicNo() + " AND provider_no = '"
                            + rx.getProviderNo() + "' order by drugid desc"; //most recent is the first.
                    MiscUtils.getLogger().debug("sql 2=" + sql2);
                    //if none, query database to see if there is rx with same brandname.
                    //if there are multiple, use latest.
                    rs = DBHandler.GetSQL(sql2);
                    if (rs.first()) {
                        setResultSpecialQuantityRepeat(rx, rs);
                    } else {
                        //else, set to special to "", quantity to "30", repeat to "0".
                        setDefaultSpecialQuantityRepeat(rx);
                    }
                } else {
                    p("if3");
                    if (rx.getCustomName() != null && rx.getCustomName().length() > 1) {
                        p("customName is not null");
                        //String sql3 = "SELECT * FROM drugs WHERE customName='" + StringEscapeUtils.escapeSql(rx.getCustomName()) + "' order by written_date desc"; //most recent is the first.
                        String sql3 = "SELECT * FROM drugs WHERE customName='"
                                + StringEscapeUtils.escapeSql(rx.getCustomName()) + "'  AND demographic_no="
                                + rx.getDemographicNo() + " AND provider_no = '" + rx.getProviderNo()
                                + "' order by drugid desc"; //most recent is the first.
                        MiscUtils.getLogger().debug("sql 3=" + sql3);
                        //if none, query database to see if there is rx with same customName.
                        //if there are multiple, use latest.
                        rs = DBHandler.GetSQL(sql3);
                        if (rs.first()) {
                            setResultSpecialQuantityRepeat(rx, rs);
                        } else {
                            setDefaultSpecialQuantityRepeat(rx);
                        }
                    } else {
                        //else, set to special to "", quantity to "30", repeat to "0".
                        setDefaultSpecialQuantityRepeat(rx);
                    }
                }
            }
        } catch (SQLException e) {
            logger.error("SQL Query ERROR", e);
        } finally {
            DbConnectionFilter.releaseThreadLocalDbConnection();
        }
    }

    private static boolean checkLastPrescribed(RxPrescriptionData.Prescription rx, int drugId) {
        //make a another query to get the latest drug with same name but archived not equals one and arhived reason equals to deleted.
        //check if drugId is greater than that compare id
        //if yes, return true;
        //if not, return false;
        boolean lastPrescribed = true;
        //need the max drugId, not using DIN because it doesn't work with customed drugs.
        String sql = "SELECT max(drugid) FROM drugs WHERE archived=0 AND archived_reason='' AND BN='"
                + StringEscapeUtils.escapeSql(rx.getBrandName()) + "' AND GN='"
                + StringEscapeUtils.escapeSql(rx.getGenericName()) + "' AND demographic_no="
                + rx.getDemographicNo();

        try {

            ResultSet rs;
            rs = DBHandler.GetSQL(sql);
            if (rs.next()) {
                int compareId = rs.getInt("max(drugid)");
                MiscUtils.getLogger().debug("compareId: " + compareId);
                if (drugId > compareId) {
                    lastPrescribed = true;
                } else {
                    lastPrescribed = false;
                }
            } else {
                lastPrescribed = true;
            }
        } catch (SQLException e) {
            logger.error(sql, e);
        }
        return lastPrescribed;
    }

    public static boolean checkDiscontinuedBefore(RxPrescriptionData.Prescription rx) {//check if this drug was discontinued before

        //String sql="SELECT * FROM drugs WHERE archived=1 AND (archived_reason>'' OR archived_reason<'' ) AND ATC='" + this.atcCode + "' AND regional_identifier='" + this.regionalIdentifier + "' AND demographic_no=" + this.demographicNo+" order by written_date desc";
        //the query will fail to check if a drug A is prescribed, and drug A is prescribed again, and then the first drug A is discontinued,when the second drug A is represcribed
        //or a third drug A is added, no warning will be given.
        boolean discontinuedLatest = false;
        String sql = "SELECT * FROM drugs WHERE archived=1 AND archived_reason<>'' AND ATC='" + rx.getAtcCode()
                + "' AND regional_identifier='" + rx.getRegionalIdentifier() + "' AND demographic_no="
                + rx.getDemographicNo() + " order by drugid desc";
        try {

            ResultSet rs;
            rs = DBHandler.GetSQL(sql);
            if (rs.next()) {//get the first result which has the largest drugid and hence the most recent result.

                int drugId = rs.getInt("drugid");

                boolean isLastPrescribed = checkLastPrescribed(rx, drugId);//check if this drug was saved after discontinued.
                if (isLastPrescribed) {

                    //get date discontinued
                    //get reason for discontinued
                    Date archivedDate = rs.getDate("archived_date");
                    // String archDate = rs.getString("archived_date");
                    String archDate = RxUtil.DateToString(archivedDate);
                    String archReason = oscar.Misc.getString(rs, "archived_reason");

                    rx.setLastArchDate(archDate);
                    rx.setLastArchReason(archReason);
                    discontinuedLatest = true;
                } else {
                    discontinuedLatest = false;
                    MiscUtils.getLogger().debug("not last drug ");
                }
            } else {

                discontinuedLatest = false;
            }
        } catch (SQLException e) {
            logger.error(sql, e);
        } finally {
            DbConnectionFilter.releaseThreadLocalDbConnection();
        }

        return discontinuedLatest;
    }

    //check to see if a represcription of a med is clicked twice.
    public static boolean isRxUniqueInStash(final oscar.oscarRx.pageUtil.RxSessionBean beanRx,
            final RxPrescriptionData.Prescription rx) {
        boolean unique = true;
        if (rx.isCustom()) {
            for (int j = 0; j < beanRx.getStashSize(); j++) {
                try {
                    RxPrescriptionData.Prescription rxTemp = beanRx.getStashItem(j);
                    //p(""+rxTemp.isCustom());
                    //p(rxTemp.getCustomName());
                    //p(rx.getCustomName());
                    //p(""+rxTemp.isCustomNote());
                    //p(""+rx.isCustomNote());
                    //p(""+rxTemp.getRandomId());
                    //p(""+rx.getRandomId());
                    if (rxTemp.isCustom() && rxTemp.getCustomName().equals(rx.getCustomName())
                            && rxTemp.isCustomNote() == rx.isCustomNote()
                            && rxTemp.getRandomId() != rx.getRandomId()) {
                        p("1unique turning false");
                        unique = false;
                    }
                } catch (Exception e) {
                    MiscUtils.getLogger().error("Error", e);
                }
            }
        } else {
            for (int j = 0; j < beanRx.getStashSize(); j++) {
                try {
                    RxPrescriptionData.Prescription rxTemp = beanRx.getStashItem(j);
                    //p(rx.getBrandName());
                    //p(rxTemp.getBrandName());

                    //p(""+rxTemp.getRandomId());
                    //p(""+rx.getRandomId());
                    if (rx.getBrandName() != null && !rx.getBrandName().equalsIgnoreCase("null")
                            && rx.getBrandName().equals(rxTemp.getBrandName())
                            && rxTemp.getRandomId() != rx.getRandomId()) { //GCN_SWQNO changes when drugref database is updated
                        p("2unique turning false");
                        unique = false;
                    }
                } catch (Exception e) {
                    MiscUtils.getLogger().error("Error", e);
                }
            }
        }
        if (unique) {
            p("unique is true");
        }
        return unique;
    }

    public static String getSpecialInstructions() {
        String retStr = "";
        RxCodesData codesData = new RxCodesData();
        String[] specArr = codesData.getSpecialInstructions();
        List<String> specList = Arrays.asList(specArr);
        // get all past record spec inst from drugs table
        String sql = "SELECT distinct special_instruction from drugs where special_instruction!='NULL'";
        List<String> resultSpecInst = new ArrayList<String>();
        try {

            ResultSet rs;
            rs = DBHandler.GetSQL(sql);
            while (rs.next()) {
                resultSpecInst.add(rs.getString("special_instruction"));
            }
        } catch (SQLException e) {
            logger.error(sql, e);
        } finally {
            DbConnectionFilter.releaseThreadLocalDbConnection();
        }
        resultSpecInst.addAll(specList);
        Set<String> specIntSet = new HashSet<String>(resultSpecInst);//remove duplicates
        specArr = specIntSet.toArray(specArr);
        for (int i = 0; i < specArr.length; i++) {
            retStr += specArr[i];
            if (i < specArr.length - 1)
                retStr += "*"; //use * as a delimiter
        }
        return retStr;

    }

    public static String findInterDrugStr(final UserPropertyDAO propDAO, String provider,
            final RxSessionBean bean) {
        //quiry mydrugref database to get a vector with all interacting drugs
        //if effect is not null or effect is not empty string
        //get a list of all pending prescriptions' ATC codes
        //compare if anyone match,
        //if yes, get it's randomId and set an session attribute
        //if not, do nothing

        UserProperty prop = propDAO.getProp(provider, UserProperty.MYDRUGREF_ID);
        String myDrugrefId = null;
        if (prop != null) {
            myDrugrefId = prop.getValue();
            MiscUtils.getLogger().debug("3myDrugrefId" + myDrugrefId);
        }
        RxPrescriptionData.Prescription[] rxs = bean.getStash();
        //acd contains all atccodes in stash
        Vector<String> acd = new Vector<String>();
        for (RxPrescriptionData.Prescription rxItem : rxs) {
            acd.add(rxItem.getAtcCode());
        }
        logger.debug("3acd=" + acd);

        String[] str = new String[] { "warnings_byATC,bulletins_byATC,interactions_byATC,get_guidelines" }; //NEW more efficent way of sending multiple requests at the same time.
        Vector allInteractions = new Vector();
        for (String command : str) {
            try {
                Vector v = getMyDrugrefInfo(command, acd, myDrugrefId);
                MiscUtils.getLogger().debug("2v in for loop: " + v);
                if (v != null && v.size() > 0) {
                    allInteractions.addAll(v);
                }
                MiscUtils.getLogger().debug("3after all.addAll(v): " + allInteractions);
            } catch (Exception e) {
                log2.debug("3command :" + command + " " + e.getMessage());
                MiscUtils.getLogger().error("Error", e);
            }
        }
        String retStr = "";
        HashMap rethm = new HashMap();
        for (RxPrescriptionData.Prescription rxItem : rxs) {
            MiscUtils.getLogger().debug("rxItem=" + rxItem.getDrugName());
            Vector uniqueDrugNameList = new Vector();
            for (int i = 0; i < allInteractions.size(); i++) {
                Hashtable hb = (Hashtable) allInteractions.get(i);
                String interactingAtc = (String) hb.get("atc");
                String interactingDrugName = (String) hb.get("drug2");
                String effectStr = (String) hb.get("effect");
                String sigStr = (String) hb.get("significance");
                MiscUtils.getLogger().debug("findInterDrugStr=" + hb);
                if (sigStr != null) {
                    if (sigStr.equals("1")) {
                        sigStr = "minor";
                    } else if (sigStr.equals("2")) {
                        sigStr = "moderate";
                    } else if (sigStr.equals("3")) {
                        sigStr = "major";
                    } else {
                        sigStr = "unknown";
                    }
                } else {
                    sigStr = "unknown";
                }
                if (interactingAtc != null && interactingDrugName != null
                        && rxItem.getAtcCode().equals(interactingAtc) && effectStr != null && effectStr.length() > 0
                        && !effectStr.equalsIgnoreCase("N") && !effectStr.equals(" ")) {
                    MiscUtils.getLogger().debug("interactingDrugName=" + interactingDrugName);
                    RxPrescriptionData.Prescription rrx = findRxFromDrugNameOrGN(rxs, interactingDrugName);

                    if (rrx != null && !uniqueDrugNameList.contains(rrx.getDrugName())) {
                        MiscUtils.getLogger().debug("rrx.getDrugName()=" + rrx.getDrugName());
                        uniqueDrugNameList.add(rrx.getDrugName());

                        String key = sigStr + "_" + rxItem.getRandomId();

                        if (rethm.containsKey(key)) {
                            String val = (String) rethm.get(key);
                            val += ";" + rrx.getDrugName();
                            rethm.put(key, val);
                        } else {
                            rethm.put(key, rrx.getDrugName());
                        }

                        key = sigStr + "_" + rrx.getRandomId();
                        if (rethm.containsKey(key)) {
                            String val = (String) rethm.get(key);
                            val += ";" + rxItem.getDrugName();
                            rethm.put(key, val);
                        } else {
                            rethm.put(key, rxItem.getDrugName());
                        }
                    }
                }
            }
            MiscUtils.getLogger().debug("***next rxItem***");
        }
        MiscUtils.getLogger().debug("rethm=" + rethm);
        retStr = rethm.toString();
        retStr = retStr.replace("}", "");
        retStr = retStr.replace("{", "");

        return retStr;
    }

    private static RxPrescriptionData.Prescription findRxFromDrugNameOrGN(
            final RxPrescriptionData.Prescription[] rxs, String interactingDrugName) {
        RxPrescriptionData.Prescription returnRx = null;
        for (RxPrescriptionData.Prescription rxItem : rxs) {
            if (rxItem.getDrugName().contains(interactingDrugName)) {
                returnRx = rxItem;
            } else if (rxItem.getGenericName().contains(interactingDrugName)) {
                returnRx = rxItem;
            }
        }
        return returnRx;

    }

    private static Vector getMyDrugrefInfo(String command, Vector drugs, String myDrugrefId) {
        MiscUtils.getLogger().debug("3in getMyDrugrefInfo");
        RxMyDrugrefInfoAction.removeNullFromVector(drugs);
        Vector params = new Vector();
        MiscUtils.getLogger().debug("3command,drugs,myDrugrefId= " + command + "--" + drugs + "--" + myDrugrefId);
        params.addElement(command);
        params.addElement(drugs);
        if (myDrugrefId != null && !myDrugrefId.trim().equals("")) {
            log2.debug("putting >" + myDrugrefId + "< in the request");
            params.addElement(myDrugrefId);
            //params.addElement("true");
        }
        Vector vec = new Vector();
        Object obj = callWebserviceLite("Fetch", params);
        log2.debug("RETURNED " + obj);
        if (obj instanceof Vector) {
            MiscUtils.getLogger().debug("3obj is instance of vector");
            vec = (Vector) obj;
            MiscUtils.getLogger().debug(vec);
        } else if (obj instanceof Hashtable) {
            MiscUtils.getLogger().debug("3obj is instace of hashtable");
            Object holbrook = ((Hashtable) obj).get("Holbrook Drug Interactions");
            if (holbrook instanceof Vector) {
                MiscUtils.getLogger().debug("3holbrook is instance of vector ");
                vec = (Vector) holbrook;
                MiscUtils.getLogger().debug(vec);
            }
            Enumeration e = ((Hashtable) obj).keys();
            while (e.hasMoreElements()) {
                String s = (String) e.nextElement();
                MiscUtils.getLogger().debug(s);
                log2.debug(
                        s + " " + ((Hashtable) obj).get(s) + " " + ((Hashtable) obj).get(s).getClass().getName());
            }
        }
        return vec;
    }

    private static final Logger log2 = MiscUtils.getLogger();

    public static Object callWebserviceLite(String procedureName, Vector params) {
        log2.debug("#CALLmyDRUGREF-" + procedureName);
        Object object = null;

        String server_url = OscarProperties.getInstance().getProperty("MY_DRUGREF_URL",
                "http://mydrugref.org/backend/api");
        MiscUtils.getLogger().debug("server_url: " + server_url);
        TimingOutCallback callback = new TimingOutCallback(30 * 1000);
        try {
            log2.debug("server_url :" + server_url);
            XmlRpcClientLite server = new XmlRpcClientLite(server_url);
            server.executeAsync(procedureName, params, callback);
            object = callback.waitForResponse();
        } catch (TimeoutException e) {
            log2.debug("No response from server." + server_url);
        } catch (Throwable ethrow) {
            log2.debug("Throwing error." + ethrow.getMessage());
        }
        return object;
    }

    public static <T> HashMap<Long, T> createKeyValPair(List<T> lst) {
        HashMap<Long, T> ret = new HashMap<Long, T>();
        Long rand;
        for (T t : lst) {
            rand = Math.round(Math.random() * 1000000);
            ret.put(rand, t);
        }
        return ret;
    }

    public static void p(String str, String s) {
        MiscUtils.getLogger().debug(str + "=" + s);
    }

    public static void p(String str) {
        MiscUtils.getLogger().debug(str);
    }
}