@Override
  public MecSsn process(MecSsn mecSsn) throws ValidationException {

    /*TODO this pattern should be cached and not compiled each time*/

    String ssn = mecSsn.getSsn();
    String MRN = mecSsn.getMrn();
    String region = regionMapper.getMecRegionCodeByVal(mecSsn.getRegion_Cd());

    if (region == null) {
      mecSsn.setInvalidRecord(MecConstants.Y_FLAG);
      // TODO: get clarification on invalid region codes
      mecSsn.setInvalidReason(MecConstants.INVALID_REGION);
    } else {
      if (mecUtils.needsCMSSNPadding(region)) {
        mecSsn.setSsn(mecUtils.padCMSSN(ssn));
      }
      if (!mecUtils.isValidSSN(ssn, MRN)) {
        mecSsn.setException(MecConstants.INVALID_SSN);
        mecSsn.setInvalidRecord(MecConstants.Y_FLAG);
        mecSsn.setInvalidReason(MecConstants.INVALID_SSN);
      } else {
        // TODO: check if ssn matches mrn
        mecSsn.setInvalidRecord(MecConstants.N_FLAG);
      }
    }

    mecSsn.setLogFileIk(logFileIk);
    mecSsn.setCreated_by(MecConstants.CREATED_BY);

    return mecSsn;
  }
  /**
   * @param newRecord
   * @param existingRecord
   * @author Eric
   * @comment Updates the month flags for a MecDocSub/MecDocCovInd record using the start/end dates
   */
  private void updateMecDocMonths(MecMdw mdwRecord, MecDoc newRecord) {

    String startDate = mdwRecord.getMbrshp_eff_strt_dt();
    String endDate = mdwRecord.getMbrshp_eff_end_dt();

    //		logger.debug("newRecord.getMbrshp_eff_strt_dt()="+mdwRecord.getMbrshp_eff_strt_dt());
    //		logger.debug("endDate()="+mdwRecord.getMbrshp_eff_end_dt());

    Date startEffDate =
        mecUtils.parseDate(startDate, mecProperty.getProperty(MecConstants.MDW_DOB_FORMAT));
    Date endEffDate =
        mecUtils.parseDate(endDate, mecProperty.getProperty(MecConstants.MDW_DOB_FORMAT));

    if (mecProperty.getProperty(MecConstants.MDW_MBRSHP_RGN).contains(mdwRecord.getRgn_cd())) {
      Date mbrEndDate = mecUtils.removeTime(endEffDate);
      // MDW_MBRSHP_DATE
      Date mdwEndDate_12314000 =
          mecUtils.parseDate(
              mecProperty.getProperty(MecConstants.MDW_MBRSHP_DATE),
              mecProperty.getProperty(MecConstants.MDW_DOB_FORMAT));

      // Check if mbrshp_end_dt <> 12/31/4000
      if (!mdwEndDate_12314000.equals(mbrEndDate)) {
        endEffDate = new Date(endEffDate.getTime() - MecConstants.MILLIS_IN_DAY);
      }
    }

    mecUtils.updateMonthsForMecDoc(startEffDate, endEffDate, newRecord);
  }
 /**
  * @param insertedRecord
  * @param mdwDependent
  * @author Eric
  * @comment Inserts a dependent into MecDocCovInd
  */
 private void generateAndInsertMecDocCovInd(long mecDocId, MecMdw mdwDependent) {
   Dependent dependent = new Dependent();
   dependent.setFirst_nm(mdwDependent.getMbr_frst_nm());
   dependent.setMiddle_nm(mdwDependent.getMbr_mdl_nm());
   dependent.setLast_nm(mdwDependent.getMbr_lst_nm());
   dependent.setSuffix_nm(mdwDependent.getMbr_sfx());
   dependent.setMrn_pfx(mdwDependent.getMrn_pfx());
   dependent.setMrn(mdwDependent.getMbr_mrn());
   dependent.setLast_nm(mdwDependent.getMbr_lst_nm());
   updateMecDocMonths(mdwDependent, dependent);
   dependent.setFk_mdw_id(mdwDependent.getMdw_id());
   dependent.setFk_mec_doc_id(mecDocId);
   dependent.setCreated_by(mecProperty.getProperty(MecConstants.CREATED_BY));
   Date dob =
       mecUtils.parseDate(
           mdwDependent.getMbr_dob(), mecProperty.getProperty(MecConstants.MDW_DOB_FORMAT));
   dependent.setDob(dob);
   dependent.setSsn(mdwDependent.getRep_ssn());
   mecDocMapper.insertMecDocCovInd(dependent);
 }
  /**
   * @param mdwSubscriber
   * @param newSubscriber
   * @author Eric
   * @comment Inserts a subscriber into MecDocSub
   */
  private void generateAndInsertMecDocSub(MecMdw mdwSubscriber, Subscriber newSubscriber) {
    // TODO: check employer sponsored codes
    if (MecConstants.EMPLOYER_SPONSORED_PLANS.contains(mdwSubscriber.getRep_policy_ogn_cd())) {
      newSubscriber.setEmployer_name(mdwSubscriber.getRep_ein_emp_name());
      newSubscriber.setEmployer_name2("");
      newSubscriber.setEmployer_ein(mdwSubscriber.getRep_ein());
      newSubscriber.setEmp_addr1(mdwSubscriber.getRep_ein_addr1());
      newSubscriber.setEmp_addr2(mdwSubscriber.getRep_ein_addr2());
      newSubscriber.setEmp_city(mdwSubscriber.getRep_ein_city());
      newSubscriber.setEmp_state(mdwSubscriber.getRep_ein_state());
      newSubscriber.setEmp_province(mdwSubscriber.getRep_ein_province());
      newSubscriber.setEmp_zip(mdwSubscriber.getRep_ein_zip());
      newSubscriber.setEmp_zip_4(mdwSubscriber.getRep_ein_zip_4());
      newSubscriber.setEmp_country_cd(mdwSubscriber.getRep_ein_country_Cd());
      newSubscriber.setEmp_country(mdwSubscriber.getRep_ein_country_name());
      newSubscriber.setEmp_foreign_zip(mdwSubscriber.getRep_ein_foreign_zip_code());
    }

    Date dob =
        mecUtils.parseDate(
            mdwSubscriber.getSbscrb_dob(), mecProperty.getProperty(MecConstants.MDW_DOB_FORMAT));
    newSubscriber.setDob(dob);
    newSubscriber.setPolicy_origin_cd(mdwSubscriber.getRep_policy_ogn_cd());
    newSubscriber.setShop_idn_num(mdwSubscriber.getRep_shop_market_id());
    newSubscriber.setSsn(mdwSubscriber.getRep_ssn());
    newSubscriber.setSubs_type_cd(mdwSubscriber.getSbscrb_typ_cd());
    newSubscriber.setFirst_nm(mdwSubscriber.getSbscrb_frst_nm());
    newSubscriber.setMiddle_nm(mdwSubscriber.getSbscrb_mdl_nm());
    newSubscriber.setLast_nm(mdwSubscriber.getSbscrb_lst_nm());
    newSubscriber.setSuffix_nm(mdwSubscriber.getSbscrb_sfx());
    newSubscriber.setAddr1(mdwSubscriber.getSbscrb_lne_1());
    newSubscriber.setAddr2(mdwSubscriber.getSbscrb_lne_2());
    newSubscriber.setCity(mdwSubscriber.getSbscrb_cty_nm());
    newSubscriber.setState(mdwSubscriber.getSbscrb_st_cd());
    newSubscriber.setSub_province(mdwSubscriber.getSbscrb_prvnc());
    newSubscriber.setZip(mdwSubscriber.getSbscrb_zip_cd());
    newSubscriber.setMailzip4(mdwSubscriber.getSbscrb_zip_pls_4());
    newSubscriber.setSub_country_cd(mdwSubscriber.getSbscrb_cntry_cd());
    newSubscriber.setCountry(mdwSubscriber.getSbscrb_cntry_name());
    newSubscriber.setSub_foreign_cd(mdwSubscriber.getSbscrb_frn_pstl_cd());
    newSubscriber.setRgn_cd(mdwSubscriber.getRgn_cd());
    newSubscriber.setMrn(mdwSubscriber.getSbscrb_mrn());
    newSubscriber.setMrn_pfx(mdwSubscriber.getSbscrb_mrn_pfx());
    newSubscriber.setFk_mdw_id(mdwSubscriber.getMdw_id());
    newSubscriber.setIrs_trans_type(MecConstants.ORIGINAL_DOC);
    newSubscriber.setStmt_type(MecConstants.ORIGINAL_DOC);
    newSubscriber.setCreated_by(mecProperty.getProperty(MecConstants.CREATED_BY));
    newSubscriber.setTax_year(mdwSubscriber.getTax_year());
    newSubscriber.setFk_issuer_id(mdwSubscriber.getRep_kaiser_issuer_id());
    // NON-COV Subscribers do not need coverage months
    if (mecProperty.getProperty(MecConstants.SUBSCRIBER).equals(newSubscriber.getSubs_type_cd())) {
      updateMecDocMonths(mdwSubscriber, newSubscriber);
    }
    try {
      // TODO: load region table by memory
      // logger.error("88888=   "+mecRegions.getRegion(1));
      // newRecord.setFk_region_id(regionMapper.getRegionIdByMdwCode(mdwRecord.getRgn_cd()));
      newSubscriber.setFk_region_id(mecRegions.getRegionIdByMdwCode(mdwSubscriber.getRgn_cd()));
    } catch (BindingException e) {
      logger.error("Error: " + e.getMessage(), e);
      throw e;
    }
    mecDocMapper.insertSubscriberRecord(newSubscriber);
  }