private void migrateFrequenciesToCodedValue(
      JdbcConnection connection, Set<String> uniqueFrequencies)
      throws CustomChangeException, SQLException, DatabaseException {
    PreparedStatement updateDrugOrderStatement = null;
    Boolean autoCommit = null;
    try {
      autoCommit = connection.getAutoCommit();
      connection.setAutoCommit(false);
      updateDrugOrderStatement =
          connection.prepareStatement(
              "update drug_order set frequency = ? where frequency_text = ?");
      for (String frequency : uniqueFrequencies) {
        Integer conceptIdForFrequency = UpgradeUtil.getConceptIdForUnits(frequency);
        if (conceptIdForFrequency == null) {
          throw new CustomChangeException("No concept mapping found for frequency: " + frequency);
        }
        Integer orderFrequencyId =
            UpgradeUtil.getOrderFrequencyIdForConceptId(
                connection.getUnderlyingConnection(), conceptIdForFrequency);
        if (orderFrequencyId == null) {
          throw new CustomChangeException(
              "No order frequency found for concept " + conceptIdForFrequency);
        }

        updateDrugOrderStatement.setInt(1, orderFrequencyId);
        updateDrugOrderStatement.setString(2, frequency);
        updateDrugOrderStatement.executeUpdate();
        updateDrugOrderStatement.clearParameters();
      }
      connection.commit();
    } catch (DatabaseException e) {
      handleError(connection, e);
    } catch (SQLException e) {
      handleError(connection, e);
    } finally {
      if (autoCommit != null) {
        connection.setAutoCommit(autoCommit);
      }
      if (updateDrugOrderStatement != null) {
        updateDrugOrderStatement.close();
      }
    }
  }
  /** Method to perform validation and resolution of duplicate EncounterType names */
  @Override
  public void execute(Database database) throws CustomChangeException {
    JdbcConnection connection = (JdbcConnection) database.getConnection();
    Map<String, HashSet<Integer>> duplicates = new HashMap<String, HashSet<Integer>>();
    Statement stmt = null;
    PreparedStatement pStmt = null;
    ResultSet rs = null;

    try {
      // set auto commit mode to false for UPDATE action
      connection.setAutoCommit(false);

      stmt = connection.createStatement();
      rs =
          stmt.executeQuery(
              "SELECT * FROM encounter_type INNER JOIN (SELECT name FROM encounter_type GROUP BY name HAVING count(name) > 1) dup ON encounter_type.name = dup.name");

      Integer id = null;
      String name = null;

      while (rs.next()) {
        id = rs.getInt("encounter_type_id");
        name = rs.getString("name");

        if (duplicates.get(name) == null) {
          HashSet<Integer> results = new HashSet<Integer>();
          results.add(id);
          duplicates.put(name, results);
        } else {
          HashSet<Integer> results = duplicates.get(name);
          results.add(id);
        }
      }

      Iterator it2 = duplicates.entrySet().iterator();
      while (it2.hasNext()) {
        Map.Entry pairs = (Map.Entry) it2.next();

        HashSet values = (HashSet) pairs.getValue();
        List<Integer> editableNames = new ArrayList<Integer>(values);

        int duplicateNameId = 1;
        for (int i = 1; i < editableNames.size(); i++) {
          String newName = pairs.getKey() + "_" + duplicateNameId;

          List<List<Object>> duplicateResult = null;
          boolean duplicateName = false;
          Connection con = DatabaseUpdater.getConnection();

          do {
            String sqlValidatorString =
                "select * from encounter_type where name = '" + newName + "'";
            duplicateResult = DatabaseUtil.executeSQL(con, sqlValidatorString, true);

            if (!duplicateResult.isEmpty()) {
              duplicateNameId += 1;
              newName = pairs.getKey() + "_" + duplicateNameId;
              duplicateName = true;
            } else {
              duplicateName = false;
            }
          } while (duplicateName);

          pStmt =
              connection.prepareStatement(
                  "update encounter_type set name = ? where encounter_type_id = ?");
          pStmt.setString(1, newName);
          pStmt.setInt(2, editableNames.get(i));

          duplicateNameId += 1;

          pStmt.executeUpdate();
        }
      }
    } catch (BatchUpdateException e) {
      log.warn("Error generated while processsing batch insert", e);

      try {
        log.debug("Rolling back batch", e);
        connection.rollback();
      } catch (Exception rbe) {
        log.warn("Error generated while rolling back batch insert", e);
      }

      // marks the changeset as a failed one
      throw new CustomChangeException(
          "Failed to update one or more suplicate EncounterType names", e);
    } catch (DatabaseException e) {
      throw new CustomChangeException(
          "Error while updating duplicate EncounterType object names", e);
    } catch (SQLException e) {
      throw new CustomChangeException(
          "Error while updating duplicate EncounterType object names", e);
    } catch (DAOException e) {
      throw new CustomChangeException("Error accessing database connection", e);
    } catch (Exception e) {
      throw new CustomChangeException("Error accessing database connection", e);
    } finally {
      // reset to auto commit mode
      try {
        connection.setAutoCommit(true);
      } catch (DatabaseException e) {
        log.warn("Failed to reset auto commit back to true", e);
      }
      if (rs != null) {
        try {
          rs.close();
        } catch (SQLException e) {
          log.warn("Failed to close the resultset object");
        }
      }

      if (stmt != null) {
        try {
          stmt.close();
        } catch (SQLException e) {
          log.warn(
              "Failed to close the select statement used to identify duplicate EncounterType object names");
        }
      }

      if (pStmt != null) {
        try {
          pStmt.close();
        } catch (SQLException e) {
          log.warn(
              "Failed to close the prepared statement used to update duplicate EncounterType object names");
        }
      }
    }
  }
  private void insertUniqueFrequencies(JdbcConnection connection, Set<String> uniqueFrequencies)
      throws CustomChangeException, SQLException, DatabaseException {
    PreparedStatement insertOrderFrequencyStatement = null;
    Boolean autoCommit = null;
    try {
      autoCommit = connection.getAutoCommit();
      connection.setAutoCommit(false);
      insertOrderFrequencyStatement =
          connection.prepareStatement(
              "insert into order_frequency "
                  + "(concept_id, creator, date_created, retired, uuid) values (?, ?, ?, ?, ?)");

      Date date = new Date(new java.util.Date().getTime());

      for (String frequency : uniqueFrequencies) {
        if (StringUtils.isBlank(frequency)) {
          continue;
        }

        Integer conceptIdForFrequency = UpgradeUtil.getConceptIdForUnits(frequency);
        if (conceptIdForFrequency == null) {
          throw new CustomChangeException("No concept mapping found for frequency: " + frequency);
        }

        Integer orderFrequencyId =
            UpgradeUtil.getOrderFrequencyIdForConceptId(
                connection.getUnderlyingConnection(), conceptIdForFrequency);
        if (orderFrequencyId != null) {
          // a single concept is mapped to more than one text or there is an order frequency already
          continue;
        }

        // Generating UUID for order frequency. Generated UUIDs will be the same if concepts UUIDs
        // are the same.
        String uuid =
            UpgradeUtil.getConceptUuid(connection.getUnderlyingConnection(), conceptIdForFrequency);
        uuid += "-6925ebb0-7c69-11e3-baa7-0800200c9a66"; // Adding random value for order frequency
        uuid = UUID.nameUUIDFromBytes(uuid.getBytes()).toString();

        insertOrderFrequencyStatement.setInt(1, conceptIdForFrequency);
        insertOrderFrequencyStatement.setInt(2, 1);
        insertOrderFrequencyStatement.setDate(3, date);
        insertOrderFrequencyStatement.setBoolean(4, false);
        insertOrderFrequencyStatement.setString(5, uuid);

        insertOrderFrequencyStatement.executeUpdate();
        insertOrderFrequencyStatement.clearParameters();
      }
      connection.commit();
    } catch (DatabaseException e) {
      handleError(connection, e);
    } catch (SQLException e) {
      handleError(connection, e);
    } finally {
      if (autoCommit != null) {
        connection.setAutoCommit(autoCommit);
      }
      if (insertOrderFrequencyStatement != null) {
        insertOrderFrequencyStatement.close();
      }
    }
  }