diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseAPI.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseAPI.java index ac6d4959..76f03884 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseAPI.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseAPI.java @@ -117,6 +117,49 @@ public abstract boolean deleteFromTable(String tableName, String courtLocation) public abstract List getCaseTypeNamesFor( String courtLocationId, String caseCategoryCode, Optional initial); + protected void validTable(String tableName) throws SQLException { + if (tableName.contains("(") + || tableName.contains(")") + || tableName.contains(" ") + || tableName.contains(";")) { + log.warn("Must be a valid table name: {} is not", tableName); + throw new CodeDatabaseUtils.UnsupportedTableException( + "Must be a valid table name: " + tableName + " is not"); + } + } + + protected boolean tableExists(String tableName) throws SQLException { + if (conn == null) { + throw new SQLException(); + } + validTable(tableName); + String tableExistsQuery = CodeDatabaseUtils.getTableExists(); + try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) { + existsSt.setString(1, tableName); + ResultSet rs = existsSt.executeQuery(); + boolean next = rs.next(); + int firstVal = rs.getInt(1); + rs.close(); + return (next && firstVal > 0); + } + } + + protected boolean indiciesExists(String tableName) throws SQLException { + if (conn == null) { + throw new SQLException(); + } + validTable(tableName); + + String indicesExist = CodeDatabaseUtils.getIndicesExist(); + try (PreparedStatement existsSt = conn.prepareStatement(indicesExist)) { + existsSt.setString(1, tableName); + ResultSet rs = existsSt.executeQuery(); + boolean next = rs.next(); + int firstVal = rs.getInt(1); + return (next && firstVal > 0); + } + } + /** Runs all of the logic for search queries (both name searches and court coverage searches). */ protected List genericSearch( String searchTerm, SQLFunction queryMaker) { diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseUtils.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseUtils.java index 34ba3413..c79ccb30 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseUtils.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/ecfcodes/CodeDatabaseUtils.java @@ -1,6 +1,11 @@ package edu.suffolk.litlab.efsp.ecfcodes; +import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Types; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class CodeDatabaseUtils { /** This exception is returned when a given table name isn't in the pre-approved list of names. */ @@ -35,4 +40,113 @@ public static String likeWildcard(String searchTerm) { } return "%" + searchTerm + "%"; } + + public static record TableColumns( + List mainList, List primaryKeys, boolean needsExtraLocCol) {} + + public static record Column(String name, String type) {} + + /** + * Returns an INSERT statement for the given table + court. The statement includes a ON CONFLICT + * (all columns...) DO NOTHING clause. + * + * @param tableName The name of the DB table (i.e. code list) to insert into + * @param courtName The Court Location ID to add codes for + */ + public static String createInsertQuery(String tableName, TableColumns tc) { + StringBuilder insertLocation = new StringBuilder(); + insertLocation.append("INSERT INTO \"" + tableName + "\" ("); + StringBuilder colNames = new StringBuilder(); + boolean isFirst = true; + for (Column col : tc.mainList()) { + if (isFirst) { + isFirst = false; + } else { + colNames.append(", "); + } + colNames.append("\"" + col.name() + "\""); + } + if (tc.needsExtraLocCol()) { + colNames.append(", location"); + } + colNames.append(", jurisdiction"); + insertLocation.append(colNames.toString()); + insertLocation.append(") VALUES ("); + for (int i = 0; i < tc.mainList().size(); i++) { + if (i > 0) { + insertLocation.append(", "); + } + insertLocation.append("?"); + } + if (tc.needsExtraLocCol()) { + insertLocation.append(", ?"); + } + insertLocation.append(", ?"); + insertLocation.append(")"); + return insertLocation.toString(); + } + + public static String createTableQuery(String tableName, TableColumns tc) { + StringBuilder createLocation = new StringBuilder(); + createLocation.append("CREATE TABLE " + tableName + "("); + boolean isFirst = true; + for (Column col : tc.mainList()) { + if (isFirst) { + isFirst = false; + } else { + createLocation.append(", "); + } + createLocation.append("\"" + col.name() + "\" " + col.type()); + } + if (tc.needsExtraLocCol()) { + createLocation.append(", \"location\" varchar(80)"); + } + createLocation.append(", \"jurisdiction\" varchar(80)"); + + if (!tc.primaryKeys().isEmpty()) { + createLocation.append( + ", PRIMARY KEY(" + tc.primaryKeys().stream().collect(Collectors.joining(",")) + ")"); + } + createLocation.append(")"); + return createLocation.toString(); + } + + public static PreparedStatement singleInsert( + PreparedStatement stmt, + TableColumns columns, + Map rowVals, + String courtName, + String jurisStr) + throws SQLException { + int idx = 1; + for (var col : columns.mainList) { + if (col.type.equalsIgnoreCase("boolean")) { + if (rowVals.containsKey(col.name)) { + stmt.setBoolean(idx, Boolean.parseBoolean(rowVals.get(col.name))); + } else { + stmt.setNull(idx, Types.BOOLEAN); + } + } else if (col.type.equalsIgnoreCase("integer")) { + if (rowVals.containsKey(col.name)) { + stmt.setInt(idx, Integer.parseInt(rowVals.get(col.name))); + } else { + stmt.setNull(idx, Types.INTEGER); + } + } else { + // colType.equalsIgnoreCase("text") || colType.startsWith("varchar") + if (rowVals.containsKey(col.name)) { + stmt.setString(idx, rowVals.get(col.name)); + } else { + stmt.setString(idx, null); + } + } + idx += 1; + } + if (columns.needsExtraLocCol) { + stmt.setString(idx, courtName); + idx += 1; + } + stmt.setString(idx, jurisStr); + return stmt; + } } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeDatabase.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeDatabase.java index 2fa61aa3..cf625727 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeDatabase.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeDatabase.java @@ -14,7 +14,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -24,7 +23,6 @@ import java.util.Optional; import java.util.Set; import javax.sql.DataSource; -import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -117,20 +115,7 @@ public static CodeDatabase fromDS(Jurisdiction jurisdiction, DataSource ds) { } public boolean tablesExist() throws SQLException { - String tableExistsQuery = CodeDatabaseUtils.getTableExists(); - boolean locationExists = false; - boolean installedExists = false; - try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) { - existsSt.setString(1, "location"); - ResultSet rs = existsSt.executeQuery(); - locationExists = rs.next() && rs.getInt(1) > 0; - } - try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) { - existsSt.setString(1, "installedversion"); - ResultSet rs = existsSt.executeQuery(); - installedExists = rs.next() && rs.getInt(1) > 0; - } - return locationExists && installedExists; + return tableExists("location") && tableExists("installedversion"); } @Override @@ -149,63 +134,35 @@ private String jurisStr() { } public void createTableIfAbsent(String tableName) throws SQLException { - if (conn == null) { - throw new SQLException(); - } - if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) { - log.warn("Must be valid table name: {} is not", tableName); - return; - } + boolean exists = tableExists(tableName); // TODO(brycew-later): eventually make the create tables have foreign keys and // required from the Id / columnRefs - String tableExistsQuery = CodeDatabaseUtils.getTableExists(); - try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) { - existsSt.setString(1, tableName); - ResultSet rs = existsSt.executeQuery(); - boolean next = rs.next(); - int firstVal = rs.getInt(1); - if (!next || firstVal <= 0) { // There's no table! Make one - if (tableName.equals("optionalservices")) { - log.info("Creating optionalservices"); - OptionalServiceCode.createFromOptionalServiceTable(conn); - } else { - String createQuery = CodeTableConstants.getCreateTable(tableName); - try (Statement createSt = conn.createStatement()) { - log.info("Full statement: {}", createQuery); - createSt.executeUpdate(createQuery); - } + if (!exists) { // There's no table! Make one + if (tableName.equals("optionalservices")) { + log.info("Creating optionalservices"); + OptionalServiceCode.createFromOptionalServiceTable(conn); + } else { + String createQuery = CodeTableConstants.getCreateTable(tableName); + try (Statement createSt = conn.createStatement()) { + log.info("Full statement: {}", createQuery); + createSt.executeUpdate(createQuery); } } - rs.close(); } } public void createIndicesIfAbsent(String tableName) throws SQLException { - if (conn == null) { - throw new SQLException(); - } - if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) { - log.warn("Must be a valid table name: {} is not", tableName); - return; - } - - String indicesExist = CodeDatabaseUtils.getIndicesExist(); - try (PreparedStatement existsSt = conn.prepareStatement(indicesExist)) { - existsSt.setString(1, tableName); - ResultSet rs = existsSt.executeQuery(); - boolean next = rs.next(); - int firstVal = rs.getInt(1); - if (!next || firstVal <= 0) { - if (tableName.equals("optionalservices")) { - OptionalServiceCode.createIndices(conn); - } else { - // Create the indices: might take a while - List createIndices = CodeTableConstants.getCreateIndex(tableName); - for (String createIndex : createIndices) { - try (PreparedStatement createSt = conn.prepareStatement(createIndex)) { - createSt.executeUpdate(); - } + boolean exists = indiciesExists(tableName); + if (!exists) { + if (tableName.equals("optionalservices")) { + OptionalServiceCode.createIndices(conn); + } else { + // Create the indices: might take a while + List createIndices = CodeTableConstants.getCreateIndex(tableName); + for (String createIndex : createIndices) { + try (PreparedStatement createSt = conn.prepareStatement(createIndex)) { + createSt.executeUpdate(); } } } @@ -217,10 +174,7 @@ public void updateTable(String tableName, String courtName, InputStream inStream if (conn == null) { throw new SQLException("Null connection!"); } - if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) { - log.warn("Must be valid table name: {} is not", tableName); - return; - } + validTable(tableName); createTableIfAbsent(tableName); createIndicesIfAbsent(tableName); @@ -266,51 +220,14 @@ private void updateTableInner( // ColumnSet cs = rows.getColumnSet(); while (rows.hasNext()) { Map rowsVals = rows.next(); - singleInsert(stmt, tableName, courtName, rowsVals); + CodeDatabaseUtils.singleInsert( + stmt, CodeTableConstants.getTableColumns(tableName), rowsVals, courtName, jurisStr()); stmt.addBatch(); } stmt.executeBatch(); } } - private PreparedStatement singleInsert( - PreparedStatement stmt, String tableName, String courtName, Map rowsVals) - throws SQLException { - int idx = 1; - List> tc = CodeTableConstants.getTableColumnsWithType(tableName); - for (Pair col : tc) { - String colName = col.getLeft(); - String colType = col.getRight(); - if (colType.equalsIgnoreCase("boolean")) { - if (rowsVals.containsKey(colName)) { - stmt.setBoolean(idx, Boolean.parseBoolean(rowsVals.get(colName))); - } else { - stmt.setNull(idx, Types.BOOLEAN); - } - } else if (colType.equalsIgnoreCase("integer")) { - if (rowsVals.containsKey(colName)) { - stmt.setInt(idx, Integer.parseInt(rowsVals.get(colName))); - } else { - stmt.setNull(idx, Types.INTEGER); - } - } else { - // colType.equalsIgnoreCase("text") || colType.startsWith("varchar") - if (rowsVals.containsKey(colName)) { - stmt.setString(idx, rowsVals.get(colName)); - } else { - stmt.setString(idx, null); - } - } - idx += 1; - } - if (CodeTableConstants.isCourtTable(tableName)) { - stmt.setString(idx, courtName); - idx += 1; - } - stmt.setString(idx, jurisStr()); - return stmt; - } - @Override public List searchCaseCategory(String searchTerm) { return genericSearch( diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeTableConstants.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeTableConstants.java index 4544b09d..5dd52664 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeTableConstants.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/tyler/ecfcodes/CodeTableConstants.java @@ -1,13 +1,15 @@ package edu.suffolk.litlab.efsp.tyler.ecfcodes; +import static edu.suffolk.litlab.efsp.ecfcodes.CodeDatabaseUtils.createInsertQuery; +import static edu.suffolk.litlab.efsp.ecfcodes.CodeDatabaseUtils.createTableQuery; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; +import edu.suffolk.litlab.efsp.ecfcodes.CodeDatabaseUtils.Column; +import edu.suffolk.litlab.efsp.ecfcodes.CodeDatabaseUtils.TableColumns; import edu.suffolk.litlab.efsp.ecfcodes.CodeDatabaseUtils.UnsupportedTableException; public class CodeTableConstants { @@ -22,307 +24,307 @@ public class CodeTableConstants { private static final Map deleteAllCourtsFromQueries = new HashMap<>(); static { - List> locationColumns = new ArrayList>(); - locationColumns.add(new ImmutablePair("code", "text")); - locationColumns.add(new ImmutablePair("name", "text")); - locationColumns.add(new ImmutablePair("initial", "text")); - locationColumns.add(new ImmutablePair("subsequent", "text")); - locationColumns.add(new ImmutablePair("disallowcopyingenvelopemultipletimes", "text")); - locationColumns.add(new ImmutablePair("allowfilingintononindexedcase", "text")); - locationColumns.add(new ImmutablePair("allowablecardtypes", "text")); - locationColumns.add(new ImmutablePair("odysseynodeid", "text")); - locationColumns.add(new ImmutablePair("cmsid", "text")); - locationColumns.add(new ImmutablePair("sendservicebeforereview", "text")); - locationColumns.add(new ImmutablePair("parentnodeid", "text")); - locationColumns.add(new ImmutablePair("iscounty", "text")); - locationColumns.add(new ImmutablePair("restrictbankaccountpayment", "text")); - locationColumns.add(new ImmutablePair("allowmultipleattorneys", "text")); - locationColumns.add(new ImmutablePair("sendservicecontactremovednotifications", "text")); - locationColumns.add(new ImmutablePair("allowmaxfeeamount", "text")); - locationColumns.add(new ImmutablePair("transferwaivedfeestocms", "text")); - locationColumns.add(new ImmutablePair("skippreauth", "text")); - locationColumns.add(new ImmutablePair("allowhearing", "text")); - locationColumns.add(new ImmutablePair("allowreturndate", "text")); - locationColumns.add(new ImmutablePair("showdamageamount", "text")); // Isn't in document anymore? - locationColumns.add(new ImmutablePair("hasconditionalservicetypes", "text")); - locationColumns.add(new ImmutablePair("hasprotectedcasetypes", "text")); - locationColumns.add(new ImmutablePair("protectedcasetypes", "text")); - locationColumns.add(new ImmutablePair("allowzerofeeswithoutfilingparty", "text")); - locationColumns.add(new ImmutablePair("allowserviceoninitial", "text")); - locationColumns.add(new ImmutablePair("allowaddservicecontactsoninitial", "text")); - locationColumns.add(new ImmutablePair("allowredaction", "text")); - locationColumns.add(new ImmutablePair("redactionurl", "text")); - locationColumns.add(new ImmutablePair("redactionviewerurl", "text")); - locationColumns.add(new ImmutablePair("redactiontargetconfig", "text")); - locationColumns.add(new ImmutablePair("enforceredaction", "text")); - locationColumns.add(new ImmutablePair("redactiondocumenttype", "text")); - locationColumns.add(new ImmutablePair("defaultdocumentdescription", "text")); - locationColumns.add(new ImmutablePair("allowwaiveronmail", "text")); - locationColumns.add(new ImmutablePair("showreturnonreject", "text")); - locationColumns.add(new ImmutablePair("protectedcasereplacementstring", "text")); - locationColumns.add(new ImmutablePair("allowchargeupdate", "text")); // Isn't in document anymore? - locationColumns.add(new ImmutablePair("allowpartyid", "text")); // Isn't in documentation anymore? - locationColumns.add(new ImmutablePair("redactionfee", "text")); - locationColumns.add(new ImmutablePair("allowwaiveronredaction", "text")); - locationColumns.add(new ImmutablePair("disallowelectronicserviceonnewcontacts", "text")); - locationColumns.add(new ImmutablePair("allowindividualregistration", "text")); + List locationColumns = new ArrayList(); + locationColumns.add(new Column("code", "text")); + locationColumns.add(new Column("name", "text")); + locationColumns.add(new Column("initial", "text")); + locationColumns.add(new Column("subsequent", "text")); + locationColumns.add(new Column("disallowcopyingenvelopemultipletimes", "text")); + locationColumns.add(new Column("allowfilingintononindexedcase", "text")); + locationColumns.add(new Column("allowablecardtypes", "text")); + locationColumns.add(new Column("odysseynodeid", "text")); + locationColumns.add(new Column("cmsid", "text")); + locationColumns.add(new Column("sendservicebeforereview", "text")); + locationColumns.add(new Column("parentnodeid", "text")); + locationColumns.add(new Column("iscounty", "text")); + locationColumns.add(new Column("restrictbankaccountpayment", "text")); + locationColumns.add(new Column("allowmultipleattorneys", "text")); + locationColumns.add(new Column("sendservicecontactremovednotifications", "text")); + locationColumns.add(new Column("allowmaxfeeamount", "text")); + locationColumns.add(new Column("transferwaivedfeestocms", "text")); + locationColumns.add(new Column("skippreauth", "text")); + locationColumns.add(new Column("allowhearing", "text")); + locationColumns.add(new Column("allowreturndate", "text")); + locationColumns.add(new Column("showdamageamount", "text")); // Isn't in document anymore? + locationColumns.add(new Column("hasconditionalservicetypes", "text")); + locationColumns.add(new Column("hasprotectedcasetypes", "text")); + locationColumns.add(new Column("protectedcasetypes", "text")); + locationColumns.add(new Column("allowzerofeeswithoutfilingparty", "text")); + locationColumns.add(new Column("allowserviceoninitial", "text")); + locationColumns.add(new Column("allowaddservicecontactsoninitial", "text")); + locationColumns.add(new Column("allowredaction", "text")); + locationColumns.add(new Column("redactionurl", "text")); + locationColumns.add(new Column("redactionviewerurl", "text")); + locationColumns.add(new Column("redactiontargetconfig", "text")); + locationColumns.add(new Column("enforceredaction", "text")); + locationColumns.add(new Column("redactiondocumenttype", "text")); + locationColumns.add(new Column("defaultdocumentdescription", "text")); + locationColumns.add(new Column("allowwaiveronmail", "text")); + locationColumns.add(new Column("showreturnonreject", "text")); + locationColumns.add(new Column("protectedcasereplacementstring", "text")); + locationColumns.add(new Column("allowchargeupdate", "text")); // Isn't in document anymore? + locationColumns.add(new Column("allowpartyid", "text")); // Isn't in documentation anymore? + locationColumns.add(new Column("redactionfee", "text")); + locationColumns.add(new Column("allowwaiveronredaction", "text")); + locationColumns.add(new Column("disallowelectronicserviceonnewcontacts", "text")); + locationColumns.add(new Column("allowindividualregistration", "text")); TableColumns locationTc = makeTableColumnInfo(false, locationColumns); tableColumns = Map.ofEntries( Map.entry("location", locationTc), Map.entry("error", makeSystemColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text")))), + new Column("code", "text"), + new Column("name", "text")))), Map.entry("version", makeSystemColumnInfo(List.of( - new ImmutablePair("location", "text"), - new ImmutablePair("codelist", "text"), - new ImmutablePair("version", "text")))), + new Column("location", "text"), + new Column("codelist", "text"), + new Column("version", "text")))), // custom table, the version that's currently installed // Custom table so we can just drop the existing version table when updating. Map.entry("installedversion", makeTableColumnInfo(false, List.of( - new ImmutablePair("location", "text"), - new ImmutablePair("codelist", "text"), - new ImmutablePair("installedversion", "text")), + new Column("location", "text"), + new Column("codelist", "text"), + new Column("installedversion", "text")), List.of("location", "codelist", "jurisdiction"))), //////////// Tables that are both system wide, and court specific Map.entry("country", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text")))), + new Column("code", "text"), + new Column("name", "text")))), Map.entry("state", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("countrycode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("countrycode", "text")))), Map.entry("filingstatus", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text")))), + new Column("code", "text"), + new Column("name", "text")))), Map.entry("datafieldconfig", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "varchar(80)"), - new ImmutablePair("name", "text"), - new ImmutablePair("isvisible", "boolean"), - new ImmutablePair("isrequired", "boolean"), - new ImmutablePair("helptext", "text"), - new ImmutablePair("ghosttext", "text"), - new ImmutablePair("contextualhelpdata", "text"), - new ImmutablePair("validationmessage", "text"), - new ImmutablePair("regularexpression", "text"), - new ImmutablePair("defaultvalueexpression", "text"), - new ImmutablePair("isreadonly", "boolean")))), + new Column("code", "varchar(80)"), + new Column("name", "text"), + new Column("isvisible", "boolean"), + new Column("isrequired", "boolean"), + new Column("helptext", "text"), + new Column("ghosttext", "text"), + new Column("contextualhelpdata", "text"), + new Column("validationmessage", "text"), + new Column("regularexpression", "text"), + new Column("defaultvalueexpression", "text"), + new Column("isreadonly", "boolean")))), ///////// Tables for courts specifically Map.entry("answer", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("answertext", "text"), - new ImmutablePair("questionid", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("answertext", "text"), + new Column("questionid", "text"), + new Column("efspcode", "text")))), Map.entry("arrestlocation", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("bond", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("casecategory", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("ecfcasetype", "text"), - new ImmutablePair("procedureremedyinitial", "text"), - new ImmutablePair("procedureremedysubsequent", "text"), - new ImmutablePair("damageamountinitial", "text"), - new ImmutablePair("damageamountsubsequent", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("ecfcasetype", "text"), + new Column("procedureremedyinitial", "text"), + new Column("procedureremedysubsequent", "text"), + new Column("damageamountinitial", "text"), + new Column("damageamountsubsequent", "text"), + new Column("efspcode", "text")))), Map.entry("casesubtype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("casetypeid", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("casetypeid", "text"), + new Column("efspcode", "text")))), Map.entry("casetype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "varchar(40)"), - new ImmutablePair("name", "text"), - new ImmutablePair("casecategory", "text"), - new ImmutablePair("initial", "text"), - new ImmutablePair("fee", "text"), - new ImmutablePair("willfileddate", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "varchar(40)"), + new Column("name", "text"), + new Column("casecategory", "text"), + new Column("initial", "text"), + new Column("fee", "text"), + new Column("willfileddate", "text"), + new Column("efspcode", "text")))), Map.entry("chargephase", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("citationjurisdiction", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("crossreference", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("casetypeid", "text"), - new ImmutablePair("isdefault", "text"), - new ImmutablePair("isrequired", "text"), - new ImmutablePair("validationregex", "text"), - new ImmutablePair("customvalidationfailuremessage", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("casetypeid", "text"), + new Column("isdefault", "text"), + new Column("isrequired", "text"), + new Column("validationregex", "text"), + new Column("customvalidationfailuremessage", "text"), + new Column("efspcode", "text")))), Map.entry("damageamount", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("casecategory", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("casecategory", "text"), + new Column("efspcode", "text")))), Map.entry("degree", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("statuecodeid", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("statuecodeid", "text"), + new Column("efspcode", "text")))), Map.entry("disclaimerrequirement", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("listorder", "text"), - new ImmutablePair<>("requirementtext", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("listorder", "text"), + new Column("requirementtext", "text"), + new Column("efspcode", "text")))), Map.entry("driverlicensetype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("documenttype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("filingcodeid", "text"), - new ImmutablePair("iscourtuseonly", "text"), - new ImmutablePair("isdefault", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("filingcodeid", "text"), + new Column("iscourtuseonly", "text"), + new Column("isdefault", "text"), + new Column("efspcode", "text")))), Map.entry("ethnicity", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("eyecolor", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("filertype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("default", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("default", "text"), + new Column("efspcode", "text")))), Map.entry("filetype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("extension", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("extension", "text"), + new Column("efspcode", "text")))), Map.entry("filing", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "varchar(40)"), - new ImmutablePair("name", "text"), - new ImmutablePair("fee", "text"), - new ImmutablePair("casecategory", "text"), - new ImmutablePair("casetypeid", "text"), - new ImmutablePair("filingtype", "text"), - new ImmutablePair("iscourtuseonly", "boolean"), - new ImmutablePair("civilclaimamount", "text"), - new ImmutablePair("probateestateamount", "text"), - new ImmutablePair("amountincontroversy", "text"), - new ImmutablePair("useduedate", "boolean"), - new ImmutablePair("isproposedorder", "boolean"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "varchar(40)"), + new Column("name", "text"), + new Column("fee", "text"), + new Column("casecategory", "text"), + new Column("casetypeid", "text"), + new Column("filingtype", "text"), + new Column("iscourtuseonly", "boolean"), + new Column("civilclaimamount", "text"), + new Column("probateestateamount", "text"), + new Column("amountincontroversy", "text"), + new Column("useduedate", "boolean"), + new Column("isproposedorder", "boolean"), + new Column("efspcode", "text")))), Map.entry("filingcomponent", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "varchar(40)"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("filingcodeid", "varchar(40)"), - new ImmutablePair<>("required", "boolean"), - new ImmutablePair<>("allowmultiple", "boolean"), - new ImmutablePair<>("displayorder", "integer"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "varchar(40)"), + new Column("name", "text"), + new Column("filingcodeid", "varchar(40)"), + new Column("required", "boolean"), + new Column("allowmultiple", "boolean"), + new Column("displayorder", "integer"), + new Column("efspcode", "text")))), Map.entry("generaloffense", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("statutecodeid", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("statutecodeid", "text"), + new Column("efspcode", "text")))), Map.entry("haircolor", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("language", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("lawenforcementunit", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("motiontype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("filingcodeid", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("filingcodeid", "text"), + new Column("efspcode", "text")))), Map.entry("namesuffix", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("partytype", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "varchar(40)"), - new ImmutablePair("name", "text"), - new ImmutablePair("isavailablefornewparties", "boolean"), - new ImmutablePair("casetypeid", "text"), - new ImmutablePair("isrequired", "boolean"), - new ImmutablePair("amount", "text"), - new ImmutablePair("numberofpartiestoignore", "text"), - new ImmutablePair("sendforredaction", "text"), - new ImmutablePair("dateofdeath", "text"), - new ImmutablePair("displayorder", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "varchar(40)"), + new Column("name", "text"), + new Column("isavailablefornewparties", "boolean"), + new Column("casetypeid", "text"), + new Column("isrequired", "boolean"), + new Column("amount", "text"), + new Column("numberofpartiestoignore", "text"), + new Column("sendforredaction", "text"), + new Column("dateofdeath", "text"), + new Column("displayorder", "text"), + new Column("efspcode", "text")))), Map.entry("physicalfeature", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("procedureremedy",makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("casecategory", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("casecategory", "text"), + new Column("efspcode", "text")))), Map.entry("question", makeCourtColumnInfo(List.of( - new ImmutablePair("code", "text"), - new ImmutablePair("name", "text"), - new ImmutablePair("questiontext", "text"), - new ImmutablePair("helptext", "text"), - new ImmutablePair("isrequired", "text"), - new ImmutablePair("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("questiontext", "text"), + new Column("helptext", "text"), + new Column("isrequired", "text"), + new Column("efspcode", "text")))), Map.entry("race", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("servicetype", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("servicemethod", "text"), - new ImmutablePair<>("fee", "text"), - new ImmutablePair<>("disclaimertext", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("servicemethod", "text"), + new Column("fee", "text"), + new Column("disclaimertext", "text")))), Map.entry("statute", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("word", "text"), - new ImmutablePair<>("referenceid", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("word", "text"), + new Column("referenceid", "text"), + new Column("efspcode", "text")))), Map.entry("statutetype", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("vehiclecolor", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("vehiclemake", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("vehicletype", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))), + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))), Map.entry("refundreason", makeCourtColumnInfo(List.of( - new ImmutablePair<>("code", "text"), - new ImmutablePair<>("name", "text"), - new ImmutablePair<>("efspcode", "text")))) + new Column("code", "text"), + new Column("name", "text"), + new Column("efspcode", "text")))) ); for (Map.Entry table : tableColumns.entrySet()) { createQueries.put(table.getKey(), createTableQuery(table.getKey(), table.getValue())); insertQueries.put(table.getKey(), createInsertQuery(table.getKey(), table.getValue())); deleteAllCourtsFromQueries.put(table.getKey(), "DELETE FROM " + table.getKey() + " WHERE jurisdiction=?"); - if (table.getValue().needsExtraLocCol) { + if (table.getValue().needsExtraLocCol()) { deleteFromQueries.put(table.getKey(), "DELETE FROM " + table.getKey() + " WHERE jurisdiction=? AND location=?"); } } @@ -346,48 +348,29 @@ public static String getZipNameFromTable(String tableName) { } } - private static class TableColumns { - public List> mainList = List.of(); - public List primaryKeys = List.of(); - public boolean needsExtraLocCol = false; - } - - private static TableColumns makeCourtColumnInfo(List> mainList) { + private static TableColumns makeCourtColumnInfo(List mainList) { return makeTableColumnInfo(true, mainList, List.of()); } - private static TableColumns makeSystemColumnInfo(List> mainList) { + private static TableColumns makeSystemColumnInfo(List mainList) { return makeTableColumnInfo(false, mainList, List.of()); } private static TableColumns makeTableColumnInfo(boolean needsExtraLocCol, - List> mainList) { + List mainList) { return makeTableColumnInfo(needsExtraLocCol, mainList, List.of()); } private static TableColumns makeTableColumnInfo(boolean needsExtraLocCol, - List> mainList, List primaryKeys) { - TableColumns tableCols = new TableColumns(); - tableCols.mainList = mainList; - tableCols.primaryKeys = primaryKeys; - tableCols.needsExtraLocCol = needsExtraLocCol; + List mainList, List primaryKeys) { + TableColumns tableCols = new TableColumns(mainList, primaryKeys, needsExtraLocCol); return tableCols; } - public static List getTableColumns(String tableName) { - // Drops the type in the column name + type pairs. - return tableColumns.getOrDefault(tableName, new TableColumns()) - .mainList.stream().map((e) -> e.getLeft()).collect(Collectors.toList()); - } - - public static List> getTableColumnsWithType(String tableName) { - return tableColumns.getOrDefault(tableName, new TableColumns()).mainList; + public static TableColumns getTableColumns(String tableName) { + return tableColumns.getOrDefault(tableName, new TableColumns(List.of(), List.of(), false)); } - public static boolean isCourtTable(String tableName) { - return tableColumns.getOrDefault(tableName, new TableColumns()).needsExtraLocCol; - } - public static String updateVersion() { return """ INSERT INTO installedversion (location, codelist, installedversion, jurisdiction) VALUES(?, ?, ?, ?) @@ -443,7 +426,7 @@ public static String vacuumAnalyzeAll() { public static boolean tableHasLocation(String tableName) { - return tableColumns.containsKey(tableName) && tableColumns.get(tableName).needsExtraLocCol; + return tableColumns.containsKey(tableName) && tableColumns.get(tableName).needsExtraLocCol(); } public static String getCreateTable(String tableName) throws UnsupportedTableException { @@ -480,69 +463,4 @@ public static String getDeleteAllCourtsFrom(String tableName) throws Unsupported } return deleteAllCourtsFromQueries.get(tableName); } - - /** - * Returns an INSERT statement for the given table + court. The statement - * includes a ON CONFLICT (all columns...) DO NOTHING clause. - * - * @param tableName The name of the DB table (i.e. code list) to insert into - * @param courtName The Court Location ID to add codes for - */ - private static String createInsertQuery(String tableName, TableColumns tc) { - StringBuilder insertLocation = new StringBuilder(); - insertLocation.append("INSERT INTO \"" + tableName + "\" ("); - StringBuilder colNames = new StringBuilder(); - boolean isFirst = true; - for (Pair col : tc.mainList) { - if (isFirst) { - isFirst = false; - } else { - colNames.append(", "); - } - colNames.append("\"" + col.getLeft() + "\""); - } - if (tc.needsExtraLocCol) { - colNames.append(", location"); - } - colNames.append(", jurisdiction"); - insertLocation.append(colNames.toString()); - insertLocation.append(") VALUES ("); - for (int i = 0; i < tc.mainList.size(); i++) { - if (i > 0) { - insertLocation.append(", "); - } - insertLocation.append("?"); - } - if (tc.needsExtraLocCol) { - insertLocation.append(", ?"); - } - insertLocation.append(", ?"); - insertLocation.append(")"); - return insertLocation.toString(); - } - - private static String createTableQuery(String tableName, TableColumns tc) { - StringBuilder createLocation = new StringBuilder(); - createLocation.append("CREATE TABLE " + tableName + "("); - boolean isFirst = true; - for (Pair col : tc.mainList) { - if (isFirst) { - isFirst = false; - } else { - createLocation.append(", "); - } - createLocation.append("\"" + col.getLeft() + "\" " + col.getRight()); - } - if (tc.needsExtraLocCol) { - createLocation.append(", \"location\" varchar(80)"); - } - createLocation.append(", \"jurisdiction\" varchar(80)"); - - if (!tc.primaryKeys.isEmpty()) { - createLocation.append( - ", PRIMARY KEY(" + tc.primaryKeys.stream().collect(Collectors.joining(",")) + ")"); - } - createLocation.append(")"); - return createLocation.toString(); - } } diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/ecfcodes/tyler/CodeDatabaseTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/ecfcodes/tyler/CodeDatabaseTest.java index fa6591b3..6ed75e7f 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/ecfcodes/tyler/CodeDatabaseTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/ecfcodes/tyler/CodeDatabaseTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import edu.suffolk.litlab.efsp.Jurisdiction; @@ -12,7 +11,6 @@ import edu.suffolk.litlab.efsp.tyler.ecfcodes.CaseCategory; import edu.suffolk.litlab.efsp.tyler.ecfcodes.CaseType; import edu.suffolk.litlab.efsp.tyler.ecfcodes.CodeDatabase; -import edu.suffolk.litlab.efsp.tyler.ecfcodes.CodeTableConstants; import edu.suffolk.litlab.efsp.tyler.ecfcodes.CourtLocationInfo; import edu.suffolk.litlab.efsp.tyler.ecfcodes.OptionalServiceCode; import edu.suffolk.litlab.efsp.tyler.ecfcodes.ServiceCodeType; @@ -63,8 +61,6 @@ public void tearDown() throws SQLException { public void allNamespacesMapToTables() { for (String table : cd.xmlElemToTableName().values()) { if (!table.equalsIgnoreCase("optionalservices")) { - assertNotEquals( - CodeTableConstants.getTableColumns(table).size(), 0, "Expected " + table + " to exist"); assertTrue(table.length() <= 63, "table name " + table + " should be <= 63 characters"); } }