Wednesday, 27 April 2016

TransactionHistoryDataUtil To perform date formats and find the days

/*** Eclipse Class Decompiler plugin, copyright (c) 2012 Chao Chen (cnfree2000@hotmail.com) ***/
package com.benefitfocus.transactionhistory.common.util;

import bf.lang.ObjectUtil;
import com.benefitfocus.transactionhistory.snapshotdata.Identifier;
import com.benefitfocus.transactionhistory.snapshotdata.IdentifierType;
import com.benefitfocus.transactionhistory.snapshotdata.Metadata;
import com.benefitfocus.transactionhistory.snapshotdata.TransitoryCommElement;
import com.benefitfocus.transactionhistory.snapshotdata.TransitoryElement;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.commons.lang.StringUtils;

public final class TransactionHistoryDataUtil {
public static final String YEAR_MONTH_DAY_HOUR_SEC = "yyyyMMddhhmmss";
public static final String YEAR_MONTH_DAY_HOUR_SECONDS = "yyyyMMddhhmmssss";
public static final String YEAR_MONTH_DAY_24HOUR_SEC = "yyyyMMddHHmmss";
public static final String YEAR_MONTH_DAY_HOUR_SECONDS_EXTENDED = "yyyyMMdd_hhmmssSSS";
public static final String DAY_MONTH_YEAR_ENROLLMENT = "dd-MM-yy";
public static final String MONTH_DAY_YYYY = "MMddyyyy";
public static final String MONTH_DAY_YYYY_SLASH = "MM/dd/yyyy";
public static final String MONTH_DAY_YYYY_HYPHENATED = "MM-dd-yyyy";
public static final String YYYY_MONTH_DAY = "yyyyMMdd";
public static final String YYYY_MONTH_DAY_HYPHENATED = "yyyy-MM-dd";
public static final String FORMAT_DATETIME_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
public static final String ORACLE_SQL_TIMESTAMP = "dd-MMM-yy hh.mm.ss.SSS a";
private static final List<String> dateFormatList = new ArrayList();

public static Date getFormattedDate(String format) throws ParseException {
return getFormattedDate(format, new Date());
}

public static Date addDays(Date date, int daysToAdd) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(5, daysToAdd);
return cal.getTime();
}

public static Date subtractDays(Date date, int daysToSubtract) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(5, -daysToSubtract);
return cal.getTime();
}

public static Date addMinutes(Date date, int minutesToAdd) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(12, minutesToAdd);
return cal.getTime();
}

public static boolean isDateBetween(Date startDate, Date endDate,
Date targetDate) {
if ((startDate == null) || (endDate == null) || (targetDate == null)
|| (endDate.before(startDate))) {
return false;
}

boolean result = false;
if ((targetDate.compareTo(startDate) == 0)
&& (targetDate.compareTo(endDate) < 0))
result = true;
else if ((targetDate.compareTo(endDate) == 0)
&& (targetDate.compareTo(startDate) > 0))
result = true;
else if (targetDate.compareTo(startDate)
* endDate.compareTo(targetDate) > 0) {
result = true;
}

return result;
}

public static Date today() {
Date today = new Date();
return zero(today);
}

public static Date zero(Date date) {
if (date != null) {
Calendar myCal = Calendar.getInstance(Locale.US);
myCal.setTime(date);
myCal.set(11, 0);
myCal.set(12, 0);
myCal.set(13, 0);
myCal.set(14, 0);
return myCal.getTime();
}
return date;
}

public static String addDays(String format, String date, int daysToAdd)
throws ParseException {
Calendar cal = Calendar.getInstance();
cal.setTime(getFormattedDate(format, date));
cal.add(5, daysToAdd);
return getFormattedDateString(format, cal.getTime());
}

public static Date addDaysDate(String format, String date, int daysToAdd)
throws ParseException {
Calendar cal = Calendar.getInstance();
cal.setTime(getFormattedDate(format, date));
cal.add(5, daysToAdd);
return getFormattedDate(format, cal.getTime());
}

public static Date addYears(Date date, int years) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

boolean originalDateWasEndOfMonth = calendar.getActualMaximum(5) == calendar
.get(5);

calendar.add(1, years);

if (originalDateWasEndOfMonth) {
boolean currentDateIsEndOfMonth = calendar.getActualMaximum(5) == calendar
.get(5);

if (!(currentDateIsEndOfMonth)) {
calendar.set(5, calendar.getActualMaximum(5));
}
}

return calendar.getTime();
}

public static boolean isOlderThan(Date dateOfBirth, int age, Date asOfDate) {
Date dateTurnedRequestedAge = addYears(dateOfBirth, age);
return dateTurnedRequestedAge.before(asOfDate);
}

public static String getFormattedDateString(String format)
throws ParseException {
return getFormattedDateString(format, getFormattedDate(format));
}

public static String getFormattedDateString(String format, Date date) {
if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equalsIgnoreCase(format)) {
DateFormat simpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return simpleDateFormat.format(date);
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
return simpleDateFormat.format(date);
}

public static String getSQLFormattedDateTime(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
"dd-MMM-yy hh.mm.ss.SSS a");
return simpleDateFormat.format(date);
}

public static String getFormattedDateString(String format, String date)
throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
Date parsedDate = simpleDateFormat.parse(date.toString());
return simpleDateFormat.format(parsedDate);
}

public static Date getFormattedDate(String format, String date)
throws ParseException {
if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equalsIgnoreCase(format)) {
DateFormat simpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return simpleDateFormat.parse(date);
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
return simpleDateFormat.parse(date);
}

public static Date getFormattedDate(String format, Date date)
throws ParseException {
if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equalsIgnoreCase(format)) {
DateFormat simpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return simpleDateFormat.parse(simpleDateFormat.format(date));
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
return simpleDateFormat.parse(simpleDateFormat.format(date));
}

@Deprecated
public static Date getDate(String date) {
Date formattedDate = null;
if (date != null) {
for (String format : dateFormatList) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
try {
simpleDateFormat.setLenient(false);
formattedDate = simpleDateFormat.parse(date.toString());
} catch (ParseException localParseException) {
}
}
}

return formattedDate;
}

public static boolean before(TransitoryElement date1,
TransitoryElement date2, String dateFormat) throws ParseException {
return ((transitoryElementHasNonEmptyValue(date1))
&& (transitoryElementHasNonEmptyValue(date2)) && (before(
date1.getValue(), date2.getValue(), dateFormat)));
}

public static boolean after(TransitoryElement date1,
TransitoryElement date2, String dateFormat) throws ParseException {
return ((transitoryElementHasNonEmptyValue(date1))
&& (transitoryElementHasNonEmptyValue(date2)) && (after(
date1.getValue(), date2.getValue(), dateFormat)));
}

public static boolean before(String date1, String date2, String dateFormat)
throws ParseException {
if ((date1 == null) || (date2 == null)) {
return false;
}

return before(getFormattedDate(dateFormat, date1),
getFormattedDate(dateFormat, date2));
}

public static boolean after(String date1, String date2, String dateFormat)
throws ParseException {
if ((date1 == null) || (date2 == null)) {
return false;
}

return after(getFormattedDate(dateFormat, date1),
getFormattedDate(dateFormat, date2));
}

public static boolean before(Date date1, Date date2) {
if ((date1 == null) || (date2 == null)) {
return false;
}

return (compare(date1, date2) < 0);
}

public static boolean after(Date date1, Date date2) {
if ((date1 == null) || (date2 == null)) {
return false;
}

return (compare(date1, date2) > 0);
}

public static int daysDifferentBetweenDates(Date earlier, Date later) {
if ((earlier == null) || (later == null))
return 0;
return (int) (later.getTime() / 86400000L - (earlier.getTime() / 86400000L));
}

public static int compare(Date date1, Date date2) {
if ((ObjectUtil.isEmpty(date1)) && (ObjectUtil.isEmpty(date2)))
return 0;
if ((ObjectUtil.isEmpty(date1) ^ ObjectUtil.isEmpty(date2))) {
return ((ObjectUtil.isEmpty(date1)) ? -1 : 1);
}
Date d1 = zero(date1);
Date d2 = zero(date2);

return d1.compareTo(d2);
}

public static boolean transitoryElementHasNonEmptyValue(
TransitoryElement element) {
return ((element != null) && (element.getValue() != null) && (!(element
.getValue().trim().equals(""))));
}

public static boolean transitoryCommElementHasNonEmptyValue(
TransitoryCommElement element) {
return ((element != null) && (element.getValue() != null) && (!(element
.getValue().trim().equals(""))));
}

public static boolean isTransitoryElementValueEmptyOrNull(
TransitoryElement element) {
return ((element == null) || (element.getValue() == null));
}

public static boolean isTransitoryElementPreviousEmptyOrNull(
TransitoryElement element) {
return ((element == null) || (element.getPrevious() == null));
}

public static boolean isTransitoryCommElementValueEmptyOrNull(
TransitoryCommElement element) {
return ((element == null) || (element.getValue() == null));
}

public static boolean isTransitoryCommElementPreviousEmptyOrNull(
TransitoryCommElement element) {
return ((element == null) || (element.getPrevious() == null));
}

public static TransitoryElement generateTransitoryElement(
String stringValue, String previousValue) {
TransitoryElement transitoryElement = new TransitoryElement();
transitoryElement.setValue(stringValue);
if (previousValue != null) {
transitoryElement.setPrevious(previousValue);
}
return transitoryElement;
}

public static String getTransitoryElementPreviousAsString(
TransitoryElement element, String defaultVal) {
if ((element != null) && (element.getPrevious() != null)
&& (element.getPrevious().trim().length() > 0)) {
return element.getPrevious();
}

return defaultVal;
}

public static String getTransitoryElementAsString(
TransitoryElement element, String defaultValue) {
if ((element == null) || (element.getValue() == null)) {
return defaultValue;
}
return element.getValue();
}

public static Boolean isTransitoryElementValueEqual(
TransitoryElement element1, TransitoryElement element2) {
if ((element1 == null) && (element2 == null)) {
return Boolean.valueOf(true);
}
if ((element1 == null) || (element2 == null)) {
return Boolean.valueOf(false);
}
return Boolean.valueOf(StringUtils.equals(element1.getValue(),
element2.getValue()));
}

public static Boolean isTransitoryElementPreviousEqual(
TransitoryElement element1, TransitoryElement element2) {
if ((element1 == null) && (element2 == null)) {
return Boolean.valueOf(true);
}
if ((element1 == null) || (element2 == null)) {
return Boolean.valueOf(false);
}
return Boolean.valueOf(StringUtils.equals(element1.getPrevious(),
element2.getPrevious()));
}

public static Boolean isEntireTransitoryElementEqual(
TransitoryElement element1, TransitoryElement element2) {
return Boolean.valueOf((isTransitoryElementPreviousEqual(element1,
element2).booleanValue())
&& (isTransitoryElementValueEqual(element1, element2)
.booleanValue()));
}

public static void addMetadataToMetadataList(List<Metadata> metadataList,
String key, String value) {
if (metadataList != null)
metadataList.add(generateMetadata(key, value));
}

public static void addMetadataToMetadataList(List<Metadata> metadataList,
String key, String value, String startDate, String endDate) {
if (metadataList != null)
metadataList.add(generateMetadata(key, value, startDate, endDate));
}

public static Metadata findMetadataByKey(List<Metadata> metadataList,
String key) {
for (Metadata metaData : metadataList) {
if (key.equals(metaData.getName())) {
return metaData;
}
}
return null;
}

public static Metadata generateMetadata(String key, String value) {
Metadata metaData = new Metadata();
metaData.setName(key);
metaData.setValue(value);
return metaData;
}

public static Metadata generateMetadata(String key, String value,
String startDate, String endDate) {
Metadata metaData = new Metadata();
metaData.setName(key);
metaData.setValue(value);
metaData.setEffectiveDate(startDate);
metaData.setExpirationDate(endDate);
return metaData;
}

