From d5f697962c519b13b5fc046d89989df15e030ab3 Mon Sep 17 00:00:00 2001 From: John Woodlock Date: Thu, 27 Sep 2012 16:58:41 +1000 Subject: [PATCH] wip update data tables and docs --- api-docs/apiLive.htm | 173 ++++++++++++++++++ .../platform/api/DataTableApiResource.java | 26 ++- .../infrastructure/ApiParameterHelper.java | 11 +- .../platform/noncore/GenericDataService.java | 2 + .../noncore/GenericDataServiceImpl.java | 60 +++++- .../noncore/ReadWriteNonCoreDataService.java | 3 - .../ReadWriteNonCoreDataServiceImpl.java | 67 ------- 7 files changed, 260 insertions(+), 82 deletions(-) diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index c6f387069..fa614c7af 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -2386,7 +2386,180 @@ Request Body: + +   +
+
+

Additional Fields (Deprecated)

+

+ In Mifos X, any number of "Sets" of "Additional Fields" can be configured for a Mifos X database table ("Type"). +

+

For example, portfolio_client is the database table that holds client data. Typically, MFI's want more client related fields than is provided by Mifos X out-of-the-box. + The MFI might add a Set called "Additional Info" containing some fields that are typically input when creating a client. + They might then add another Set called "Highly Improbable Info" containing some fields that are only input in exceptional + circumstances. +

+

+ The additional fields resource allows you to retrieve and update any Additional Fields data that has been configured in Mifos X. +

+

+ The Mifos X Individual Lending client application uses a JQuery plugin called stretchydata which, itself, uses this + additional fields resource to provide a pretty flexible additional fields User Interface (UI). +

+
+
+ +   +
+
+

List Additional Fields Sets

+

+ Lists the Sets of additional fields have been defined in Mifos X. +

+ +
Arguments
+
+
type
+
optional
+
The Additional Fields Type (Mifos X database table) to restrict the output to
+
+

Example Requests:

+
additionalfields?type=m_client
+

+
additionalfields
+
+
+ GET https://Domain Name/api/v1/additionalfields + [ { + "id" : 1, + "name" : "Additional Information", + "type" : "portfolio_client" +}, { + "id" : 8, + "name" : "Additional Information", + "type" : "portfolio_loan" +}, { + "id" : 9, + "name" : "Highly Improbable Info", + "type" : "portfolio_client" +} ] + +
+
+ + +   +
+
+

Retrieve Additional Fields

+

+ Returns the Set of Additional Fields data for the ID provided. The ID is the id field of the Type table e.g. portfolio_client might have an id value of 4. The output is a JSON formatted "Generic Resultset". The Generic Resultset contains Column Heading as well as Data information. The Column Heading information may include allowed values (columnValues array). +

+

Example Request: +

additionalfields/m_client/Additional Information/2
+

+
+
+ GET https://Domain Name/api/v1/additionalfields/{type}/{set}/{id} + { + "columnHeaders" : [ { + "columnName" : "Ethnic Group", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : "List", + "columnValues" : [ "Bedouin", "Berber", "Italian", "Miknasa", "Mrazig", "Other", "Unknown" ] + }, { + "columnName" : "Ethnic Group Other", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : null, + "columnValues" : [ ] + }, { + "columnName" : "Household Location", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : "List", + "columnValues" : [ "East Sikkim", "North Sikkim", "South Sikkim", "West Sikkim", "Other" ] + }, { + "columnName" : "Household Location Other", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : null, + "columnValues" : [ ] + }, { + "columnName" : "Religion", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : "List", + "columnValues" : [ "Protestant", "Catholic", "Muslim", "Animist", "Atheist", "Other", "Unknown" ] + }, { + "columnName" : "Religion Other", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : null, + "columnValues" : [ ] + }, { + "columnName" : "Knowledge of Person", + "columnType" : "String", + "columnLength" : 50, + "columnDisplayType" : "List", + "columnValues" : [ "Staff member", "Spouse of staff member", "Son/daughter of staff member", "Friend of staff member", "Not known by any staff member", "Other" ] + }, { + "columnName" : "Gender", + "columnType" : "String", + "columnLength" : 10, + "columnDisplayType" : "List", + "columnValues" : [ "Female", "Male" ] + }, { + "columnName" : "Whois", + "columnType" : "Text", + "columnLength" : null, + "columnDisplayType" : null, + "columnValues" : [ ] + } ], + "data" : [ { + "row" : [ "Bedouin", null, "East Sikkim", null, "Animist", "Agnostic", "Friend of staff member", "Female", "A person of honesty & clear thought" ] + } ] +} + +
+
+   +
+
+

