diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 282155441..cdef2fb9d 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -8126,21 +8126,20 @@ GET https://DomainName/api/v1/datatables POST https://DomainName/api/v1/datatables/register/{datatable}/{apptable} -POST datatables/register/userDefinedTableName/m_client +POST datatables/register/extra_client_details/m_client Content-Type: application/json Request Body: {} -{ - "resourceId": null +{ + "resourceIdentifier": "extra_client_details" } -  
@@ -8154,7 +8153,7 @@ Request Body: POST https://DomainName/api/v1/datatables/deregister/{datatable} -POST datatables/deregister/userDefinedTableName +POST datatables/deregister/extra_client_details Content-Type: application/json Request Body: @@ -8162,8 +8161,8 @@ Request Body: { - "resourceId": null -} + "resourceIdentifier": "extra_client_details" +}
@@ -8186,20 +8185,20 @@ Request Body: POST https://DomainName/api/v1/datatables/{datatable}/{apptableId} -POST datatables/Additional Client Fields Data/1 +POST datatables/extra_client_details/1 Content-Type: application/json Request Body: { "Business Description": "Livestock sales", - Comment: "First comment\nmade", - Education_cv: "Trade", - Gender_cd: "21", + "Comment": "First comment made", + "Education_cv": "Primary", + "Gender_cd": "6", "Highest Rate Paid": "8.5", "Next Visit": "01 October 2012", "Years in Business": "5", - dateFormat: "dd MMMM yyyy", - locale: "en" + "dateFormat": "dd MMMM yyyy", + "locale": "en" } @@ -8235,46 +8234,142 @@ Request Body:
optional
-
If 'true' a Generic Result Set JSON format is returned. +
If 'true' an optimised JSON format is returned suitable for tabular display of data. This format is used by the default data tables UI functionality.

Example Requests:

-
datatables/Additional Client Fields - Data/1
+
datatables/extra_client_details/1


-
datatables/Extra Family Details - Data/1?order=`Date of Birth` desc
+
datatables/extra_family_details/1?order=`Date of Birth` desc


-
datatables/Additional Client Fields - Data/1?genericResultSet=true
+
datatables/extra_client_details/1?genericResultSet=true
-GET https://DomainName/api/v1/datatables/{datatable}/{apptableId} +GET https://DomainName/api/v1/datatables/{datatable}/{apptableId}?genericResultSet=true -[ { - "client_id": 1, - "Business Description": "Livestock sales", - "Years in Business": 5, - "Gender_cd": "21", - "Education_cv": "Trade", - "Next Visit": [2012, 10, 1], - "Highest Rate Paid": 8.500000, - "Comment": "First comment made" -} -] + "columnHeaders": [ + { + "columnName": "client_id", + "columnType": "bigint", + "columnLength": 0, + "columnDisplayType": "INTEGER", + "isColumnNullable": false, + "isColumnPrimaryKey": true, + "columnValues": [] + }, + { + "columnName": "Business Description", + "columnType": "varchar", + "columnLength": 100, + "columnDisplayType": "STRING", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [] + }, + { + "columnName": "Years in Business", + "columnType": "int", + "columnLength": 0, + "columnDisplayType": "INTEGER", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [] + }, + { + "columnName": "Gender_cd", + "columnType": "int", + "columnLength": 0, + "columnDisplayType": "CODELOOKUP", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [ + { + "id": 5, + "value": "option.Male" + }, + { + "id": 6, + "value": "option.Female" + } + ] + }, + { + "columnName": "Education_cv", + "columnType": "varchar", + "columnLength": 60, + "columnDisplayType": "CODEVALUE", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [ + { + "id": 9, + "value": "Primary" + }, + { + "id": 10, + "value": "Secondary" + }, + { + "id": 11, + "value": "University" + } + ] + }, + { + "columnName": "Next Visit", + "columnType": "date", + "columnLength": 0, + "columnDisplayType": "DATE", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [] + }, + { + "columnName": "Highest Rate Paid", + "columnType": "decimal", + "columnLength": 0, + "columnDisplayType": "DECIMAL", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [] + }, + { + "columnName": "Comment", + "columnType": "text", + "columnLength": 65535, + "columnDisplayType": "TEXT", + "isColumnNullable": true, + "isColumnPrimaryKey": false, + "columnValues": [] + } + ], + "data": [ + { + "row": [ + "1", + "Livestock sales", + "5", + "6", + "Primary", + "2012-10-01", + "8.500000", + "First\tcomment made" + ] + } + ] +}
-   +  