public static String getAnnualSalary(String earningsClass, String salary) {
if ((earningsClass != null) && (!(earningsClass.equals("")))
&& (salary != null) && (!(salary.equals("")))) {
BigDecimal numPayChecks = new BigDecimal(
getYearlyPaychecks(earningsClass));
BigDecimal salaryAmt = new BigDecimal(salary);
BigDecimal annualSalary = numPayChecks.multiply(salaryAmt);
return annualSalary.toString();
}
return null;
}

public static int getYearlyPaychecks(String earningsClass) {
String[] year = { "YEAR", "YEARLY", "ANNUAL", "ANNUALLY" };
String[] ten_per_year = { "TEN PER YEAR" };
String[] month = { "MONTH", "MONTHLY" };
String[] sixteen_per_year = { "SIXTEEN PER YEAR" };
String[] twentyone_per_year = { "TWENTYONE PER YEAR" };
String[] halfmonth = { "HALF MONTH", "HALF MONTHLY" };
String[] twoweek = { "TWO WEEKS" };
String[] four_per_month = { "FOUR PER MONTH" };
String[] week = { "WEEK", "WEEKLY" };
String[] hour = { "HOUR", "HOURLY" };

if ((earningsClass == null)
|| (Arrays.asList(year).contains(earningsClass)))
return 1;
if (Arrays.asList(hour).contains(earningsClass))
return 2080;
if (Arrays.asList(week).contains(earningsClass))
return 52;
if (Arrays.asList(four_per_month).contains(earningsClass))
return 48;
if (Arrays.asList(twoweek).contains(earningsClass))
return 26;
if (Arrays.asList(halfmonth).contains(earningsClass))
return 24;
if (Arrays.asList(twentyone_per_year).contains(earningsClass))
return 21;
if (Arrays.asList(sixteen_per_year).contains(earningsClass))
return 16;
if (Arrays.asList(month).contains(earningsClass))
return 12;
if (Arrays.asList(ten_per_year).contains(earningsClass)) {
return 10;
}
return 1;
}

public static Identifier findIdentifierByName(List<Identifier> identifiers,
String identifierName, IdentifierType identifierType) {
if ((identifiers != null) && (identifierName != null)
&& (identifierType != null)) {
for (Identifier identifier : identifiers) {
if ((getTransitoryElementAsString(identifier.getName(), "")
.equalsIgnoreCase(identifierName))
&& (identifier.getIdentifierType() == identifierType)) {
return identifier;
}
}
}

return null;
}

public static Identifier findIdentifierByTypeClassification(
List<Identifier> identifiers, String identifierTypeClassification,
IdentifierType identifierType) {
if ((identifiers != null) && (identifierTypeClassification != null)
&& (identifierType != null)) {
for (Identifier identifier : identifiers) {
if ((identifierTypeClassification.equalsIgnoreCase(identifier
.getIdentifierTypeClassification()))
&& (identifier.getIdentifierType() == identifierType)) {
return identifier;
}
}
}

return null;
}

public static Identifier createCustomIdentifier(String identName,
String identValue) {
if ((identName != null) && (identValue != null)) {
Identifier ident = new Identifier();
ident.setIdentifierType(IdentifierType.CUSTOM);

TransitoryElement identifierTENameElement = generateTransitoryElement(
identName, null);
ident.setName(identifierTENameElement);

TransitoryElement identifierTEValue = generateTransitoryElement(
identValue, null);
ident.setValue(identifierTEValue);

return ident;
}

return null;
}

static {
dateFormatList.add("MMddyyyy");
dateFormatList.add("MM/dd/yyyy");
dateFormatList.add("MM-dd-yyyy");
dateFormatList.add("yyyyMMdd");
dateFormatList.add("yyyy-MM-dd");
dateFormatList.add("dd-MM-yy");
dateFormatList.add("yyyyMMdd_hhmmssSSS");
dateFormatList.add("yyyyMMddhhmmssss");
dateFormatList.add("yyyyMMddhhmmss");
dateFormatList.add("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
dateFormatList.add("dd-MMM-yy hh.mm.ss.SSS a");
}
}

EDIUTIL.java

/*
 * EDIUtil.java 2/23/15 12:11 PM jcain
 *
 * Copyright(c) 2000 - 2015 by Benefitfocus.com, Inc., All Rights Reserved
 */

package com.benefitfocus.edi.outbound.util;

import bf.lang.StringUtil;
import com.benefitfocus.edi.EDIException;
import com.benefitfocus.edi.comparator.BenefitAgeComparator;
import com.benefitfocus.edi.comparator.ParticipationPeriodComparator;
import com.benefitfocus.edi.comparator.SubscriberFirstComparator;
import com.benefitfocus.edi.outbound.EDIOutboundManager;
import com.benefitfocus.edi.outbound.constants.*;
import com.benefitfocus.edi.outbound.core.*;
import com.benefitfocus.edi.outbound.core.dao.data.SponsorDestinationPlan;
import com.benefitfocus.edi.outbound.util.ParticipationPeriodUtil.ParticipationPeriodType;
import com.benefitfocus.edi.outbound.util.comparator.AddressComparator;
import com.benefitfocus.transactionhistory.common.comparator.match.BFEnrollmentPersonComparator;
import com.benefitfocus.transactionhistory.common.util.TransactionHistoryDataUtil;
import com.benefitfocus.transactionhistory.extractinfo.BenefitInfo;
import com.benefitfocus.transactionhistory.extractinfo.ExtractInformation;
import com.benefitfocus.transactionhistory.extractinfo.SentInfo;
import com.benefitfocus.transactionhistory.extractinfo.SentPlanInfo;
import com.benefitfocus.transactionhistory.snapshotdata.*;
import com.benefitfocus.transactionhistory.snapshotdata.BFEnrollmentPerson.Benefits;
import com.benefitfocus.transactionhistory.transaction.TransactionInformation;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import javax.jms.*;
import java.text.ParseException;
import java.util.*;
import java.util.Map.Entry;

//import org.apache.xpath.operations.String;

public final class EDIUtil {
    private static Logger logger = Logger.getLogger(EDIUtil.class);

    private static List<SubscriberTypeEnum> nonACAOnlySubscriberTypeList = Arrays.asList(
            SubscriberTypeEnum.FULLY_MANAGED__SUBSCRIBER,
            SubscriberTypeEnum.FULLY_MANAGED__DEPENDENT
    );

    private static List<SubscriberTypeEnum> acaOnlySubscriberTypeList = Arrays.asList(
            SubscriberTypeEnum.EXTERNALLY_MANAGED__ACA_ONLY__SUBSCRIBER,
            SubscriberTypeEnum.EXTERNALLY_MANAGED__ACA_ONLY__DEPENDENT
    );

    public static enum SortDirection {
        ASC,
        DESC
    }

    public static BFEnrollmentPerson getSubscriberFromSnapshotData(SnapshotData snapshotData, boolean useApprovedData) {
        if (snapshotData != null) {
            if (useApprovedData) {
                if (snapshotData.getLatestApprovedData() != null) {
                    return getSubscriberFromList(snapshotData.getLatestApprovedData().getPerson());
                }
            } else if (snapshotData.getLatestRequestedData() != null) {
                return getSubscriberFromList(snapshotData.getLatestRequestedData().getPerson());
            }
        }
        return null;
    }

    public static List<BFEnrollmentPerson> getDependentsFromSnapshotData(SnapshotData snapshotData, boolean useApprovedData) {
        if (snapshotData != null) {
            if (useApprovedData) {
                if (snapshotData.getLatestApprovedData() != null) {
                    return getDependentsFromList(snapshotData.getLatestApprovedData().getPerson());
                }
            } else if (snapshotData.getLatestRequestedData() != null) {
                return getDependentsFromList(snapshotData.getLatestRequestedData().getPerson());
            }
        }
        return null;
    }

    public static List<BFEnrollmentPerson> getFamilyFromSnapshotData(SnapshotData snapshotData, boolean useApprovedData) {
        if (snapshotData != null) {
            if (useApprovedData) {
                if (snapshotData.getLatestApprovedData() != null) {
                    return snapshotData.getLatestApprovedData().getPerson();
                }
            } else if (snapshotData.getLatestRequestedData() != null) {
                return snapshotData.getLatestRequestedData().getPerson();
            }
        }
        return null;
    }

    public static Set<String> getSSNsFromSnapshot(SnapshotData snapshotData) {
        Set<String> ssns= new HashSet<String>();

        if(!snapshotHasMembers(snapshotData)){
            return ssns;
        }

        for(BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()){
            if(TEIsNotEmpty(person.getSsn())){
                ssns.add(person.getSsn().getValue());
            }
        }

        return ssns;
    }