Update Additional Fields

+

+ Updates (or creates) the Set of Additional Fields data for the ID provided. The ID is the id field of the Type table e.g. portfolio_client might have an id value of 4. +

+
+
+ POST https://Domain Name/api/v1/additionalfields/{type}/{set}/{id} + POST additionalfields/portfolio_client/Additional Information/2 +Content-Type: application/json +Request Body: +{ + "Ethnic_Group":"Berber", + "Ethnic_Group_Other":"", + "Household_Location":"East Sikkim", + "Household_Location_Other":"", + "Religion":"Animist", + "Religion_Other":"jjjjjjj", + "Knowledge_of_Person":"Son/daughter of staff member", + "Gender":"Female", + "Whois":"its\r\nme of\r\ncourse\r\nyes\r\nend and the end of it all" +} + + { + "entityId": 2 +} + +
+
+ + + +  
diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java index 500c45f3d..10589a764 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java @@ -29,6 +29,7 @@ import org.mifosng.platform.api.data.GenericResultsetData; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.ApiParameterHelper; import org.mifosng.platform.exceptions.NoAuthorizationException; +import org.mifosng.platform.noncore.GenericDataService; import org.mifosng.platform.noncore.ReadWriteNonCoreDataService; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.user.domain.AppUser; @@ -53,6 +54,9 @@ public class DataTableApiResource { this.context = context; } + @Autowired + private GenericDataService genericDataService; + @Autowired private ReadWriteNonCoreDataService readWriteNonCoreDataService; @@ -113,21 +117,23 @@ public class DataTableApiResource { checkUserPermissionForDatatable(datatable, "READ"); - /* - * Dont use this for now... but its the code for returning data as json - * objects rather than a generic resultset String resultStr = - * this.readWriteNonCoreDataService - * .retrieveDataTableJSONObject(datatable, id, sqlFields, sqlOrder); - */ - GenericResultsetData results = this.readWriteNonCoreDataService .retrieveDataTableGenericResultSet(datatable, apptableId, sqlFields, sqlOrder, null); - boolean prettyPrints = ApiParameterHelper.prettyPrint(uriInfo + boolean genericResultSet = ApiParameterHelper.genericResultSet(uriInfo .getQueryParameters()); - return this.apiJsonSerializerService - .serializeGenericResultsetDataToJson(prettyPrints, results); + + if (genericResultSet) { + boolean prettyPrints = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + return this.apiJsonSerializerService + .serializeGenericResultsetDataToJson(prettyPrints, results); + } else { + + return this.genericDataService + .generateJsonFromGenericResultsetData(results); + } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiParameterHelper.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiParameterHelper.java index cfe1d4bde..041e7b3da 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiParameterHelper.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiParameterHelper.java @@ -60,7 +60,7 @@ public class ApiParameterHelper { } return parameterType; } - + public static boolean template(final MultivaluedMap queryParams) { boolean template = false; if (queryParams.getFirst("template") != null) { @@ -69,4 +69,13 @@ public class ApiParameterHelper { } return template; } + + public static boolean genericResultSet(final MultivaluedMap queryParams) { + boolean genericResultSet = false; + if (queryParams.getFirst("genericResultSet") != null) { + String genericResultSetValue = queryParams.getFirst("genericResultSet"); + genericResultSet = "true".equalsIgnoreCase(genericResultSetValue); + } + return genericResultSet; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java index a64356f33..014932017 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java @@ -12,6 +12,8 @@ public interface GenericDataService { GenericResultsetData fillGenericResultSet(final String sql); + String generateJsonFromGenericResultsetData(GenericResultsetData grs); + String replace(String str, String pattern, String replace); String wrapSQL(String sql); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java index b6f860eae..8b18bc3b5 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java @@ -11,6 +11,7 @@ import java.util.List; import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; +import org.joda.time.LocalDate; import org.mifosng.platform.api.data.GenericResultsetData; import org.mifosng.platform.api.data.ResultsetColumnHeader; import org.mifosng.platform.api.data.ResultsetDataRow; @@ -22,7 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.sun.rowset.CachedRowSetImpl; - +//TODO - Performance Item - most items (code values etc) can be cached but not doing that yet @Service public class GenericDataServiceImpl implements GenericDataService { @@ -39,6 +40,7 @@ public class GenericDataServiceImpl implements GenericDataService { @Override public CachedRowSet getCachedResultSet(String sql, String sqlErrorMsg) { + //TODO - Need to reimplement this away from Sun library - could be mixture of Lists and jdbcTemplate.query long startTime = System.currentTimeMillis(); Connection db_connection = null; @@ -157,6 +159,62 @@ public class GenericDataServiceImpl implements GenericDataService { return "select x.* from (" + sql + ") x"; } + @Override + public String generateJsonFromGenericResultsetData(GenericResultsetData grs) { + + StringBuffer writer = new StringBuffer(); + + writer.append("["); + + List columnHeaders = grs.getColumnHeaders(); + logger.info("NO. of Columns: " + columnHeaders.size()); + + List data = grs.getData(); + List row; + Integer rSize; + String currColType; + String currVal; + logger.info("NO. of Rows: " + data.size()); + for (int i = 0; i < data.size(); i++) { + writer.append("\n{"); + + row = data.get(i).getRow(); + rSize = row.size(); + for (int j = 0; j < rSize; j++) { + + writer.append('\"' + columnHeaders.get(j).getColumnName() + + '\"' + ": "); + currColType = columnHeaders.get(j).getColumnDisplayTypeNew(); + currVal = row.get(j); + if (currVal != null) { + if (currColType.equals("DECIMAL") + || currColType.equals("INTEGER")) + writer.append(currVal); + else { + if (currColType.equals("DATE")) { + LocalDate localDate = new LocalDate(currVal); + writer.append("[" + localDate.getYear() + ", " + localDate.getMonthOfYear() + ", " + localDate.getDayOfMonth() + "]"); + } else + writer.append('\"' + currVal + '\"'); + } + } else + writer.append("null"); + + if (j < (rSize - 1)) + writer.append(",\n"); + } + + if (i < (data.size() - 1)) + writer.append("},"); + else + writer.append("}"); + } + + writer.append("\n]"); + return writer.toString(); + + } + private void dbClose(Statement db_statement, Connection db_connection) { logger.debug("dbClose"); try { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java index 32a61a6c9..53cb65d2a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java @@ -20,9 +20,6 @@ public interface ReadWriteNonCoreDataService { GenericResultsetData retrieveDataTableGenericResultSet(String datatable, Long appTableId, String sqlFields, String sqlOrder, Long id); - String retrieveDataTableJSONObject(String datatable, Long appTableId, - String sqlFields, String sqlOrder); - void newDatatableEntry(String datatable, Long appTableId, Map queryParams); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java index 4a9842d18..79a6185c4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java @@ -294,22 +294,6 @@ public class ReadWriteNonCoreDataServiceImpl implements } - @Override - public String retrieveDataTableJSONObject(String datatable, - Long appTableId, String sqlFields, String sqlOrder) { - long startTime = System.currentTimeMillis(); - - GenericResultsetData result = retrieveDataTableGenericResultSet( - datatable, appTableId, sqlFields, sqlOrder, null); - - String jsonString = generateJsonFromGenericResultsetData(result); - - long elapsed = System.currentTimeMillis() - startTime; - logger.info("FINISHING DATATABLE JSON OBJECT: " + datatable - + " Elapsed Time: " + elapsed); - return jsonString; - } - @Override public GenericResultsetData retrieveDataTableGenericResultSet( String datatable, Long appTableId, String sqlFields, @@ -595,57 +579,6 @@ public class ReadWriteNonCoreDataServiceImpl implements } - private static String generateJsonFromGenericResultsetData( - GenericResultsetData result) { - - StringBuffer writer = new StringBuffer(); - - writer.append("["); - - List columnHeaders = result.getColumnHeaders(); - logger.info("NO. of Columns: " + columnHeaders.size()); - - List data = result.getData(); - List row; - Integer rSize; - String currColType; - String currVal; - logger.info("NO. of Rows: " + data.size()); - for (int i = 0; i < data.size(); i++) { - writer.append("\n{"); - - row = data.get(i).getRow(); - rSize = row.size(); - for (int j = 0; j < rSize; j++) { - - writer.append('\"' + columnHeaders.get(j).getColumnName() - + '\"' + ": "); - currColType = columnHeaders.get(j).getColumnDisplayTypeNew(); - currVal = row.get(j); - if (currVal != null) { - if (currColType.equals("DECIMAL") - || currColType.equals("INTEGER")) - writer.append(currVal); - else - writer.append('\"' + currVal + '\"'); - } else - writer.append("null"); - - if (j < (rSize - 1)) - writer.append(",\n"); - } - - if (i < (data.size() - 1)) - writer.append("},"); - else - writer.append("}"); - } - - writer.append("\n]"); - return writer.toString(); - - } - private String getAddSql(List columnHeaders, String datatable, String fkName, Long appTableId, Map queryParams) {