From d7a4773a3bf55456da977bbc1ab3f1db7a0f9afe Mon Sep 17 00:00:00 2001 From: Murray Cumming Date: Wed, 28 Nov 2012 09:06:42 +0100 Subject: [PATCH] SelfHosting test: Also try using a relationship. * src/main/java/org/glom/web/server/database/DBAccess.java: convertResultSetToDTO(): Move some code into a public method as: * src/main/java/org/glom/web/server/SqlUtils.java: fillDataItemFromResultSet(): This takes a DataItem and sets it from a value from a datbase recordset. * src/main/java/org/glom/web/server/libglom/Document.java: Make getDocument() public, so we can use it in a test. * src/test/java/org/glom/web/server/SelfHostExampleTest.java: Add testExampleMusiccollectionDataRelated() and call it from testExampleMusiccollectionData(), to do a basic test of using a relationship. --- ChangeLog | 17 ++++++ src/main/java/org/glom/web/server/SqlUtils.java | 70 +++++++++++++++++++++ .../org/glom/web/server/database/DBAccess.java | 64 ++----------------- .../java/org/glom/web/server/libglom/Document.java | 5 +- .../org/glom/web/server/SelfHostExampleTest.java | 71 +++++++++++++++++++--- 5 files changed, 160 insertions(+), 67 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d8887c..1d6df2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2012-11-28 Murray Cumming + + SelfHosting test: Also try using a relationship. + + * src/main/java/org/glom/web/server/database/DBAccess.java: + convertResultSetToDTO(): Move some code into a public + method as: + * src/main/java/org/glom/web/server/SqlUtils.java: + fillDataItemFromResultSet(): This takes a DataItem and + sets it from a value from a datbase recordset. + * src/main/java/org/glom/web/server/libglom/Document.java: + Make getDocument() public, so we can use it in a test. + * src/test/java/org/glom/web/server/SelfHostExampleTest.java: + Add testExampleMusiccollectionDataRelated() and call it from + testExampleMusiccollectionData(), to do a basic test of using + a relationship. + 2012-11-22 Murray Cumming Build: Specify the source encoding. diff --git a/src/main/java/org/glom/web/server/SqlUtils.java b/src/main/java/org/glom/web/server/SqlUtils.java index f00e094..59a0f05 100644 --- a/src/main/java/org/glom/web/server/SqlUtils.java +++ b/src/main/java/org/glom/web/server/SqlUtils.java @@ -19,11 +19,18 @@ package org.glom.web.server; +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Time; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import org.apache.commons.lang3.StringUtils; import org.glom.web.server.libglom.Document; +import org.glom.web.shared.DataItem; import org.glom.web.shared.TypedDataItem; import org.glom.web.shared.libglom.Field; import org.glom.web.shared.libglom.Relationship; @@ -400,4 +407,67 @@ public class SqlUtils { return condition; } + + /** + * @param dataItem + * @param field + * @param rsIndex + * @param rs + * @param primaryKeyValue + * @throws SQLException + */ + public static void fillDataItemFromResultSet(final DataItem dataItem, final LayoutItemField field, final int rsIndex, + final ResultSet rs, final String documentID, final String tableName, final TypedDataItem primaryKeyValue) throws SQLException { + switch (field.getGlomType()) { + case TYPE_TEXT: + final String text = rs.getString(rsIndex); + dataItem.setText(text != null ? text : ""); + break; + case TYPE_BOOLEAN: + dataItem.setBoolean(rs.getBoolean(rsIndex)); + break; + case TYPE_NUMERIC: + dataItem.setNumber(rs.getDouble(rsIndex)); + break; + case TYPE_DATE: + final Date date = rs.getDate(rsIndex); + if (date != null) { + // TODO: Pass Date and Time types instead of converting to text here? + // TODO: Use a 4-digit-year short form, somehow. + final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ROOT); + dataItem.setText(dateFormat.format(date)); + } else { + dataItem.setText(""); + } + break; + case TYPE_TIME: + final Time time = rs.getTime(rsIndex); + if (time != null) { + final DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.ROOT); + dataItem.setText(timeFormat.format(time)); + } else { + dataItem.setText(""); + } + break; + case TYPE_IMAGE: + //We don't get the data here. + //Instead we provide a way for the client to get the image separately. + + //This doesn't seem to work, + //presumably because the base64 encoding is wrong: + //final byte[] imageByteArray = rs.getBytes(rsIndex); + //if (imageByteArray != null) { + // String base64 = org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(imageByteArray); + // base64 = "data:image/png;base64," + base64; + + final String url = Utils.buildImageDataUrl(primaryKeyValue, documentID, tableName, field); + dataItem.setImageDataUrl(url); + break; + case TYPE_INVALID: + default: + Log.warn(documentID, tableName, "Invalid LayoutItem Field type. Using empty string for value."); + dataItem.setText(""); + break; + } + } } diff --git a/src/main/java/org/glom/web/server/database/DBAccess.java b/src/main/java/org/glom/web/server/database/DBAccess.java index 5bab981..5efdbbc 100644 --- a/src/main/java/org/glom/web/server/database/DBAccess.java +++ b/src/main/java/org/glom/web/server/database/DBAccess.java @@ -19,17 +19,14 @@ package org.glom.web.server.database; -import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.sql.Time; -import java.text.DateFormat; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import org.glom.web.server.Log; +import org.glom.web.server.SqlUtils; import org.glom.web.server.Utils; import org.glom.web.server.libglom.Document; import org.glom.web.shared.DataItem; @@ -76,15 +73,14 @@ public abstract class DBAccess { final DataItem[] rowArray = new DataItem[layoutFieldsSize]; for (int i = 0; i < layoutFieldsSize; i++) { // make a new DataItem to set the text and colors - rowArray[i] = new DataItem(); // TODO: Performance: Set it in the rowArray at the end, to avoid repeated - // lookup via []. + final DataItem dataItem = new DataItem(); final LayoutItemField field = layoutFields.get(i); if (i >= rsColumnscount) { Log.error("convertResultSetToDTO(): index i=" + i + "+1 (field=" + field.getName() + " is out of range for the ResultSet. Using empty string for value."); - rowArray[i].setText(""); + dataItem.setText(""); continue; } @@ -92,57 +88,9 @@ public abstract class DBAccess { // Convert the field value to a string based on the glom type. We're doing the formatting on the // server side for now but it might be useful to move this to the client side. - switch (field.getGlomType()) { - case TYPE_TEXT: - final String text = rs.getString(rsIndex); - rowArray[i].setText(text != null ? text : ""); - break; - case TYPE_BOOLEAN: - rowArray[i].setBoolean(rs.getBoolean(rsIndex)); - break; - case TYPE_NUMERIC: - rowArray[i].setNumber(rs.getDouble(rsIndex)); - break; - case TYPE_DATE: - final Date date = rs.getDate(rsIndex); - if (date != null) { - // TODO: Pass Date and Time types instead of converting to text here? - // TODO: Use a 4-digit-year short form, somehow. - final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ROOT); - rowArray[i].setText(dateFormat.format(date)); - } else { - rowArray[i].setText(""); - } - break; - case TYPE_TIME: - final Time time = rs.getTime(rsIndex); - if (time != null) { - final DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.ROOT); - rowArray[i].setText(timeFormat.format(time)); - } else { - rowArray[i].setText(""); - } - break; - case TYPE_IMAGE: - //We don't get the data here. - //Instead we provide a way for the client to get the image separately. - - //This doesn't seem to work, - //presumably because the base64 encoding is wrong: - //final byte[] imageByteArray = rs.getBytes(rsIndex); - //if (imageByteArray != null) { - // String base64 = org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(imageByteArray); - // base64 = "data:image/png;base64," + base64; - - final String url = Utils.buildImageDataUrl(primaryKeyValue, documentID, tableName, field); - rowArray[i].setImageDataUrl(url); - break; - case TYPE_INVALID: - default: - Log.warn(documentID, tableName, "Invalid LayoutItem Field type. Using empty string for value."); - rowArray[i].setText(""); - break; - } + SqlUtils.fillDataItemFromResultSet(dataItem, field, rsIndex, rs, documentID, tableName, primaryKeyValue); + + rowArray[i] = dataItem; } // add the row of DataItems to the ArrayList we're going to return and update the row count diff --git a/src/main/java/org/glom/web/server/libglom/Document.java b/src/main/java/org/glom/web/server/libglom/Document.java index e87f9c3..2a92c8f 100644 --- a/src/main/java/org/glom/web/server/libglom/Document.java +++ b/src/main/java/org/glom/web/server/libglom/Document.java @@ -1412,12 +1412,13 @@ public class Document { return false; } - /** + /** Get the relationship by name for a table. + * * @param tableName * @param relationshipName * @return */ - private Relationship getRelationship(final String tableName, final String relationshipName) { + public Relationship getRelationship(final String tableName, final String relationshipName) { final TableInfo info = getTableInfo(tableName); if (info == null) { Log.error("table not found: " + tableName); diff --git a/src/test/java/org/glom/web/server/SelfHostExampleTest.java b/src/test/java/org/glom/web/server/SelfHostExampleTest.java index 017abd9..fe12291 100644 --- a/src/test/java/org/glom/web/server/SelfHostExampleTest.java +++ b/src/test/java/org/glom/web/server/SelfHostExampleTest.java @@ -34,6 +34,7 @@ import org.glom.web.server.libglom.Document; import org.glom.web.server.libglom.Document.HostingMode; import org.glom.web.shared.TypedDataItem; import org.glom.web.shared.libglom.Field; +import org.glom.web.shared.libglom.Relationship; import org.glom.web.shared.libglom.layout.LayoutItemField; import org.jooq.Condition; import org.junit.AfterClass; @@ -72,20 +73,21 @@ public class SelfHostExampleTest { //Check that some data is as expected: final TypedDataItem quickFindValue = new TypedDataItem(); quickFindValue.setText("Born To Run"); - final Condition whereClause = SqlUtils.getFindWhereClauseQuick(document, "albums", quickFindValue); + final String tableName = "albums"; + final Condition whereClause = SqlUtils.getFindWhereClauseQuick(document, tableName, quickFindValue); assertTrue(whereClause != null); final List fieldsToGet = new ArrayList(); - Field field = document.getField("albums", "album_id"); + Field field = document.getField(tableName, "album_id"); + final LayoutItemField layoutItemFieldAlbumID = new LayoutItemField(); + layoutItemFieldAlbumID.setFullFieldDetails(field); + fieldsToGet.add(layoutItemFieldAlbumID); + field = document.getField(tableName, "name"); LayoutItemField layoutItemField = new LayoutItemField(); layoutItemField.setFullFieldDetails(field); fieldsToGet.add(layoutItemField); - field = document.getField("albums", "name"); - layoutItemField = new LayoutItemField(); - layoutItemField.setFullFieldDetails(field); - fieldsToGet.add(layoutItemField); - final String sqlQuery = SqlUtils.buildSqlSelectWithWhereClause("albums", fieldsToGet, whereClause, null); + final String sqlQuery = SqlUtils.buildSqlSelectWithWhereClause(tableName, fieldsToGet, whereClause, null); final Connection conn = selfHoster.createConnection(false); assertTrue(conn != null); @@ -101,6 +103,61 @@ public class SelfHostExampleTest { rs.last(); final int rsRowsCount = rs.getRow(); Assert.assertEquals(1, rsRowsCount); + + final TypedDataItem albumID = new TypedDataItem(); + SqlUtils.fillDataItemFromResultSet(albumID, layoutItemFieldAlbumID, 1, + rs, "fake-document-id", tableName, null); + testExampleMusiccollectionDataRelated(document, albumID); + } + + /** Check that we can get data via a relationship. + * @param document + * @param albumID + * @throws SQLException + */ + private void testExampleMusiccollectionDataRelated(Document document, TypedDataItem albumID) throws SQLException { + final String tableName = "albums"; + + //Normal fields: + final List fieldsToGet = new ArrayList(); + final Field fieldAlbumID = document.getField(tableName, "album_id"); + assertNotNull(fieldAlbumID); + LayoutItemField layoutItemField = new LayoutItemField(); + layoutItemField.setFullFieldDetails(fieldAlbumID); + fieldsToGet.add(layoutItemField); + Field field = document.getField(tableName, "name"); + assertNotNull(field); + layoutItemField = new LayoutItemField(); + layoutItemField.setFullFieldDetails(field); + fieldsToGet.add(layoutItemField); + + //Related field: + final Relationship relationship = document.getRelationship(tableName, "artist"); + assertNotNull(relationship); + layoutItemField = new LayoutItemField(); + layoutItemField.setRelationship(relationship); + field = document.getField("artists", "name"); + assertNotNull(field); + layoutItemField.setFullFieldDetails(field); + fieldsToGet.add(layoutItemField); + + + final String sqlQuery = SqlUtils.buildSqlSelectWithKey(tableName, fieldsToGet, fieldAlbumID, albumID); + + final Connection conn = selfHoster.createConnection(false); + assertTrue(conn != null); + + final Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + //st.setFetchSize(length); + final ResultSet rs = st.executeQuery(sqlQuery); + assertTrue(rs != null); + + final ResultSetMetaData rsMetaData = rs.getMetaData(); + Assert.assertEquals(3, rsMetaData.getColumnCount()); + + rs.last(); + final int rsRowsCount = rs.getRow(); + Assert.assertEquals(1, rsRowsCount); } @AfterClass -- 2.1.4