PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/api/src/main/java/org/openmrs/util/databasechange/DuplicateEncounterTypeNameChangeSet.java

https://gitlab.com/Jayanth.Kumar/lh-toolkit
Java | 205 lines | 149 code | 35 blank | 21 comment | 17 complexity | ee72947a35c42147b9e81e0c32268aa1 MD5 | raw file
  1. /**
  2. * This Source Code Form is subject to the terms of the Mozilla Public License,
  3. * v. 2.0. If a copy of the MPL was not distributed with this file, You can
  4. * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
  5. * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
  6. *
  7. * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
  8. * graphic logo is a trademark of OpenMRS Inc.
  9. */
  10. package org.openmrs.util.databasechange;
  11. import java.sql.BatchUpdateException;
  12. import java.sql.Connection;
  13. import java.sql.ResultSet;
  14. import java.sql.SQLException;
  15. import java.sql.Statement;
  16. import java.util.ArrayList;
  17. import java.util.HashMap;
  18. import java.util.HashSet;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.Map;
  22. import liquibase.database.jvm.JdbcConnection;
  23. import java.sql.PreparedStatement;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.openmrs.util.DatabaseUpdater;
  27. import org.openmrs.util.DatabaseUtil;
  28. import liquibase.change.custom.CustomTaskChange;
  29. import liquibase.database.Database;
  30. import liquibase.exception.CustomChangeException;
  31. import liquibase.exception.DatabaseException;
  32. import liquibase.exception.SetupException;
  33. import liquibase.exception.ValidationErrors;
  34. import liquibase.resource.ResourceAccessor;
  35. /**
  36. * Liquibase custom changeset used to identify and resolve duplicate EncounterType names. If a
  37. * duplicate EncounterType name is identified, it will be edited to include a suffix term which
  38. * makes it unique, and identifies it as a value to be manually changed during later review
  39. */
  40. public class DuplicateEncounterTypeNameChangeSet implements CustomTaskChange {
  41. private static final Log log = LogFactory.getLog(DuplicateEncounterTypeNameChangeSet.class);
  42. @Override
  43. public String getConfirmationMessage() {
  44. return "Completed updating duplicate EncounterType names";
  45. }
  46. @Override
  47. public void setFileOpener(ResourceAccessor arg0) {
  48. }
  49. @Override
  50. public void setUp() throws SetupException {
  51. // No setup actions
  52. }
  53. @Override
  54. public ValidationErrors validate(Database arg0) {
  55. return null;
  56. }
  57. /**
  58. * Method to perform validation and resolution of duplicate EncounterType names
  59. */
  60. @Override
  61. public void execute(Database database) throws CustomChangeException {
  62. JdbcConnection connection = (JdbcConnection) database.getConnection();
  63. Map<String, HashSet<Integer>> duplicates = new HashMap<String, HashSet<Integer>>();
  64. Statement stmt = null;
  65. PreparedStatement pStmt = null;
  66. ResultSet rs = null;
  67. Boolean initialAutoCommit = null;
  68. try {
  69. initialAutoCommit = connection.getAutoCommit();
  70. // set auto commit mode to false for UPDATE action
  71. connection.setAutoCommit(false);
  72. stmt = connection.createStatement();
  73. rs = stmt
  74. .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");
  75. Integer id = null;
  76. String name = null;
  77. while (rs.next()) {
  78. id = rs.getInt("encounter_type_id");
  79. name = rs.getString("name");
  80. if (duplicates.get(name) == null) {
  81. HashSet<Integer> results = new HashSet<Integer>();
  82. results.add(id);
  83. duplicates.put(name, results);
  84. } else {
  85. HashSet<Integer> results = duplicates.get(name);
  86. results.add(id);
  87. }
  88. }
  89. Iterator it2 = duplicates.entrySet().iterator();
  90. while (it2.hasNext()) {
  91. Map.Entry pairs = (Map.Entry) it2.next();
  92. HashSet values = (HashSet) pairs.getValue();
  93. List<Integer> ids = new ArrayList<Integer>(values);
  94. int duplicateNameId = 1;
  95. for (int i = 1; i < ids.size(); i++) {
  96. String newName = pairs.getKey() + "_" + duplicateNameId;
  97. List<List<Object>> duplicateResult = null;
  98. boolean duplicateName = false;
  99. Connection con = DatabaseUpdater.getConnection();
  100. do {
  101. String sqlValidatorString = "select * from encounter_type where name = '" + newName + "'";
  102. duplicateResult = DatabaseUtil.executeSQL(con, sqlValidatorString, true);
  103. if (!duplicateResult.isEmpty()) {
  104. duplicateNameId += 1;
  105. newName = pairs.getKey() + "_" + duplicateNameId;
  106. duplicateName = true;
  107. } else {
  108. duplicateName = false;
  109. }
  110. } while (duplicateName);
  111. pStmt = connection.prepareStatement("update encounter_type set name = ? where encounter_type_id = ?");
  112. pStmt.setString(1, newName);
  113. pStmt.setInt(2, ids.get(i));
  114. duplicateNameId += 1;
  115. pStmt.executeUpdate();
  116. }
  117. }
  118. }
  119. catch (BatchUpdateException e) {
  120. log.warn("Error generated while processsing batch insert", e);
  121. try {
  122. log.debug("Rolling back batch", e);
  123. connection.rollback();
  124. }
  125. catch (Exception rbe) {
  126. log.warn("Error generated while rolling back batch insert", e);
  127. }
  128. // marks the changeset as a failed one
  129. throw new CustomChangeException("Failed to update one or more duplicate EncounterType names", e);
  130. }
  131. catch (Exception e) {
  132. throw new CustomChangeException(e);
  133. }
  134. finally {
  135. // set auto commit to its initial state
  136. try {
  137. if (initialAutoCommit != null) {
  138. connection.setAutoCommit(initialAutoCommit);
  139. }
  140. }
  141. catch (DatabaseException e) {
  142. log.warn("Failed to set auto commit to ids initial state", e);
  143. }
  144. if (rs != null) {
  145. try {
  146. rs.close();
  147. }
  148. catch (SQLException e) {
  149. log.warn("Failed to close the resultset object");
  150. }
  151. }
  152. if (stmt != null) {
  153. try {
  154. stmt.close();
  155. }
  156. catch (SQLException e) {
  157. log.warn("Failed to close the select statement used to identify duplicate EncounterType object names");
  158. }
  159. }
  160. if (pStmt != null) {
  161. try {
  162. pStmt.close();
  163. }
  164. catch (SQLException e) {
  165. log.warn("Failed to close the prepared statement used to update duplicate EncounterType object names");
  166. }
  167. }
  168. }
  169. }
  170. }