    public static boolean isSkipTransaction(SnapshotData snapshotData) {
        boolean isSkip = true;
        if (snapshotData != null && snapshotData.getLatestRequestedData().getPerson() != null) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (person.getEdiTransaction() != null && StringUtil.isNotEmpty(person.getEdiTransaction())
                        && !EdiTransactionConstants.isSkipTransaction(person.getEdiTransaction())
                        //Pends are skips which we don't want to historize
                        && !EdiTransactionConstants.isPendTransaction(person.getEdiTransaction())) {
                    isSkip = false;
                    break;
                }
            }
        }

        return isSkip;
    }
 
    public static boolean isPersonSkipTransaction(BFEnrollmentPerson person) {
    boolean isSkip = true;
    if (person != null && person.getEdiTransaction() != null && StringUtil.isNotEmpty(person.getEdiTransaction())  && !EdiTransactionConstants.isSkipTransaction(person.getEdiTransaction()) && !EdiTransactionConstants.isPendTransaction(person.getEdiTransaction())) {
    isSkip = false;
    }

    return isSkip;
    }
 
    public static boolean isBenefitSkipTransaction(BenefitRecord benefit) {
    boolean isSkip = true;
    if (benefit != null && benefit.getEdiTransaction() != null && StringUtil.isNotEmpty(benefit.getEdiTransaction())  && !EdiTransactionConstants.isSkipTransaction(benefit.getEdiTransaction()) && !EdiTransactionConstants.isPendTransaction(benefit.getEdiTransaction())) {
    isSkip = false;
    }

    return isSkip;
    }

    public static boolean hasPendingTransaction(SnapshotData snapshotData) {
        boolean hasPendingTransaction = false;
        if (EDIUtil.snapshotHasMembers(snapshotData)) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (hasPendingTransaction) {
                    break;
                }
                if (EdiTransactionConstants.isValidEDITransaction(person.getEdiTransaction()) && EdiTransactionConstants.isPendTransaction(person.getEdiTransaction())) {
                    hasPendingTransaction = true;
                    break;
                } else if (EDIUtil.enrollmentPersonHasBenefits(person)) {
                    for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                        if (EdiTransactionConstants.isPendTransaction(benefit.getEdiTransaction())) {
                            hasPendingTransaction = true;
                            break;
                        }
                    }
                }
            }
        }

        return hasPendingTransaction;
    }

    public static boolean hasValidTransactions(SnapshotData snapshotData) {
        boolean hasValidTransaction = true;
        if (EDIUtil.snapshotHasMembers(snapshotData)) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (!hasValidTransaction) {
                    break;
                }
                if (!EdiTransactionConstants.isValidEDITransaction(person.getEdiTransaction())) {
                    logger.debug("Person " + person.getReferenceId() + " has invalid person transaction: " + person.getEdiTransaction());
                    hasValidTransaction = false;
                    break;
                } else if (EDIUtil.enrollmentPersonHasBenefits(person)) {
                    for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                        if (!EdiTransactionConstants.isValidEDITransaction(benefit.getEdiTransaction())) {
                            logger.debug("Person " + person.getReferenceId() + " has invalid benefit transaction: " + benefit.getEdiTransaction() + " benefit-type: " + benefit.getBenefitType());
                            hasValidTransaction = false;
                            break;
                        }
                    }
                }
            }
        } else {
            logger.debug("Snapshot has no members with benefits");
            hasValidTransaction = false;
        }

        return hasValidTransaction;
    }

    public static boolean isErrorTransaction(SnapshotData snapshotData) {
        boolean isError = false;
        if (snapshotData != null && snapshotData.getLatestRequestedData().getPerson() != null) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (person.getEdiTransaction() != null && StringUtil.isNotEmpty(person.getEdiTransaction()) && EdiTransactionConstants.isErrorTransaction(person.getEdiTransaction())) {
                    isError = true;
                    break;
                }
            }
        }

        return isError;
    }

    public static boolean isDropAddTransaction(SnapshotData snapshotData) {
        boolean isDropAdd = false;
        if (snapshotData != null && snapshotData.getLatestRequestedData().getPerson() != null) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (isDropAddTransaction(person)) {
                    isDropAdd = true;
                    break;
                }
            }
        }

        return isDropAdd;
    }

    public static boolean isDropAddTransaction(BFEnrollmentPerson person) {
        boolean isDropAdd = false;
        if (person != null) {
            if (person.getEdiTransaction() != null && StringUtil.isNotEmpty(person.getEdiTransaction()) && EdiTransactionConstants.isDropAddTransaction(person.getEdiTransaction())) {
                isDropAdd = true;
            } else if (person.getBenefits() != null) {
                for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                    if (isDropAddTransaction(benefit)) {
                        isDropAdd = true;
                        break;
                    }
                }
            }
        }
        return isDropAdd;
    }

    public static boolean isDropAddTransaction(BenefitRecord benefit) {
        boolean isDropAdd = false;
        if (benefit != null) {
            if (benefit.getEdiTransaction() != null && StringUtil.isNotEmpty(benefit.getEdiTransaction()) && EdiTransactionConstants.isDropAddTransaction(benefit.getEdiTransaction())) {
                isDropAdd = true;
            }
        }
        return isDropAdd;
    }
    // New logic to support Add Drop transactions for members and benefits
    public static boolean isAddDropTransaction(SnapshotData snapshotData) {
    boolean isAddDrop = false;
         if (snapshotData != null && snapshotData.getLatestRequestedData().getPerson() != null) {
             for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                 if (isAddDropTransaction(person)) {
                isAddDrop = true;
                     break;
                 }
             }
         }

         return isAddDrop;
    }
    public static boolean isAddDropTransaction(BFEnrollmentPerson person) {
    boolean isAddDrop = false;
         if (person != null) {
             if (person.getEdiTransaction() != null && StringUtil.isNotEmpty(person.getEdiTransaction()) && EdiTransactionConstants.isAddDropTransaction(person.getEdiTransaction())) {
            isAddDrop = true;
             } else if (person.getBenefits() != null) {
                 for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                     if (isAddDropTransaction(benefit)) {
                    isAddDrop = true;
                         break;
                     }
                 }
             }
         }
         return isAddDrop;
    }
 
    public static boolean isAddDropTransaction(BenefitRecord benefit) {
    boolean isAddDrop = false;
         if (benefit != null) {
             if (benefit.getEdiTransaction() != null && StringUtil.isNotEmpty(benefit.getEdiTransaction()) && EdiTransactionConstants.isAddDropTransaction(benefit.getEdiTransaction())) {
            isAddDrop = true;
             }
         }
         return isAddDrop;
    }
    // End of changes for Add Drop transaction

    public static BFEnrollmentPerson getSubscriberFromSnapshotData(SnapshotData snapshotData, String subscriberOID) {
        BFEnrollmentPerson subscriber = null;
        if (snapshotData != null) {
            if (snapshotData.getLatestRequestedData() != null && snapshotData.getLatestRequestedData().getPerson() != null) {
                for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                    if (person.getReferenceId().equals(subscriberOID)) {
                        subscriber = person;
                        break;
                    }
                }
            }
        }
        return subscriber;
    }

    public static List<BFEnrollmentPerson> getPersonsFromSnapshotData(SnapshotData snapshotData, boolean useApprovedData) {
        if (snapshotData != null) {
            if (useApprovedData) {
                if (snapshotData.getLatestApprovedData() != null) {
                    return snapshotData.getLatestApprovedData().getPerson();
                }
            } else if (snapshotData.getLatestRequestedData() != null) {
                return snapshotData.getLatestRequestedData().getPerson();
            }
        }
        return null;
    }

    public static boolean enrollmentPersonHasBenefits(BFEnrollmentPerson enrollmentPerson) {
        if (enrollmentPerson != null && enrollmentPerson.getBenefits() != null && !enrollmentPerson.getBenefits().getBenefitRecord().isEmpty()) {
            return true;
        }

        return false;
    }

    public static boolean snapshotHasMembers(SnapshotData snapshotdata) {
        if (snapshotdata != null && snapshotdata.getLatestRequestedData() != null && !snapshotdata.getLatestRequestedData().getPerson().isEmpty()) {
            return true;
        }

        return false;
    }

    public static boolean snapshotHasSomeMemberWithBenefits(SnapshotData snapshotdata) {
        if (snapshotHasMembers(snapshotdata)) {
            boolean someMemberHasBenefit = false;
            for (BFEnrollmentPerson enrolledPerson : snapshotdata.getLatestRequestedData().getPerson()) {
                if (enrollmentPersonHasBenefits(enrolledPerson)) {
                    someMemberHasBenefit = true;
                }
            }
            return someMemberHasBenefit;
        }

        return false;
    }

    public static void removeMemberFromSnapshotWithNoBenefits(SnapshotData snapshotData) {
        if (snapshotData != null && snapshotHasMembers(snapshotData)) {
            Iterator<BFEnrollmentPerson> enrollmentPersonIterator = snapshotData.getLatestRequestedData().getPerson().iterator();
            while (enrollmentPersonIterator.hasNext()) {
                if (!enrollmentPersonHasBenefits(enrollmentPersonIterator.next())) {
                    enrollmentPersonIterator.remove();
                }
            }
        }
    }

    public static boolean reasonCodeListContainsAnyReasonCodeInSearchList(List<ReasonCode> memberOrBenefitReasonCodeList, String[] reasonCodesToSearch) {
        if (memberOrBenefitReasonCodeList == null || memberOrBenefitReasonCodeList.isEmpty() || reasonCodesToSearch == null || reasonCodesToSearch.length == 0) {
            return false;
        }

        List<String> memberOrBenefitReasonCodeStrList = getReasonCodesAsStringList(memberOrBenefitReasonCodeList);

        for (String reasonCodeToSearch : reasonCodesToSearch) {
            if (memberOrBenefitReasonCodeStrList.contains(reasonCodeToSearch)) {
                return true;
            }
        }

        return false;
    }

    public static List<String> getReasonCodesAsStringList(List<ReasonCode> reasonCodeList) {
        List<String> reasonCodeStringList = new ArrayList<String>();

        if (reasonCodeList != null) {
            for (ReasonCode rc : reasonCodeList) {
                reasonCodeStringList.add(rc.getValue());
            }
        }

        return reasonCodeStringList;
    }

    public static Map<String, BFEnrollmentPerson> getPersonsFromSnapshotDataAsMap(SnapshotData snapshotData, boolean useApprovedData) {
        Map<String, BFEnrollmentPerson> memberMap = null;

        if (snapshotData != null) {
            if (useApprovedData) {
                if (snapshotData.getLatestApprovedData() != null) {
                    memberMap = new HashMap<String, BFEnrollmentPerson>();

                    for (BFEnrollmentPerson member : snapshotData.getLatestApprovedData().getPerson()) {
                        memberMap.put(member.getReferenceId(), member);
                    }
                }
            } else if (snapshotData.getLatestRequestedData() != null) {
                memberMap = new HashMap<String, BFEnrollmentPerson>();

                for (BFEnrollmentPerson member : snapshotData.getLatestRequestedData().getPerson()) {
                    memberMap.put(member.getReferenceId(), member);
                }
            }
        }

        return memberMap;
    }

    public static BFEnrollmentPerson getSubscriberFromList(List<BFEnrollmentPerson> bfEnrollmentPersonList) {
        BFEnrollmentPerson subscriber = null;
        if (bfEnrollmentPersonList != null && !bfEnrollmentPersonList.isEmpty()) {
            for (BFEnrollmentPerson person : bfEnrollmentPersonList) {
                if (person.getSubscriberOid() == null) {
                    subscriber = person;
                    break;
                }
            }
        }
        return subscriber;
    }

    public static List<BFEnrollmentPerson> getDependentsFromList(List<BFEnrollmentPerson> bfEnrollmentPersonList) {
        Predicate predicate = new Predicate() {
            @Override
            public boolean evaluate(Object object) {
                BFEnrollmentPerson person = (BFEnrollmentPerson) object;
                if (person.getSubscriberOid() != null) {
                    return true;
                }
                return false;
            }
        };
        List<BFEnrollmentPerson> dependents = new ArrayList<BFEnrollmentPerson>();
        CollectionUtils.select(bfEnrollmentPersonList, predicate, dependents);

        return dependents;
    }

    public static List<BenefitRecord> getBenefitByBenefitType(BFEnrollmentPerson person, String benefitType) {
        List<BenefitRecord> benefit = new ArrayList<BenefitRecord>();
        if (person != null && person.getBenefits() != null && !person.getBenefits().getBenefitRecord().isEmpty()) {
            for (BenefitRecord benefitRecord : person.getBenefits().getBenefitRecord()) {
                if (benefitRecord.getBenefitType()!=null && benefitRecord.getBenefitType().equals(benefitType)) {
                    benefit.add(benefitRecord);
                }
            }
        }
        return benefit;
    }

    public static void forceSubscriberToBeFirstMember(List<BFEnrollmentPerson> memberList) {
        if (memberList != null && !memberList.isEmpty()) {
            Collections.sort(memberList, new SubscriberFirstComparator());
        }
    }

    public static void sortBenefitsByParticipationPeriod(List<BenefitRecord> benefits, SortDirection direction) {
        if (direction == null) {
            direction = SortDirection.ASC;
        }
        if (benefits != null && !benefits.isEmpty()) {
            Collections.sort(benefits, new ParticipationPeriodComparator());
            if (SortDirection.DESC.equals(direction)) {
                Collections.reverse(benefits);
            }
        }
    }

    public static TransitoryElement generateTransitoryElement(String value, String previousValue) {
        TransitoryElement te = new TransitoryElement();
        te.setValue(value);
        if (previousValue != null) {
            te.setPrevious(previousValue);
        }
        return te;
    }

    public static SnapshotData filterByPlan(SnapshotData snapshotData, Map<String, SponsorDestinationPlan> planIdMap) {
        if (snapshotData != null) {
            if (planIdMap != null && !planIdMap.isEmpty()) {
                if (snapshotData.getLatestRequestedData() != null && !snapshotData.getLatestRequestedData().getPerson().isEmpty()) {
                    Iterator<BFEnrollmentPerson> personIterator = snapshotData.getLatestRequestedData().getPerson().iterator();
                    while (personIterator.hasNext()) {
                        BFEnrollmentPerson person = personIterator.next();
                        if (person.getBenefits() != null && person.getBenefits().getBenefitRecord() != null) {
                            Iterator<BenefitRecord> benefitIterator = person.getBenefits().getBenefitRecord().iterator();
                            while (benefitIterator.hasNext()) {
                                BenefitRecord benefit = benefitIterator.next();
                                String sponsorProductReferenceId = benefit.getSponsorProductReferenceId() == null ? "" : benefit.getSponsorProductReferenceId().getValue();
                                SponsorDestinationPlan sponsorDestinationPlan = planIdMap.get(sponsorProductReferenceId);
                                if (sponsorDestinationPlan == null || !sponsorDestinationPlan.isEdiEnabled()) {
                                    benefitIterator.remove();
                                }
                            }
                        }
                    }
                    if (snapshotData.getLatestRequestedData().getPerson().isEmpty()) {
                        snapshotData = null;
                    }
                } else {
                    snapshotData = null;
                }
            }
        }

        return snapshotData;
    }

    public static boolean snapshotContainsDisabledProducts(SnapshotData snapshotData, Map<String, SponsorDestinationPlan> planIdMap) {
        if (snapshotData != null && EDIUtil.snapshotHasMembers(snapshotData) && planIdMap != null && !planIdMap.isEmpty()) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (EDIUtil.enrollmentPersonHasBenefits(person)) {
                    for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                        String sponsorProductReferenceId = benefit.getSponsorProductReferenceId() == null ? "" : benefit.getSponsorProductReferenceId().getValue();
                        SponsorDestinationPlan sponsorDestinationPlan = planIdMap.get(sponsorProductReferenceId);
                        if (sponsorDestinationPlan != null && !sponsorDestinationPlan.isEdiEnabled()) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * Generates a map from the person oids to a map of benefits based on the comparator key for all members in the latestRequested data
     *
     * @param transactionInformation - transaction information to build map from
     * @return - map from person reference ids to benefit maps
     */
    public static Map<String, Map<String, BenefitRecord>> generatePersonOidToBenefitMapMap(TransactionInformation transactionInformation, Transformer<BenefitRecord,String> benefitKeyTransformer) {
        HashMap<String, Map<String, BenefitRecord>> map = new HashMap<String, Map<String, BenefitRecord>>();

        if (transactionInformation == null) {
            return map;
        }

        List<BFEnrollmentPerson> people = EDIUtil.getPersonsFromSnapshotData(transactionInformation.getSnapshotData(), false);
        if (people == null) {
            return map;
        }

        for (BFEnrollmentPerson person : people) {
            map.put(person.getReferenceId(), generateBenefitMap(person, benefitKeyTransformer));
        }

        return map;
    }

    /**
     * Generated a map of all benefits on the person using the BenefitComparator to create the keys
     *
     * @param person - person to create map for
     * @return map from benefitComparator keys to benefits
     */
    public static Map<String,BenefitRecord> generateBenefitMap(BFEnrollmentPerson person, Transformer<BenefitRecord,String> benefitKeyTransformer){

        HashMap<String, BenefitRecord> map = new HashMap<String, BenefitRecord>();
        if(person == null || person.getBenefits() == null){
            return map;
        }

        for(BenefitRecord benefit : person.getBenefits().getBenefitRecord()){
           map.put(benefitKeyTransformer.transform(benefit), benefit);
        }

        return map;
    }


    public static void removeAllPreviousExceptMostCurrentPrevious(List<TransactionInformation> transactionInformationList) {
        for (TransactionInformation transactionInformation : transactionInformationList) {
            if (transactionInformation != null) {
                removeAllPreviousExceptMostCurrentPrevious(transactionInformation.getSnapshotData());
            }
        }
    }

    public static void removeAllPreviousExceptMostCurrentPrevious(TransactionInformation transactionInformation) {
        if (transactionInformation != null) {
            removeAllPreviousExceptMostCurrentPrevious(transactionInformation.getSnapshotData());
        }
    }

    public static void removeAllPreviousExceptMostCurrentPrevious(SnapshotData snapshotData) {
        if (snapshotData != null && snapshotData.getLatestRequestedData() != null) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                removeAllPreviousExceptMostCurrentPrevious(person);
            }
        }
    }

    public static void removeAllPreviousExceptMostCurrentPrevious(BFEnrollmentPerson person) {
        if (person.getBenefits() == null) {
            return;
        }
        //Map of benefits in the previous participation period stored by benefitType
        Map<String, BenefitRecord> latestPrevPPBenefitsByIdentificationKey = new HashMap<String, BenefitRecord>();

       //find one benefit from most recent prev PP for each benefitType. (may have duplicates but only need one)
        for(BenefitRecord benefit: person.getBenefits().getBenefitRecord()){
            if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getParticipationPeriod())
                    && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getParticipationPeriodStartDate())
                    && EDIConstants.PERIOD_PREV.equals(benefit.getParticipationPeriod().getValue())) {

                String key = generatePPTypeBenTypeKey(benefit);

                //check if latest previous period so far
                BenefitRecord currentLatest = latestPrevPPBenefitsByIdentificationKey.get(key);
                try {
                    if (currentLatest == null ||
                            TransactionHistoryDataUtil.after(benefit.getParticipationPeriodStartDate(),
                                    currentLatest.getParticipationPeriodStartDate(), TransactionHistoryDataUtil.FORMAT_DATETIME_ISO)) {
                        latestPrevPPBenefitsByIdentificationKey.put(key, benefit);
                    }
                } catch (ParseException e) {
                    throw new EDIException("Error parsing PP dates for benefit " + benefit.getReferenceId(), e);
                }
            }
        }

        //remove all prev benefits with different start dates (not the latest)
        Iterator<BenefitRecord> benefitIterator  = person.getBenefits().getBenefitRecord().iterator();
        while(benefitIterator.hasNext()){
            BenefitRecord benefit = benefitIterator.next();

            if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getParticipationPeriod())
                    && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getParticipationPeriodStartDate())
                    && EDIConstants.PERIOD_PREV.equals(benefit.getParticipationPeriod().getValue())) {

                String key = generatePPTypeBenTypeKey(benefit);
                BenefitRecord latestPrev = latestPrevPPBenefitsByIdentificationKey.get(key);

                //go by PPStartDate and not benefitRecord match, since there may still be duplicates at this point.
                if (!benefit.getParticipationPeriodStartDate().getValue().equals(latestPrev.getParticipationPeriodStartDate().getValue())) {
                    benefitIterator.remove();
                }
            }
        }
    }

    private static String generatePPTypeBenTypeKey(BenefitRecord benefit) {
        return benefit.getBenefitType() + benefit.getParticipationPeriod().getValue();
    }

    public static void sendAMQData(EDIStatus ediStatus, String messageBrokerUrl, String eventQueue, String alertsHandler, String endpoint, String processId, String environment, String sourceSystem, String ediMode) throws JMSException {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL(messageBrokerUrl);
        Connection connection = factory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(eventQueue);
        MessageProducer producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        TextMessage message = session.createTextMessage();
        message.setStringProperty("alerts_DOT_handler", alertsHandler); //DO NOT CHANGE THE KEY from "alerts_DOT_handler". EM doesn't like the "."[dot]
        message.setStringProperty(JobContextConstants.endpoint, endpoint);
        message.setStringProperty(JobContextConstants.ediStatus, ediStatus.getStatus().name());
        message.setStringProperty(OutboundConstants.PROCESSID, processId);
        message.setStringProperty(OutboundConstants.ENVIRONMENT, environment);
        message.setStringProperty(OutboundConstants.SOURCE_SYSTEM_ID_VAL, sourceSystem);
        message.setStringProperty(OutboundConstants.EDI_SOURCE_MODE_VAL, ediMode);
        message.setText(ediStatus.getMessage());

        producer.send(message);

        session.close();
        connection.close();

    }

    public static boolean isAddTerm(BenefitRecord benefit) throws Exception {
        boolean benefitIsAddTerm = false;

        //if queue record exists and it is cancelled and benefit has gap in coverage, then:
        if (benefit.getRefusedIndicator() != null && benefit.getRefusedIndicator().getValue() != null && benefit.getRefusedIndicator().getValue().equalsIgnoreCase("true")
                && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEffectiveDate())
                && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEndDate())
                && getGapBetweenDates(benefit.getCoverageEffectiveDate().getValue(), benefit.getCoverageEndDate().getValue()) > 0) {

            //...it is add-term, if benefit has no history
            if (EntityActionType.CREATE.equals(benefit.getEntityActionType()) && StringUtil.isEmpty(benefit.getRefusedIndicator().getPrevious())) {
                benefitIsAddTerm = true;
            }
        }

        return benefitIsAddTerm;
    }

    public static boolean hadCoverage(BenefitRecord benefit) throws ParseException {

        if(TEIsEmpty(benefit.getCoverageEffectiveDate()) ) {
            return false; //refusal
        }else {
            Date effDate = DateConverter.getInstance(benefit.getCoverageEffectiveDate().getValue()).getDate();

            if(TEIsEmpty(benefit.getCoverageEndDate())){
                return true;
            }else {
                Date endDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefit.getCoverageEndDate().getValue());
                return endDate.after(effDate);
            }
        }
    }

    /**
     * Return the number of years between date1 - date2
     * @param date1 - date to subtract from in ISO format
     * @param date2 - date to subtract in ISO format
     * @return years of date1 - date2
     */
    public static Integer getYearsBetweenDates(String date1, String date2) throws ParseException {
        return getYearsBetweenDates(date1,date2,TransactionHistoryDataUtil.FORMAT_DATETIME_ISO);
    }

    /**
     * Return the number of years between date1 - date2
     * @param date1 - date to subtract from
     * @param date2 - date to subtract
     * @param format - format the dates are in
     * @return years of date1 - date2
     */
    public static Integer getYearsBetweenDates(String date1, String date2, String format) throws ParseException {
        if(date1 == null || date2 == null){
            return null;
        }

        Date d1 = DateConverter.getInstance(date1, format).getDate();
        Date d2 = DateConverter.getInstance(date2, format).getDate();
        return getYearsBetweenDates(d1,d2);
    }

    /**
     * Return the number of years between date1 - date2
     * @param date1 - date to subtract from
     * @param date2 - date to subtract by
     * @return years of date1 - date2
     */
    public static Integer getYearsBetweenDates(Date date1, Date date2){
        if(date1 == null || date2 == null){
            return null;
        }

        Calendar cal1 = getCalendar(date1);
        Calendar cal2 = getCalendar(date2);

        int diffYears = cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);
        int diffMonth = (cal1.get(Calendar.MONTH) - cal2.get(Calendar.MONTH));
        int diffDays = cal1.get(Calendar.DAY_OF_MONTH) - cal2.get(Calendar.DAY_OF_MONTH);

        if(diffYears != 0){
            //check if last year difference was a full year
            int lastYearAdjustemnt = 0;
            if(diffMonth != 0){
                lastYearAdjustemnt = diffMonth;
            }else if(diffDays != 0){
                lastYearAdjustemnt = diffDays;
            }
            if(diffYears > 0 && lastYearAdjustemnt < 0){
                diffYears --;
            }else if (diffYears < 0 && lastYearAdjustemnt > 0){
                diffYears ++;
            }
        }

        return diffYears;
    }


    public static Calendar getCalendar(Date date){
        //make sure we give the date back in GMT time to avoid adjusting the date due to time zone differences
        //GMT is the time zone for all date from eEnrollment on the snapshots
        TimeZone zone = TimeZone.getTimeZone("GMT");
        Calendar cal = Calendar.getInstance(zone);
        cal.setTime(date);
        return cal;
    }

    /**
     * This method returns the difference in days between two dates by taking into account the timestamp.
     *
     * @param dateOneStr first date value as string
     * @param dateTwoStr second date value as string
     * @return 0 if both dates are the same day, negative value if dateOneStr is after dateTwoStr, positive value if dateTwoStr is after dateOneStr
     * @throws Exception
     */
    public static Integer getGapBetweenDates(String dateOneStr, String dateTwoStr) throws Exception {
        Date dateOne = null;
        Date dateTwo = null;
        Integer daysDifferentBetweenDates = 0;

        if (!StringUtil.isEmpty(dateOneStr)) {
            dateOne = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, dateOneStr);
        }

        if (!StringUtil.isEmpty(dateTwoStr)) {
            dateTwo = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, dateTwoStr);
        }

        if (dateOne != null && dateTwo != null) {
            daysDifferentBetweenDates = TransactionHistoryDataUtil.daysDifferentBetweenDates(dateOne, dateTwo);
        }

        return daysDifferentBetweenDates;
    }

    /**
     * This method returns the difference in days between two dates after zeroing the timestamps on both dates.
     *
     * @param dateOneStr first date value as string
     * @param dateTwoStr second date value as string
     * @return 0 if both dates are the same day, negative value if dateOneStr is after dateTwoStr, positive value if dateTwoStr is after dateOneStr
     * @throws Exception
     */

    public static Integer getGapBetweenDatesWithZeroedTimestamp(String dateOneStr, String dateTwoStr) throws Exception {
        Date dateOne = null;
        Date dateTwo = null;
        Integer daysDifferentBetweenDates = 0;

        if (!StringUtil.isEmpty(dateOneStr)) {
            dateOne = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, dateOneStr);
        }

        if (!StringUtil.isEmpty(dateTwoStr)) {
            dateTwo = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, dateTwoStr);
        }

        if (dateOne != null && dateTwo != null) {
            Date zeroedDateOne = TransactionHistoryDataUtil.zero(dateOne);
            Date zeroedDateTwo = TransactionHistoryDataUtil.zero(dateTwo);
            daysDifferentBetweenDates = TransactionHistoryDataUtil.daysDifferentBetweenDates(zeroedDateOne, zeroedDateTwo);
        }

        return daysDifferentBetweenDates;
    }

    public static boolean benefitHasSameStartAndEndDates(BenefitRecord benefit) throws Exception {
        return TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEffectiveDate()) &&
                TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEndDate()) &&
                getGapBetweenDates(benefit.getCoverageEffectiveDate().getValue(), benefit.getCoverageEndDate().getValue()) == 0;
    }

    /**
     * This method checks if last-sent state of a benefit was a cancellation. The benefit could currently be active (so it's a reinstate)
     * or still in a cancelled state. This is mainly intended for CUP & TUP reason-code rules. One of the checks for CUPs & TUPs is to
     * check if member had coverage (gap in eff-date and end-date is atleast one day) on benefit.
     *
     * @param benefit a benefit-record that is
     * @return true if last-sent state of benefit is a cancellation, false if it's either a refusal or it was in a active state
     * @throws Exception
     */
    public static boolean lastSentStateOfBenefitIsCancellation(BenefitRecord benefit) throws Exception {
        Date effDate = null;
        Date endDate = null;
        Integer daysDifferentBetweenDates = 0;
        //no need to check if current value of refusedIndicator is false because previous value will only be added if it's different from current value
        //and for refusedIndicator if previous value is true then current value has to be false.
        boolean benefitWasPreviouslyInactive = !StringUtil.isEmpty(benefit.getRefusedIndicator().getPrevious()) && benefit.getRefusedIndicator().getPrevious().equals("true");
        boolean benefitIsInactive = !StringUtil.isEmpty(benefit.getRefusedIndicator().getValue()) && benefit.getRefusedIndicator().getValue().equals("true") && StringUtil.isEmpty(benefit.getRefusedIndicator().getPrevious());

        //if benefit was or still is in an inactive state then check if there is a gap between previous eff-date and end-dates.
        // If these dates are changing then check the previous values, otherwise compare the current values of these dates.
        if (benefitWasPreviouslyInactive || benefitIsInactive) {
            //since we are checking if the benefit had coverage, we should compare the previous values of eff-date and end-date incase either of the dates or both dates are changing
            if (benefit.getCoverageEffectiveDate() != null && !StringUtil.isEmpty(benefit.getCoverageEffectiveDate().getPrevious())) {
                effDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefit.getCoverageEffectiveDate().getPrevious());

            } else if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEffectiveDate())) {
                effDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefit.getCoverageEffectiveDate().getValue());
            }

            if (benefit.getCoverageEndDate() != null && !StringUtil.isEmpty(benefit.getCoverageEndDate().getPrevious())) {
                endDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefit.getCoverageEndDate().getPrevious());

            } else if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getCoverageEndDate())) {
                endDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefit.getCoverageEndDate().getValue());
            }

            if (effDate != null && endDate != null) {
                daysDifferentBetweenDates = TransactionHistoryDataUtil.daysDifferentBetweenDates(effDate, endDate);
            }

            return (daysDifferentBetweenDates > 0);
        }

        return false;
    }


    public static void promoteBeneficiariesToEnrolledPerson(SnapshotData.LatestRequestedData latestRequestedData) throws EdiUtilityException {

        if (latestRequestedData.getPerson() == null || latestRequestedData.getPerson().size() == 0) return;

        HashMap<String, BFEnrollmentPerson> personMap = new HashMap<String, BFEnrollmentPerson>();
        BFEnrollmentPerson subscriber = null;

        //preload the personMap
        for (BFEnrollmentPerson person : latestRequestedData.getPerson()) {
            if (EdiTransitoryElement.isNullOrEmpty(person.getSsn())) continue;

            //check if subscriber
            if (!EdiTransitoryElement.isNullOrEmpty(person.getHireDate())) {
                subscriber = person;
            }

            setIsBeneficiary(false, person);

            if (person.getBenefits() == null)
                person.setBenefits(new Benefits());

            personMap.put(person.getSsn().getValue(), person);
        }

        if (subscriber == null
                || subscriber.getBenefits() == null
                || subscriber.getBenefits().getBenefitRecord() == null)
                    return;

        for (BenefitRecord benefitRecord : subscriber.getBenefits().getBenefitRecord()) {

            if (benefitRecord.getBeneficiaries() == null ) continue;

            List<BeneficiaryInformation.Beneficiary> beneficiaryList = benefitRecord.getBeneficiaries().getBeneficiary();

            if (beneficiaryList == null) continue;

            for (BeneficiaryInformation.Beneficiary beneficiary : beneficiaryList) {

                String beneficiaryIdValue = beneficiary.getType() !=null &&
                                                "TRUST".equals(beneficiary.getType().getValue()) ?
                                                    beneficiary.getBeneficiaryOid().getValue() :
                                                    beneficiary.getBeneficiaryID().getValue();

                if (beneficiaryIdValue == null
                        || subscriber.getSsn().getValue().equals(beneficiaryIdValue)) continue;

                boolean isNew = !personMap.containsKey(beneficiaryIdValue);

                BFEnrollmentPerson person = !isNew?
                                            personMap.get(beneficiaryIdValue) :
                                            createMemberDataFromBeneficiary(beneficiary, subscriber);

                person.getBenefits().getBenefitRecord().add(createBeneficiaryBenefitFromSubscriberBenefit(benefitRecord, beneficiary));

                setIsBeneficiary(true, person);

                if (isNew) {
                    // add to full person map so we include added member in next check
                    personMap.put(beneficiary.getBeneficiaryID().getValue(), person);

                    latestRequestedData.getPerson().add(person);
                }
            }
        }

    }



    private static BFEnrollmentPerson createMemberDataFromBeneficiary(final BeneficiaryInformation.Beneficiary  beneficiary, final BFEnrollmentPerson subscriber) {
        return new BFEnrollmentPerson() {{
            setReferenceGUID(beneficiary.getReferenceId());
            String ref = (beneficiary.getBeneficiaryOid() == null) ?
                            beneficiary.getBeneficiaryID().getValue() :
                            beneficiary.getBeneficiaryOid().getValue();

            setReferenceId(ref);
            setDefaultRelationship(beneficiary.getRelationship());
            TransitoryElement ssn =
                    TransactionHistoryDataUtil.isTransitoryElementValueEmptyOrNull(beneficiary.getBeneficiaryID()) ?
                            generateTransitoryElement(beneficiary.getBeneficiaryOid().getValue(),null) :
                            beneficiary.getBeneficiaryID();
            setSsn(ssn);
            setBirthDate(beneficiary.getBirthDate());
            setFirstName(beneficiary.getName());
            setAddress(beneficiary.getAddress());
            getAdditionalAddresses().addAll(beneficiary.getAdditionalAddresses());
            setEmailAddresses(beneficiary.getEmailAddresses());
            setPhoneNumbers(beneficiary.getPhoneNumbers());
            setFaxNumbers(beneficiary.getFaxNumbers());
            setEntityActionType(beneficiary.getEntityActionType());
            setSubscriberOid(generateTransitoryElement(subscriber.getReferenceId(), null));
            setEffectiveChangeDate(subscriber.getEffectiveChangeDate());
            getIdentifiers().addAll(subscriber.getIdentifiers());
            setBenefits(new BFEnrollmentPerson.Benefits());
            if (!TransactionHistoryDataUtil.isTransitoryElementValueEmptyOrNull(beneficiary.getRelationship()))
                setRelationship(beneficiary.getRelationship().getValue());
        }};
    }

    private static BenefitRecord createBeneficiaryBenefitFromSubscriberBenefit(BenefitRecord benefitRecord, BeneficiaryInformation.Beneficiary beneficiary) throws EdiUtilityException {
        //parent method has null checks
        BenefitRecord benefit = TransactionHistoryCloneUtil.copy(BenefitRecord.class, benefitRecord);
        TransactionHistoryDataUtil.addMetadataToMetadataList(benefit.getDxMetaData(), "IS_PROMOTED_BENEFIT", "true");

        if (benefit == null) return benefit;

        //Set coveredPerson Specific Data
        benefit.setRelationship(beneficiary.getRelationship());

        return benefit;
    }

    private static void setIsBeneficiary(Boolean isBeneficiary, BFEnrollmentPerson person) {
        String valueToSet = Boolean.FALSE.toString();

        if (isBeneficiary) {
            for (Metadata metadata : person.getDxMetaData()) {
                if (EDIConstants.METADATA_PROMOTE_BENEFICIARY.equalsIgnoreCase(metadata.getName())) {
                    if (metadata.getValue().equals(Boolean.FALSE.toString())) {
                        metadata.setValue("BOTH");
                    }
                    return;
                }
            }
            valueToSet = Boolean.TRUE.toString();
        }

        TransactionHistoryDataUtil.addMetadataToMetadataList(person.getDxMetaData(), EDIConstants.METADATA_PROMOTE_BENEFICIARY, valueToSet);
    }

    //    This method promotes all non existing coveredPerson to BFEnrollmentPerson with all covered benefits and adds all covered benefits to existing BFEnrollmentPersons
    public static void promoteCoveredPersonsToEnrolledPerson(SnapshotData.LatestRequestedData latestRequestedData) throws Exception {
        if (latestRequestedData.getPerson() != null && latestRequestedData.getPerson().size() > 0) {
            BFEnrollmentPerson subscriber = null;
            HashMap<String, BFEnrollmentPerson> personMap = new HashMap<String, BFEnrollmentPerson>();
            List<BFEnrollmentPerson> newPersonList = new ArrayList<BFEnrollmentPerson>();

            for (BFEnrollmentPerson person : latestRequestedData.getPerson()) {
                //check if subscriber
                if (!TransactionHistoryDataUtil.isTransitoryElementValueEmptyOrNull(person.getHireDate())) {
                    subscriber = person;
                }
                setIsCoveredPeson("FALSE", person);
                personMap.put(person.getReferenceId(), person);
            }

            if (subscriber != null && subscriber.getBenefits() != null && subscriber.getBenefits().getBenefitRecord() != null) {
                for (BenefitRecord benefitRecord : subscriber.getBenefits().getBenefitRecord()) {
                    if (benefitRecord.getCoveredPersons() != null && benefitRecord.getCoveredPersons().getCoveredPerson() != null) {
                        for (CoveredPerson coveredPerson : benefitRecord.getCoveredPersons().getCoveredPerson()) {
                       
                        System.out.println(coveredPerson.getPersonOid().getValue()+"   "+personMap.keySet());
                            //if subscriber is also covered-person then continue processing the next covered-person since
                            //this logic applies only for dependents.
                            if (coveredPerson.getPersonOid().getValue().equals(subscriber.getReferenceId())) {
                                continue;
                            }
                            //Check if member exists for covered person
                            if (coveredPerson.getPersonOid() != null && personMap.keySet().contains(coveredPerson.getPersonOid().getValue())) {
                                BFEnrollmentPerson enrollmentPersonForCoveredPerson = personMap.get(coveredPerson.getPersonOid().getValue());

                                if (enrollmentPersonForCoveredPerson.getBenefits() == null) {
                                    enrollmentPersonForCoveredPerson.setBenefits(new Benefits());
                                }
                                enrollmentPersonForCoveredPerson.getBenefits().getBenefitRecord().add(createCoveredPersonBenefitFromSubscriberBenefit(benefitRecord, coveredPerson));
                                System.out.println(coveredPerson.getPersonOid());
                                System.out.println(coveredPerson.getPersonOid());
                            }
                            else if (coveredPerson.getPersonOid() != null) {
                                BFEnrollmentPerson newPerson = createMemberDataFromCoveredPerson(coveredPerson, subscriber);
                                setIsCoveredPeson("TRUE", newPerson);
                                newPerson.getBenefits().getBenefitRecord().add(createCoveredPersonBenefitFromSubscriberBenefit(benefitRecord, coveredPerson));
                                personMap.put(coveredPerson.getPersonOid().getValue(), newPerson); // add to full person map so we include added member in next check
                                newPersonList.add(newPerson);
                            }
                        }
                    }
                }
                latestRequestedData.getPerson().addAll(newPersonList);
            }
        }
    }

    public static boolean isPersonPolicyOwnerButNotOriginatingSubscriberOnAnyBenefit(BFEnrollmentPerson person) {

        if (person != null && person.getBenefits() != null && person.getReferenceId() != null) {
            for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                if (!isPolicyOwnerTheOriginatingSubscriberBenefit(benefit, person.getReferenceId())) {
                    return true;
                }
            }
        }
        return false;

    }

    public static boolean isPolicyOwnerTheOriginatingSubscriberBenefit(BenefitRecord benefit, String personReferenceId) {
        boolean isOriginatingSubscriberBenefit = true;
        if (benefit != null && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getPolicyOwnerReferenceId())
                && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getOriginatingSubscriberReferenceId())
                && !benefit.getPolicyOwnerReferenceId().getValue().equals(benefit.getOriginatingSubscriberReferenceId().getValue())
                && benefit.getPolicyOwnerReferenceId().getValue().equals(personReferenceId)) {
            isOriginatingSubscriberBenefit = false;
        }
        return isOriginatingSubscriberBenefit;
    }

    public static boolean isPolicyOwnerOfAnyBenefitAndNotOriginatingSubscriber(List<BenefitRecord> benefits, String personReferenceId) {
        boolean isPolicyOwnerAndNotOriginalSubscriber = false;
        if (benefits != null && !benefits.isEmpty() && personReferenceId != null) {
            for (BenefitRecord benefit : benefits) {
                if (isPolicyOwnerOfTheBenefit(benefit, personReferenceId)) {
                    if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getOriginatingSubscriberReferenceId()) && !benefit.getOriginatingSubscriberReferenceId().getValue().equals(personReferenceId)) {
                        isPolicyOwnerAndNotOriginalSubscriber = true;
                        break;
                    }
                }
            }
        }
        return isPolicyOwnerAndNotOriginalSubscriber;
    }

    public static boolean isPolicyOwnerOfAnyBenefit(List<BenefitRecord> benefits, String personReferenceId) {
        boolean isPolicyOwnerofAnyBenefit = false;
        if (benefits != null && !benefits.isEmpty() && personReferenceId != null) {
            for (BenefitRecord benefit : benefits) {
                if (isPolicyOwnerOfTheBenefit(benefit, personReferenceId)) {
                    isPolicyOwnerofAnyBenefit = true;
                    break;
                }
            }
        }
        return isPolicyOwnerofAnyBenefit;
    }

    public static boolean isPolicyOwnerOfTheBenefit(BenefitRecord benefit, String personReferenceId) {
        boolean isPolicyOwnerofBenefit = false;
        if (benefit != null && TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefit.getPolicyOwnerReferenceId())
                && benefit.getPolicyOwnerReferenceId().getValue().equals(personReferenceId)) {
            isPolicyOwnerofBenefit = true;
        }
        return isPolicyOwnerofBenefit;
    }

    //We only want the first value set to prevent cases of a Promoted member going from True to False on finding another covered benefit in the list and then finding the new person in the personMap
    private static void setIsCoveredPeson(String value, BFEnrollmentPerson person) {
        Boolean hasMetaDataSet = false;
        for (Metadata metadata : person.getDxMetaData()) {
            if ("IS_PROMOTED_COVERED_PERSON".equalsIgnoreCase(metadata.getName())) {
                hasMetaDataSet = true;
            }
        }
        if (!hasMetaDataSet) {
            TransactionHistoryDataUtil.addMetadataToMetadataList(person.getDxMetaData(), "IS_PROMOTED_COVERED_PERSON", value);
        }
    }

    protected static BenefitRecord createCoveredPersonBenefitFromSubscriberBenefit(BenefitRecord subscriberBenefit, CoveredPerson coveredPerson) throws Exception {
//        parent method has null checks
        BenefitRecord benefit = TransactionHistoryCloneUtil.copy(BenefitRecord.class, subscriberBenefit);

        if (benefit != null) {
            //Set coveredPerson Specific Data
            TransactionHistoryDataUtil.addMetadataToMetadataList(benefit.getDxMetaData(), "IS_PROMOTED_BENEFIT", "true");
            if (coveredPerson.getRelationship() != null && coveredPerson.getRelationship().getValue() != null) {
                benefit.setRelationship(coveredPerson.getRelationship());
            } else {
                benefit.setRelationship(null);
            }
            benefit.setTobaccoUsage(coveredPerson.getTobaccoUsage());
            benefit.setCoveredPersons(null);

            //term using exp Date if refused
            if (coveredPerson.getRefusedIndicator() != null && Boolean.valueOf(coveredPerson.getRefusedIndicator().getValue())
                    && coveredPerson.getExpirationDate() != null) {
                benefit.setCoverageEndDate(TransactionHistoryDataUtil.generateTransitoryElement(coveredPerson.getExpirationDate().getValue(), null));
                benefit.setRefusedIndicator(TransactionHistoryDataUtil.generateTransitoryElement("true", null));
                benefit.setEnrollmentReasonCode(TransactionHistoryDataUtil.generateTransitoryElement("CANCELLED", null));
            }
        }
        return benefit;
    }

    private static BFEnrollmentPerson createMemberDataFromCoveredPerson(CoveredPerson coveredPerson, BFEnrollmentPerson subscriber) {
        BFEnrollmentPerson promotedMember = new BFEnrollmentPerson();
//      Data from Covered Person
        promotedMember.setReferenceGUID(coveredPerson.getPersonOid().getValue());
        promotedMember.setReferenceId(coveredPerson.getPersonOid().getValue());
        promotedMember.setGender(coveredPerson.getGender());
        promotedMember.setDefaultRelationship(coveredPerson.getRelationship());
        if (coveredPerson.getRelationship() != null && coveredPerson.getRelationship().getValue() != null) {
            promotedMember.setRelationship(coveredPerson.getRelationship().getValue());
        }
        promotedMember.setSsn(coveredPerson.getSSN());
        promotedMember.setBirthDate(coveredPerson.getBirthDate());
        promotedMember.setHandicapIndicator(coveredPerson.getHandicapIndicator());
        promotedMember.setPrefix(coveredPerson.getPrefix());
        promotedMember.setFirstName(coveredPerson.getFirstName());
        promotedMember.setMiddleName(coveredPerson.getMiddleName());
        promotedMember.setLastName(coveredPerson.getLastName());
        promotedMember.setSuffix(coveredPerson.getSuffix());
        promotedMember.setMaidenName(coveredPerson.getMaidenName());
        promotedMember.setCourtOrderDependentIndicator(coveredPerson.getCourtOrderDependentIndicator());
//      Data from Subscriber
        promotedMember.setSubscriberOid(generateTransitoryElement(subscriber.getReferenceId(), null));
        promotedMember.setEffectiveChangeDate(subscriber.getEffectiveChangeDate());
        promotedMember.getIdentifiers().addAll(subscriber.getIdentifiers());
//      Add Empty Benefits
        promotedMember.setBenefits(new BFEnrollmentPerson.Benefits());

        return promotedMember;
    }

    public static String getCarrierMemberProfileIdent(BFEnrollmentPerson member, String cmpIdentToFind) {
        for (Identifier ident : member.getIdentifiers()) {
            //the BaseSnapshotPrediffProcessor class filters out carrier-member-profile entries on the snapshot that are not
            //tied to the carrier we are extracting and just keeps the idents that are tied to the carrier. Even with this filtering
            //we may have multiple CMP idents, since eEnrollment writes out old and new data to the snapshot anytime a field on CMP table
            //is changed. We have no way to determine which value is latest until eEnrollment can provide additional fields we
            //can use for filtering. So until then, this method will return the first value it can find in the list that matches
            // the ident-to-find.

            if (ident.getIdentifierTypeClassification() != null && ident.getIdentifierTypeClassification().equalsIgnoreCase("CarrierMemberProfile")
                    && ident.getReferenceId().endsWith(cmpIdentToFind) && ident.getValue() != null && !StringUtil.isEmpty(ident.getValue().getValue())) {

                return ident.getValue().getValue();
            }
        }

        return null;
    }

    public static void markVobBenefitsAsVOB(BFEnrollmentPerson person) {
        if (person == null || person.getViewOnlyBenefits() == null) {
            return;
        }
        for (BenefitRecord benefit : person.getViewOnlyBenefits().getBenefitRecord()) {
            markAsVOB(benefit);
        }
    }

    public static void markAsVOB(BenefitRecord benefit) {
        TransactionHistoryDataUtil.addMetadataToMetadataList(benefit.getDxMetaData(), EDIConstants.METADATA_BENEFIT_VOB, Boolean.TRUE.toString());
    }

    public static void markAsBenefitType(BenefitRecord benefit) {
        TransactionHistoryDataUtil.addMetadataToMetadataList(benefit.getDxMetaData(), MetadataConstants.BENEFIT_TYPE, benefit.getBenefitType());
    }

    public static boolean isVOBBenefit(BenefitRecord benefit) {
        Metadata metadata = TransactionHistoryDataUtil.findMetadataByKey(benefit.getDxMetaData(), EDIConstants.METADATA_BENEFIT_VOB);
        return metadata != null && Boolean.valueOf(metadata.getValue());
    }

    public static void removeMemberFromSnapshotByPersonReferenceGuid(SnapshotData snapshotData, String personGUID) {
        if (personGUID != null && snapshotData != null && snapshotData.getLatestRequestedData() != null && snapshotData.getLatestRequestedData().getPerson() != null) {
            Iterator<BFEnrollmentPerson> personIterator = snapshotData.getLatestRequestedData().getPerson().iterator();
            while (personIterator.hasNext()) {
                BFEnrollmentPerson person = personIterator.next();
                if (personGUID.equals(person.getReferenceGUID())) {
                    personIterator.remove();
                }
            }
        }
    }


    // this code is put here for WR-237833(per Nate's suggestion) as this might be re-used for other tenant rule sets in future
    public static void setUniqueValueForMembersWithoutSSN(BFEnrollmentPerson member) {
        if (member.getReferenceId() != null) {
            int memberOidLength = member.getReferenceId().length();
            StringBuffer uniqueValue = new StringBuffer();
            uniqueValue.append("000");
            if (memberOidLength > 6) {
                uniqueValue = uniqueValue.append(member.getReferenceId().substring(memberOidLength - 6, memberOidLength));
            } else {
                int oid = Integer.parseInt(member.getReferenceId());
                uniqueValue = uniqueValue.append(String.format("%06d", oid));

            }
            member.setSsn(generateTransitoryElement(uniqueValue.toString(), null));
        }
    }

    /**
     * Removes duplicate benefits keeping the one with the greatest PP start date then by non refused benefits
     * then by highest reference id
     *
     * @param person
     * @param comparator - comparator to use for matching benefits
     */
    public static void removeDuplicateBenefits(BFEnrollmentPerson person, Comparator<BenefitRecord> comparator) {
        if (person == null) {
            return;
        }
        Map<BenefitRecord, List<BenefitRecord>> dupsMap = new HashMap<BenefitRecord, List<BenefitRecord>>();
        if (person.getBenefits() == null || person.getBenefits().getBenefitRecord() == null) {
            return;
        }
        boolean haveMatch;
        List<BenefitRecord> temp;
        //find duplicate benefits and create lists for each type
        for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
            haveMatch = false;
            for (Entry<BenefitRecord, List<BenefitRecord>> dupsMapEntry : dupsMap.entrySet()) {
                if (comparator.compare(benefit, dupsMapEntry.getKey()) == 0) {
                    dupsMapEntry.getValue().add(benefit);
                    haveMatch = true;
                    break;
                }
            }

            if (!haveMatch) {
                temp = new ArrayList<BenefitRecord>();
                temp.add(benefit);
                dupsMap.put(benefit, temp);
            }
        }

        //clear all benefits
        person.getBenefits().getBenefitRecord().clear();

        //keep one with greatest PP start date or, if equal, latest reference id
        for (List<BenefitRecord> dups : dupsMap.values()) {
            if (dups.size() > 1) {
                Collections.sort(dups, new BenefitAgeComparator());
            }
            PayrollUtil.addBenefit(person, dups.get(dups.size() - 1));
        }
    }

    /**
     * Gets a transactionInformationObject from the xml String in the snapshotIdentifiier.
     * Takes care of some initial data modifications to save space and or update data based on the current run time
     *
     * @param snapshotIdentifier
     * @return TransactionInformation
     * @throws Exception
     */
    public static TransactionInformation getTransactionInformationFromSnapshotIdentifier(SnapshotIdentifier snapshotIdentifier) throws Exception {
        TransactionInformation transactionInformation = null;
        if (snapshotIdentifier != null && snapshotIdentifier.getTransactionInfoString() != null) {
            transactionInformation = MarshallingUtil.unmarshalXmlToEntity(TransactionInformation.class, snapshotIdentifier.getTransactionInfoString());
            if (transactionInformation != null && transactionInformation.getSnapshotData() != null) {
                removeChangeAndApprovePayload(transactionInformation.getSnapshotData());
                resetParticipationPeriodOnBenefits(transactionInformation.getSnapshotData());
            }
        }
        return transactionInformation;
    }
 
    public static TransactionInformation getTransactionInformationFromXmlString(String transactionInformationString) throws Exception {
        TransactionInformation transactionInformation = null;
        if (transactionInformationString != null) {
            transactionInformation = MarshallingUtil.unmarshalXmlToEntity(TransactionInformation.class, transactionInformationString);
            if (transactionInformation != null && transactionInformation.getSnapshotData() != null) {
                removeChangeAndApprovePayload(transactionInformation.getSnapshotData());
                resetParticipationPeriodOnBenefits(transactionInformation.getSnapshotData());
            }
        }
        return transactionInformation;
    }

    public static String getXMLStringFromTransactionInformation(TransactionInformation transactionInformation) throws Exception {
        if(transactionInformation!=null){
            return MarshallingUtil.marshalEntityToXml(TransactionInformation.class, transactionInformation);
        }else{
            return null;
        }
    }

    public static void resetParticipationPeriodOnBenefits(SnapshotData snapshotData) throws Exception {
        if (EDIUtil.getPersonsFromSnapshotData(snapshotData, false) != null) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                resetParticipationPeriodOnBenefits(person);
            }
        }
    }

    public static void resetParticipationPeriodOnBenefits(BFEnrollmentPerson person) throws Exception {
        if (EDIUtil.enrollmentPersonHasBenefits(person)) {
            for (BenefitRecord ben : person.getBenefits().getBenefitRecord()) {
                //set PP end date to end of day. Comes in as 12:00 am and clear current text value as it may be incorrect.
                if (ben.getParticipationPeriodEndDate() != null && ben.getParticipationPeriodEndDate().getValue() != null) {
                    ben.getParticipationPeriodEndDate().setValue(
                            DateConverter.getInstance(ben.getParticipationPeriodEndDate().getValue(), TransactionHistoryDataUtil.FORMAT_DATETIME_ISO)
                                    .endOfDay().getDateAsString(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO));
                    ben.setParticipationPeriod(null);
                }
                ParticipationPeriodType type = ParticipationPeriodUtil.getParticipationPeriodType(ben);
                if (type != null) {
                    ben.setParticipationPeriod(
                            TransactionHistoryDataUtil.generateTransitoryElement(
                                    type.toString(), null));
                }
            }
        }
    }

    public static void removeChangeAndApprovePayload(SnapshotData snapshot) {
    if(snapshot!=null){
    snapshot.setChangePayload(null);
            snapshot.setLatestApprovedData(null);
    }
    }

    public static ExtractInformation getExtractInformationFromOutboundRecord(OutboundRecord outboundRecord) throws Exception {
        ExtractInformation extractInformation = null;
        if (outboundRecord != null && outboundRecord.getLastExtractInformation() != null) {
            extractInformation = MarshallingUtil.unmarshalXmlToEntity(ExtractInformation.class, outboundRecord.getLastExtractInformation());
            //Update ParticipationPeriod Type of last sent data to be valid based on todays run date.
            setParticipationPeriodOnSentInfo(extractInformation);
        }
        return extractInformation;
    }
 
    public static void setExtractInformationOnOutboundRecord(ExtractInformation extractInfo, OutboundRecord outboundRecord) {
    String extractInformationString = null;
    if (outboundRecord != null){
    if (extractInfo!=null){
    extractInformationString = getXMLStringFromExtractInformation(extractInfo);
    }
    outboundRecord.setLastExtractInformation(extractInformationString);
    }
}
 
    public static String getXMLStringFromExtractInformation(ExtractInformation extractInfo){
    String extractInformationString = null;
    if(extractInfo!=null){
    try {
extractInformationString = MarshallingUtil.marshalEntityToXml(ExtractInformation.class, extractInfo);
} catch (EdiUtilityException e) {
throw new EDIException("Error marshalling extract information object", e);
}
    }
return extractInformationString;
    }

    protected static void setParticipationPeriodOnSentInfo(ExtractInformation extractInformation) throws Exception {
        if (extractInformation != null) {
            if (extractInformation.getMemberInfo() != null) {
                for (SentInfo sentInfo : extractInformation.getSentInfo()) {
                    setParticipationPeriodOnBenefitInfo(sentInfo.getPlansSentOnCurrentSnapshot());
                    setParticipationPeriodOnBenefitInfo(sentInfo.getPlansSentOnLastSnapshot());
                }
            }
            if (extractInformation.getLastSentContractState() != null) {
                for (BFEnrollmentPerson person : extractInformation.getLastSentContractState().getBFEnrollmentPersons()) {
                    resetParticipationPeriodOnBenefits(person);
                }
            }
        }
    }

    private static void setParticipationPeriodOnBenefitInfo(SentPlanInfo sentPlanInfo) throws Exception {
        if (sentPlanInfo == null) {
            return;
        }
        for (BenefitInfo benefitInfo : sentPlanInfo.getBenefitInfo()) {
            ParticipationPeriodType type = ParticipationPeriodUtil.determineParticipationPeriodTypeByDates(benefitInfo.getParticipationPeriodStartDate(), benefitInfo.getParticipationPeriodEndDate());
            if (type != null) {
                benefitInfo.setParticipationPeriod(type.toString());
            }
        }
    }

    /**
     * This method determines whether a medicare policy of a member has an active plan or not. An active plan is one that
     * has no end-date or end-date is same as today's date or it's a future date.
     *
     * @param medicare medicare policy of a member
     * @return true if medicare has an active plan, false if not
     * @throws ParseException thrown when either today or planEndDateIso can't be parsed to an ISO format Date object.
     */
    public static boolean medicareHasAnActivePlan(Medicare medicare) throws ParseException {
        if (medicare != null && medicare.getPlans() != null && medicare.getPlans().getPlan() != null && !medicare.getPlans().getPlan().isEmpty()) {
            for (Medicare.Plans.Plan plan : medicare.getPlans().getPlan()) {
                if (plan.getEndDate() == null || StringUtil.isEmpty(plan.getEndDate().getValue())) {
                    return true;

                } else {
                    Date today = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, new Date());
                    Date planEndDateIso = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, plan.getEndDate().getValue());

                    if (!TransactionHistoryDataUtil.before(planEndDateIso, today)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static boolean benefitHasSpanOfCoverage(BenefitRecord benefitRecord) throws EDIException, ParseException {
        if (benefitRecord.getCoverageEndDate() == null || StringUtil.isEmpty(benefitRecord.getCoverageEndDate().getValue())) {
            return true;
        } else if (benefitRecord.getCoverageEffectiveDate() == null || (benefitRecord.getCoverageEffectiveDate() != null && StringUtil.isEmpty(benefitRecord.getCoverageEffectiveDate().getValue()))) {
            throw new EDIException("Benefit Record: " + benefitRecord.getReferenceId() + " is missing coverage effective Date!!");
        } else {
            return TransactionHistoryDataUtil.after(TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefitRecord.getCoverageEndDate().getValue()), TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefitRecord.getCoverageEffectiveDate().getValue()));
        }
    }

    public static boolean hasMetaDataName(List<Metadata> metadataList, String name) {
        if (name != null) {
            for (Metadata metadata : metadataList) {
                if (metadata.getName() != null && name.equals(metadata.getName())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Generates a distinct set of BFEnrollmentPerson referenceIds from a snapshot
     *
     * @param snapshotData
     * @return
     */
    public static Set<String> getEnrolledPersonReferenceIdsFromSnapshot(SnapshotData snapshotData) {
        Set<String> enrollmentPersonRefIdList = new HashSet<String>();
        if (EDIUtil.snapshotHasMembers(snapshotData)) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (person.getReferenceId() != null) {
                    enrollmentPersonRefIdList.add(person.getReferenceId());
                }
            }
        }
        return enrollmentPersonRefIdList;
    }

    /**
     * Generates a distinct set of BFEnrollmentPerson referenceIds from a snapshot
     *
     * @param snapshotData
     * @return
     */
    public static Set<String> getBenefitRecordReferenceIdsFromSnapshot(SnapshotData snapshotData) {
        Set<String> benefitRecordRefIdList = new HashSet<String>();
        if (EDIUtil.snapshotHasMembers(snapshotData)) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (EDIUtil.enrollmentPersonHasBenefits(person)) {
                    for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                        if (benefit.getReferenceId() != null) {
                            benefitRecordRefIdList.add(benefit.getReferenceId());
                        }
                    }
                }
            }
        }
        return benefitRecordRefIdList;
    }

    public static boolean isCobraLaterThanNonCobra(List<BenefitRecord> nonCobraRecs, List<BenefitRecord> cobraRecs) throws ParseException {
        if (cobraRecs == null || cobraRecs.isEmpty()) {
            return false;
        } else if (nonCobraRecs == null || nonCobraRecs.isEmpty()) {
            return true;
        } else {
            Date latestNonCobraEffDate = getLatestBenefitEffectiveDate(nonCobraRecs);
            Date latestCobraEffDate = getLatestBenefitEffectiveDate(cobraRecs);

            if (latestNonCobraEffDate != null && latestCobraEffDate != null && latestCobraEffDate.after(latestNonCobraEffDate)) {
                return true;
            }
        }

        return false;
    }

    public static boolean isNonCobraLaterThanCobra(List<BenefitRecord> nonCobraRecs, List<BenefitRecord> cobraRecs) throws ParseException {
        if (nonCobraRecs == null || nonCobraRecs.isEmpty()) {
            return false;
        } else if (cobraRecs == null || cobraRecs.isEmpty()) {
            return true;
        } else {
            Date latestNonCobraEffDate = getLatestBenefitEffectiveDate(nonCobraRecs);
            Date latestCobraEffDate = getLatestBenefitEffectiveDate(cobraRecs);

            if (latestNonCobraEffDate != null && latestCobraEffDate != null && latestNonCobraEffDate.after(latestCobraEffDate)) {
                return true;
            }
        }

        return false;
    }

    private static Date getLatestBenefitEffectiveDate(List<BenefitRecord> benefitRecs) throws ParseException {
        Date latestDate = null;

        if (benefitRecs != null && !benefitRecs.isEmpty()) {
            TreeSet<Date> effDates = new TreeSet<Date>();

            for (BenefitRecord benefitRec : benefitRecs) {
                if (TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(benefitRec.getCoverageEffectiveDate())) {
                    effDates.add(TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefitRec.getCoverageEffectiveDate().getValue()));
                }
            }

            latestDate = !effDates.isEmpty() ? effDates.last() : null;
        }

        return latestDate;
    }

    public static String getEventDateFromLifeEvent(BenefitRecord benefitRecord, String eventType) {
        Date eventDate = null;
        Date ppStartDate = null;
        try {
            for (LifeEventType lifeEventType : benefitRecord.getLifeEvent()) {
                if (eventType.equalsIgnoreCase(lifeEventType.getEventType().getValue())) {
                    eventDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, lifeEventType.getEventDate().getValue());
                    ppStartDate = TransactionHistoryDataUtil.getFormattedDate(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, benefitRecord.getParticipationPeriodStartDate().getValue());
                    if (eventDate.before(ppStartDate)) {
                        return TransactionHistoryDataUtil.getFormattedDateString(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, ppStartDate);
                    } else {
                        return TransactionHistoryDataUtil.getFormattedDateString(TransactionHistoryDataUtil.FORMAT_DATETIME_ISO, eventDate);
                    }
                }
            }
        } catch (ParseException pe) {
            throw new RuntimeException(pe);
        }
        return null;
    }

    public static List<String> getBenefitsThatMedicareIsApplicableFor() {
        return BenefitTypeConstant.getMedicareBenefitTypes();
    }

    public static boolean doesMedicarePolicyApplyForBenefit(String benefitType) {
        return getBenefitsThatMedicareIsApplicableFor().contains(benefitType);
    }

    public static boolean shouldMarkSubscribersForNextExtractionForJobType(EDIOutboundManager manager, AbstractConfig jobConfig) {
        if (manager == null) {
            return false;
        }

        if (manager.isAllowMarkSnapshots() == null) {
            manager.setAllowMarkSnapshots(false);
            if (manager.getEdiType() != null) {
                if (EDIProcessorEnum.EDI.equals(manager.getEdiType()) || EDIProcessorEnum.EDISERVICE.equals(manager.getEdiType())) {
                    manager.setAllowMarkSnapshots(manager.isHistorizeEdi() && manager.getEdiType().isAllowMarkSnapshotsForNextExtraction());
                } else if (EDIProcessorEnum.EDIREPORT.equals(manager.getEdiType()) && jobConfig != null) {
                    manager.setAllowMarkSnapshots(manager.isHistorizeEdi() && ((EDIReportConfig) jobConfig).isChangesReport());
                }
            }
        }

        return manager.isAllowMarkSnapshots();
    }

    public static Set<String> getUnderWritingCarrierOidsFromSnapshot(SnapshotData snapshotData) {
        Set<String> carrierOids = new HashSet<String>();
        if (EDIUtil.snapshotHasMembers(snapshotData)) {
            for (BFEnrollmentPerson person : snapshotData.getLatestRequestedData().getPerson()) {
                if (EDIUtil.enrollmentPersonHasBenefits(person)) {
                    for (BenefitRecord benefit : person.getBenefits().getBenefitRecord()) {
                        if (benefit.getUnderwritingCarrier() != null && benefit.getUnderwritingCarrier().getReferenceId() != null) {
                            carrierOids.add(benefit.getUnderwritingCarrier().getReferenceId());
                        }
                    }
                }
            }
        }

        return carrierOids;
    }

    /**
     * Attempts to return a BFEnrollmentPerson based on the first match utilizing the BFEnrollmentPersonComparator
     *
     * @param personToMatch The BFEnrollmentPerson instance to try to match
     * @param personList    - List of BFEnrollmentPersons to match against
     * @return
     * @see com.benefitfocus.transactionhistory.common.comparator.match.BFEnrollmentPersonComparator
     */
    public static BFEnrollmentPerson getMatchingPersonFromPersonList(BFEnrollmentPerson personToMatch, List<BFEnrollmentPerson> personList) {
        BFEnrollmentPerson matchedPerson = null;
        if (personToMatch != null && personList != null && !personList.isEmpty()) {
            BFEnrollmentPersonComparator personComparator = new BFEnrollmentPersonComparator();
            for (BFEnrollmentPerson person : personList) {
                if (personComparator.compare(person, personToMatch) == 0) {
                    matchedPerson = person;
                    break;
                }
            }
        }
        return matchedPerson;
    }

    /**
     * Attempts to return a BenefitRecord based on the first match utilizing the BenefitRecordComparator
     *
     * @param benefitToMatch - The BenefitRecord instance to try to match
     * @param benefitList    - List of BenefitRecords to match against
     * @param comparator - comparator to use for matching benefits
     * @return
     * @see com.benefitfocus.transactionhistory.common.comparator.match.custom.ediOutbound.BenefitRecordComparator
     */
    public static BenefitRecord getMatchingBenefitFromBenefitList(BenefitRecord benefitToMatch, List<BenefitRecord> benefitList, Comparator<BenefitRecord> comparator){
    List<BenefitRecord> matchedBenefitList = new ArrayList<BenefitRecord>();
    BenefitRecord matchedBenefit = null;
    if(benefitToMatch!=null && benefitList!=null && !benefitList.isEmpty()){
            for (BenefitRecord benefit : benefitList) {
                if (comparator.compare(benefit, benefitToMatch) == 0) {
                matchedBenefitList.add(benefit);
                }
            }
    }
    if(matchedBenefitList.isEmpty()){
    return null;
    }else{
    matchedBenefit = matchedBenefitList.get(0);
    for(BenefitRecord benefit : matchedBenefitList){
    if(benefit.getReferenceId().equals(benefitToMatch.getReferenceId())){
    matchedBenefit = benefit;
    break;
    }
    }
    }
return matchedBenefit;
    }

    public static Metadata findMetadataInMetadataList(List<Metadata> metadataList, String metadataName) {
        if(metadataList != null) {
            for(Metadata metadata : metadataList) {
                if(metadata != null && metadata.getName() != null && metadata.getName().equals(metadataName)) {
                    return metadata;
                }
            }
        }
        return null;
    }


    /**
     * Attempts to return a BenefitRecord based on first matching the provided person from the provided personList and then attempting to match the provided benefit agains the matched persons benefits
     *
     * @param personToMatch
     * @param benefitToMatch
     * @param personList
     * @return
     */
    public static BenefitRecord getMatchingBenefitFromMatchedPerson(BFEnrollmentPerson personToMatch, BenefitRecord benefitToMatch, List<BFEnrollmentPerson> personList, Comparator<BenefitRecord> comparator) {
        BenefitRecord matchedBenefit = null;
        if (personToMatch != null && benefitToMatch != null && personList != null && !personList.isEmpty()) {
            BFEnrollmentPerson matchedPerson = getMatchingPersonFromPersonList(personToMatch, personList);
            if (matchedPerson != null && EDIUtil.enrollmentPersonHasBenefits(matchedPerson)) {
                matchedBenefit = getMatchingBenefitFromBenefitList(benefitToMatch, matchedPerson.getBenefits().getBenefitRecord(), comparator);
            }
        }
        return matchedBenefit;
    }

    public static boolean TEIsEmpty(TransitoryElement teField) {
        return !TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(teField);
    }

    public static boolean TEPrevIsEmpty(TransitoryElement teField) {
        return teField == null || StringUtils.isBlank(teField.getPrevious());
    }

    public static boolean TEIsNotEmpty(TransitoryElement teField) {
        return TransactionHistoryDataUtil.transitoryElementHasNonEmptyValue(teField);
    }

    public static String getTEVal(TransitoryElement teField, String defaultVal){
        if(TEIsEmpty(teField)){
            return defaultVal;
        }else{
            return teField.getValue();
        }
    }

    public static String getTEPrevVal(TransitoryElement teField, String defaultVal){
        if(TEIsEmpty(teField)){
            return defaultVal;
        }else{
            return teField.getPrevious();
        }
    }

    public static boolean isNotEmpty(List list) {
        if (list != null && !list.isEmpty()) {
            return true;
        }
        return false;
    }
    /**
     * Helper method to create the standard Identifier
     * @param value - the value you need to Boomi to put on the file
     * @param name - name of the value copied from. (For research purposes)
     * @param classification - string non spaced value used for Boomi mapping
     * @return - Standard Identifier.
     */
    public static Identifier generateCustomIdentifier(String value, String classification, String name){
        Identifier ident = new Identifier();
        ident.setIdentifierType(IdentifierType.CUSTOM);
        ident.setValue(TransactionHistoryDataUtil.generateTransitoryElement(value,null));
        ident.setIdentifierTypeClassification(classification);
        ident.setName(TransactionHistoryDataUtil.generateTransitoryElement(name,null));
        return ident;
    }

    public static Identifier getIdentifier(List<Identifier> identifiers, String name, IdentifierType type){

        for (Identifier ident : identifiers){
            if (!TransactionHistoryDataUtil.isTransitoryElementValueEmptyOrNull(ident.getName())
                    && StringUtils.equalsIgnoreCase(ident.getName().getValue(), name)
                    && ident.getIdentifierType()==type){
                return ident;
            }
        }
        return null;
    }

    public static Address findAddressByType(BFEnrollmentPerson person, String addressType){
        if(person.getAdditionalAddresses() == null){
            return null;
        }

        for(Address address : person.getAdditionalAddresses()){
            if(getTEVal(address.getAddressType(), "").equalsIgnoreCase(addressType)){
                return address;
            }
        }
        return null;
    }

    public static boolean areAddressesEquals(Address a1, Address a2){
        return new AddressComparator().compare(a1,a2) == 0;
    }


public static boolean isERPaidBenefit(BenefitRecord benefit) {
boolean isERPaid = false;
        if (benefit != null && !benefit.getBenefitType().equals("HSA")) {
        for (ReasonCode rCode: benefit.getReasonCodes()) {
        if (rCode.getValue().equals("ZEC")) {
        isERPaid = true;
        break;
        }
        }          
        }
        return isERPaid;
}

    /**
     *
     * @return list of NON-ACA subscriber types represented on subscribers
     *
     */
    public static List<SubscriberTypeEnum> getNonACAOnlySubscriberTypes(){
       return nonACAOnlySubscriberTypeList;
    }

    /**
     *
     * @return list of ACA subscriber types represented on subscribers
     * These subscribers are ACA specific and may not represent full enrollments
     *
     */
    public static List<SubscriberTypeEnum> getACAOnlySubscriberTypes(){
        return acaOnlySubscriberTypeList;
    }
}