Update Entry in Data Table (One to One)

@@ -8285,23 +8380,22 @@ GET https://DomainName/api/v1/datatables/{datatable}/{apptableId} PUT https://DomainName/api/v1/datatables/{datatable}/{apptableId}
-PUT datatables/Additional Client Fields Data/1 +PUT datatables/extra_client_details/1 Content-Type: application/json Request Body: -{ - "Business Description": "Livestock sales updated", - Comment: "First comment\nmade", - Education_cv: "Trade", - Gender_cd: "21", - "Highest Rate Paid": "8.5", - "Next Visit": "01 October 2012", - "Years in Business": "5", - dateFormat: "dd MMMM yyyy", - locale: "en" -} +{ + "Business Description": "Livestock sales updated", +} + + +{ + "resourceId": 1, + "changes": { + "Business Description": "Livestock sales updated" + } +} - { "resourceId": 1 }
@@ -8385,8 +8479,7 @@ Request Body: { "resourceId": 1 } - - +   diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResult.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResult.java index 7f2c7372f..c47864cae 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResult.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResult.java @@ -19,13 +19,17 @@ public class CommandProcessingResult { private final Long groupId; private final Long clientId; private final Long loanId; - private Long resourceId; + private final Long resourceId; private final String transactionId; - private Map changes; + private final Map changes; + @SuppressWarnings("unused") + private final String resourceIdentifier; public static CommandProcessingResult fromDetails(final Long commandId, final Long officeId, final Long groupId, final Long clientId, - final Long loanId, final Long entityId, final String transactionId, final Map changes) { - return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, entityId, transactionId, changes); + final Long loanId, final String resourceIdentifier, final Long entityId, final String transactionId, + final Map changes) { + return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, resourceIdentifier, entityId, transactionId, + changes); } public static CommandProcessingResult commandOnlyResult(final Long commandId) { @@ -54,10 +58,18 @@ public class CommandProcessingResult { } public static CommandProcessingResult empty() { - return new CommandProcessingResult(Long.valueOf(-1), Long.valueOf(-1), Long.valueOf(-1), null); + return new CommandProcessingResult(null, null, null, null); } + /* + * Deprecated + */ public CommandProcessingResult(final Long entityId) { + if (entityId != null) { + this.resourceIdentifier = entityId.toString(); + } else { + this.resourceIdentifier = null; + } this.resourceId = entityId; this.officeId = null; this.groupId = null; @@ -68,18 +80,24 @@ public class CommandProcessingResult { } private CommandProcessingResult(final Long commandId, final Long officeId, final Long groupId, final Long clientId, final Long loanId, - final Long resourceId, final String transactionId, final Map changesOnly) { + final String resourceIdentifier, final Long resourceId, final String transactionId, final Map changesOnly) { this.commandId = commandId; this.officeId = officeId; this.groupId = groupId; this.clientId = clientId; this.loanId = loanId; + this.resourceIdentifier = resourceIdentifier; this.resourceId = resourceId; this.changes = changesOnly; this.transactionId = transactionId; } private CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId, final Map changesOnly) { + if (resourceId != null) { + this.resourceIdentifier = resourceId.toString(); + } else { + this.resourceIdentifier = null; + } this.resourceId = resourceId; this.officeId = officeId; this.groupId = null; @@ -102,7 +120,7 @@ public class CommandProcessingResult { return this.officeId; } - public void setOfficeId(Long officeId) { + public void setOfficeId(final Long officeId) { this.officeId = officeId; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResultBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResultBuilder.java index fe0664c11..227e425ac 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResultBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/CommandProcessingResultBuilder.java @@ -18,12 +18,14 @@ public class CommandProcessingResultBuilder { private Long groupId; private Long clientId; private Long loanId; + private String resourceIdentifier; private Long entityId; private String transactionId; private Map changes; public CommandProcessingResult build() { - return CommandProcessingResult.fromDetails(commandId, officeId, groupId, clientId, loanId, entityId, transactionId, changes); + return CommandProcessingResult.fromDetails(commandId, officeId, groupId, clientId, loanId, resourceIdentifier, entityId, + transactionId, changes); } public CommandProcessingResultBuilder withCommandId(final Long withCommandId) { @@ -36,6 +38,11 @@ public class CommandProcessingResultBuilder { return this; } + public CommandProcessingResultBuilder withResourceIdAsString(final String withResourceIdentifier) { + this.resourceIdentifier = withResourceIdentifier; + return this; + } + public CommandProcessingResultBuilder withEntityId(final Long withEntityId) { this.entityId = withEntityId; return this; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DatatablesApiResource.java similarity index 92% rename from mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java rename to mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DatatablesApiResource.java index 6d7bbe946..f8eea1764 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DatatablesApiResource.java @@ -25,6 +25,7 @@ import org.mifosplatform.commands.service.CommandWrapperBuilder; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer; import org.mifosplatform.infrastructure.dataqueries.data.DatatableData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; @@ -38,7 +39,7 @@ import org.springframework.stereotype.Component; @Path("/datatables") @Component @Scope("singleton") -public class DataTableApiResource { +public class DatatablesApiResource { private final PlatformSecurityContext context; private final GenericDataService genericDataService; @@ -47,7 +48,7 @@ public class DataTableApiResource { private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired - public DataTableApiResource(final PlatformSecurityContext context, final GenericDataService genericDataService, + public DatatablesApiResource(final PlatformSecurityContext context, final GenericDataService genericDataService, final ReadWriteNonCoreDataService readWriteNonCoreDataService, final ToApiJsonSerializer toApiJsonSerializer, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { @@ -77,7 +78,9 @@ public class DataTableApiResource { this.readWriteNonCoreDataService.registerDatatable(datatable, apptable); - return this.toApiJsonSerializer.serialize(CommandProcessingResult.empty()); + final CommandProcessingResult result = new CommandProcessingResultBuilder().withResourceIdAsString(datatable).build(); + + return this.toApiJsonSerializer.serialize(result); } @POST @@ -88,7 +91,9 @@ public class DataTableApiResource { this.readWriteNonCoreDataService.deregisterDatatable(datatable); - return this.toApiJsonSerializer.serialize(CommandProcessingResult.empty()); + final CommandProcessingResult result = new CommandProcessingResultBuilder().withResourceIdAsString(datatable).build(); + + return this.toApiJsonSerializer.serialize(result); } @GET @@ -143,7 +148,7 @@ public class DataTableApiResource { @Path("{datatable}/{apptableId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String newDatatableEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId, + public String createDatatableEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId, final String apiRequestBodyAsJson) { final CommandWrapper commandRequest = new CommandWrapperBuilder().createDatatable(datatable, apptableId, null) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/DataTableNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/DataTableNotFoundException.java index a9ca13175..a82da4fb6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/DataTableNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/DataTableNotFoundException.java @@ -10,15 +10,13 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN /** * A {@link RuntimeException} thrown when client resources are not found. */ -public class DataTableNotFoundException extends AbstractPlatformResourceNotFoundException { +public class DatatableNotFoundException extends AbstractPlatformResourceNotFoundException { - public DataTableNotFoundException(final String datatable, Long id) { - super("error.msg.datatable.data.not.found", "Data Not Found for Data Table: ", - datatable + " Id:" + id); - } - - public DataTableNotFoundException(final String datatable) { - super("error.msg.datatable.not.found", "Data Table Not Found", - datatable); - } + public DatatableNotFoundException(final String datatable, final Long id) { + super("error.msg.datatable.data.not.found", "Data not found for datatable: ", datatable + " Id:" + id); + } + + public DatatableNotFoundException(final String datatable) { + super("error.msg.datatable.not.found", "Datatable not found.", datatable); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/ReportNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/ReportNotFoundException.java index a93005f46..29595da0e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/ReportNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/exception/ReportNotFoundException.java @@ -13,6 +13,6 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN public class ReportNotFoundException extends AbstractPlatformResourceNotFoundException { public ReportNotFoundException(final String reportSql) { - super("error.msg.report.name.not.found", "Reporting Meta Data Entry Not Found", "Input Sql: " + reportSql); + super("error.msg.report.name.not.found", "Reporting meta-data entry not found.", "Input sql: " + reportSql); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/handler/CreateDatatableEntryCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/handler/CreateDatatableEntryCommandHandler.java index 46c23f017..a91c10f2c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/handler/CreateDatatableEntryCommandHandler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/handler/CreateDatatableEntryCommandHandler.java @@ -12,7 +12,6 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder import org.mifosplatform.infrastructure.dataqueries.service.ReadWriteNonCoreDataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service public class CreateDatatableEntryCommandHandler implements NewCommandSourceHandler { @@ -24,11 +23,10 @@ public class CreateDatatableEntryCommandHandler implements NewCommandSourceHandl this.writePlatformService = writePlatformService; } - @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - this.writePlatformService.newDatatableEntry(command.entityName(), command.getApptableId(), command); + this.writePlatformService.createNewDatatableEntry(command.entityName(), command.getApptableId(), command); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataService.java index 7d0a43d1c..9296855d6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataService.java @@ -20,7 +20,5 @@ public interface GenericDataService { String wrapSQL(String sql); - String getDatabaseName(); - List fillResultsetColumnHeaders(String datatable); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java index 62825f6f1..af062e423 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java @@ -5,20 +5,18 @@ */ package org.mifosplatform.infrastructure.dataqueries.service; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import org.joda.time.LocalDate; -import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnValueData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData; -import org.mifosplatform.infrastructure.dataqueries.exception.DataTableNotFoundException; +import org.mifosplatform.infrastructure.dataqueries.exception.DatatableNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.rowset.SqlRowSet; @@ -168,15 +166,6 @@ public class GenericDataServiceImpl implements GenericDataService { } - @Override - public String getDatabaseName() { - try { - return dataSource.getConnection().getCatalog(); - } catch (SQLException e) { - throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Error Accessing Database Name"); - } - } - @Override public List fillResultsetColumnHeaders(final String datatable) { @@ -249,6 +238,6 @@ public class GenericDataServiceImpl implements GenericDataService { final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql); if (columnDefinitions.next()) { return columnDefinitions; } - throw new DataTableNotFoundException(datatable); + throw new DatatableNotFoundException(datatable); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java index c6215f1a8..acccce265 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java @@ -25,7 +25,7 @@ public interface ReadWriteNonCoreDataService { GenericResultsetData retrieveDataTableGenericResultSet(String datatable, Long appTableId, String order, Long id); - void newDatatableEntry(String datatable, Long appTableId, JsonCommand command); + void createNewDatatableEntry(String datatable, Long appTableId, JsonCommand command); Map updateDatatableEntryOneToOne(String datatable, Long appTableId, JsonCommand command); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java index b2fe582aa..bd0d3a12e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java @@ -17,6 +17,7 @@ import java.util.Set; import javax.sql.DataSource; import org.apache.commons.lang.StringUtils; +import org.hibernate.exception.ConstraintViolationException; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.ApiParameterError; @@ -29,12 +30,14 @@ import org.mifosplatform.infrastructure.dataqueries.data.DatatableData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData; -import org.mifosplatform.infrastructure.dataqueries.exception.DataTableNotFoundException; +import org.mifosplatform.infrastructure.dataqueries.exception.DatatableNotFoundException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.useradministration.domain.AppUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSetMetaData; @@ -96,63 +99,89 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ return datatables; } + private void logAsErrorUnexpectedDataIntegrityException(final Exception dve) { + logger.error(dve.getMessage(), dve); + } + @Override - public void registerDatatable(final String datatable, final String appTable) { + public void registerDatatable(final String dataTableName, final String applicationTableName) { - validateAppTable(appTable); + // FIXME - KW - hardcoded supported app tables are m_loan or m_client? + validateAppTable(applicationTableName); - final String createPermission = "'CREATE_" + datatable + "'"; - final String createPermissionChecker = "'CREATE_" + datatable + "_CHECKER'"; - final String readPermission = "'READ_" + datatable + "'"; - final String updatePermission = "'UPDATE_" + datatable + "'"; - final String updatePermissionChecker = "'UPDATE_" + datatable + "_CHECKER'"; - final String deletePermission = "'DELETE_" + datatable + "'"; - final String deletePermissionChecker = "'DELETE_" + datatable + "_CHECKER'"; + try { + // TODO - JW - put in batch command later + final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name) values ('" + + dataTableName + "', '" + applicationTableName + "')"; - // TODO - JW - put in batch command later - final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name) values ('" - + datatable + "', '" + appTable + "')"; + this.jdbcTemplate.update(registerDatatableSql); + } catch (DataIntegrityViolationException dve) { + Throwable realCause = dve.getMostSpecificCause(); + if (realCause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException( + "error.msg.datatable.registered", "Datatable `" + dataTableName + + "` is already registered against an application table.", "dataTableName", dataTableName); } - this.jdbcTemplate.update(registerDatatableSql); + logAsErrorUnexpectedDataIntegrityException(dve); + throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } - final String permissionsSql = "insert into m_permission (grouping, code, action_name, entity_name, can_maker_checker) values " - + "('datatable', " - + createPermission - + ", 'CREATE', '" - + datatable - + "', true)," - + "('datatable', " - + createPermissionChecker - + ", 'CREATE', '" - + datatable - + "', false)," - + "('datatable', " - + readPermission - + ", 'READ', '" - + datatable - + "', false)," - + "('datatable', " - + updatePermission - + ", 'UPDATE', '" - + datatable - + "', true)," - + "('datatable', " - + updatePermissionChecker - + ", 'UPDATE', '" - + datatable - + "', false)," - + "('datatable', " - + deletePermission - + ", 'DELETE', '" - + datatable - + "', true)," - + "('datatable', " - + deletePermissionChecker - + ", 'DELETE', '" - + datatable - + "', false)"; + try { + final String createPermission = "'CREATE_" + dataTableName + "'"; + final String createPermissionChecker = "'CREATE_" + dataTableName + "_CHECKER'"; + final String readPermission = "'READ_" + dataTableName + "'"; + final String updatePermission = "'UPDATE_" + dataTableName + "'"; + final String updatePermissionChecker = "'UPDATE_" + dataTableName + "_CHECKER'"; + final String deletePermission = "'DELETE_" + dataTableName + "'"; + final String deletePermissionChecker = "'DELETE_" + dataTableName + "_CHECKER'"; - this.jdbcTemplate.update(permissionsSql); + final String permissionsSql = "insert into m_permission (grouping, code, action_name, entity_name, can_maker_checker) values " + + "('datatable', " + + createPermission + + ", 'CREATE', '" + + dataTableName + + "', true)," + + "('datatable', " + + createPermissionChecker + + ", 'CREATE', '" + + dataTableName + + "', false)," + + "('datatable', " + + readPermission + + ", 'READ', '" + + dataTableName + + "', false)," + + "('datatable', " + + updatePermission + + ", 'UPDATE', '" + + dataTableName + + "', true)," + + "('datatable', " + + updatePermissionChecker + + ", 'UPDATE', '" + + dataTableName + + "', false)," + + "('datatable', " + + deletePermission + + ", 'DELETE', '" + + dataTableName + + "', true)," + + "('datatable', " + + deletePermissionChecker + + ", 'DELETE', '" + + dataTableName + "', false)"; + + this.jdbcTemplate.update(permissionsSql); + } catch (DataIntegrityViolationException dve) { + Throwable realCause = dve.getMostSpecificCause(); + if (realCause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException( + "error.msg.permissions.datatable.duplicate", "Permissions for datatable `" + dataTableName + "` already exist.", + "dataTableName", dataTableName); } + + logAsErrorUnexpectedDataIntegrityException(dve); + throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } } @Override @@ -161,29 +190,53 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ final String permissionList = "('CREATE_" + datatable + "', 'CREATE_" + datatable + "_CHECKER', 'READ_" + datatable + "', 'UPDATE_" + datatable + "', 'UPDATE_" + datatable + "_CHECKER', 'DELETE_" + datatable + "', 'DELETE_" + datatable + "_CHECKER')"; - String sql = "delete from m_role_permission where m_role_permission.permission_id in (select id from m_permission where code in " + final String deleteRolePermissionsSql = "delete from m_role_permission where m_role_permission.permission_id in (select id from m_permission where code in " + permissionList + ")"; - this.jdbcTemplate.update(sql); + this.jdbcTemplate.update(deleteRolePermissionsSql); - sql = "delete from m_permission where code in " + permissionList; - this.jdbcTemplate.update(sql); + final String deletePermissionsSql = "delete from m_permission where code in " + permissionList; + this.jdbcTemplate.update(deletePermissionsSql); - sql = "delete from x_registered_table where registered_table_name = '" + datatable + "'"; - this.jdbcTemplate.update(sql); + final String deleteRegisteredDatatableSql = "delete from x_registered_table where registered_table_name = '" + datatable + "'"; + this.jdbcTemplate.update(deleteRegisteredDatatableSql); } @Override - public void newDatatableEntry(final String datatable, final Long appTableId, final JsonCommand command) { - String appTable = getWithinScopeApplicationTableName(datatable, appTableId); + public void createNewDatatableEntry(final String dataTableName, final Long appTableId, final JsonCommand command) { - final List columnHeaders = this.genericDataService.fillResultsetColumnHeaders(datatable); + try { + final String appTable = getWithinScopeApplicationTableName(dataTableName, appTableId); - final Type typeOfMap = new TypeToken>() {}.getType(); - final Map dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json()); + final List columnHeaders = this.genericDataService.fillResultsetColumnHeaders(dataTableName); - final String sql = getAddSql(columnHeaders, datatable, getFKField(appTable), appTableId, dataParams); + final Type typeOfMap = new TypeToken>() {}.getType(); + final Map dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json()); - this.jdbcTemplate.update(sql); + final String sql = getAddSql(columnHeaders, dataTableName, getFKField(appTable), appTableId, dataParams); + + this.jdbcTemplate.update(sql); + } catch (ConstraintViolationException dve) { + // NOTE: jdbctemplate throws a + // org.hibernate.exception.ConstraintViolationException even though + // it should be a DataAccessException? + Throwable realCause = dve.getCause(); + if (realCause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException( + "error.msg.datatable.entry.duplicate", "An entry already exists for datatable `" + dataTableName + + "` and application table with identifier `" + appTableId + "`.", "dataTableName", dataTableName, appTableId); } + + logAsErrorUnexpectedDataIntegrityException(dve); + throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } catch (DataAccessException dve) { + Throwable realCause = dve.getMostSpecificCause(); + if (realCause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException( + "error.msg.datatable.entry.duplicate", "An entry already exists for datatable `" + dataTableName + + "` and application table with identifier `" + appTableId + "`.", "dataTableName", dataTableName, appTableId); } + + logAsErrorUnexpectedDataIntegrityException(dve); + throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } } @Override @@ -191,7 +244,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, null); - if (grs.getData().size() == 0) throw new DataTableNotFoundException(datatable, appTableId); + if (grs.getData().size() == 0) throw new DatatableNotFoundException(datatable, appTableId); if (grs.getData().size() > 1) throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update", "Application Table: " + datatable @@ -223,7 +276,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ final GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, datatableId); - if (grs.getData().size() == 0) throw new DataTableNotFoundException(datatable, appTableId); + if (grs.getData().size() == 0) throw new DatatableNotFoundException(datatable, appTableId); final Type typeOfMap = new TypeToken>() {}.getType(); final Map dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json()); @@ -296,7 +349,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql); - if (!rs.next()) { throw new DataTableNotFoundException(appTable, appTableId); } + if (!rs.next()) { throw new DatatableNotFoundException(appTable, appTableId); } } private String dataScopedSQL(final String unscopedSQL, final String appTable) { @@ -374,7 +427,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ if (rs.next()) { applicationTableName = rs.getString("application_table_name"); } else { - throw new DataTableNotFoundException(datatable); + throw new DatatableNotFoundException(datatable); } return applicationTableName;