From 11b382caf6971c8045b96b3be003762a57958e5b Mon Sep 17 00:00:00 2001 From: mitchellsundt Date: Tue, 26 Aug 2014 17:45:51 -0700 Subject: [PATCH 1/2] Change to correctly compute the isUnitOfRetention value. --- .../aggregate/odktables/TableManager.java | 7 +- .../relation/DbColumnDefinitions.java | 100 ++++++++++++++++-- .../odktables/rest/entity/Column.java | 29 ++--- 3 files changed, 104 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java b/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java index 91d12fc259..0a7c1e9eeb 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java @@ -432,7 +432,12 @@ public TableEntry createTable(String tableId, List columns) for (DbColumnDefinitionsEntity e : colDefs) { e.put(cc); } - + /** + * Update the isUnitOfRetention field for these so they can be used + * to create the data tables on the server. + */ + DbColumnDefinitions.markUnitOfRetention(colDefs); + /** * Instantiate the actual tables */ diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java index a95d9e1277..bac3d2e0f4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java @@ -16,9 +16,12 @@ package org.opendatakit.aggregate.odktables.relation; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Query; @@ -32,6 +35,10 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * This defines the columns in a given schemaETag storage representation of that * tableId. The table defines the abstract objects (e.g., geopoint) and @@ -76,9 +83,12 @@ private DbColumnDefinitions(String namespace, String tableName, List dataFields.add(LIST_CHILD_ELEMENT_KEYS); } + public static final ObjectMapper mapper = new ObjectMapper(); + public static class DbColumnDefinitionsEntity { Entity e; + private boolean isUnitOfRetention = true; DbColumnDefinitionsEntity(Entity e) { this.e = e; @@ -143,20 +153,38 @@ public String getListChildElementKeys() { return e.getString(LIST_CHILD_ELEMENT_KEYS); } + public ArrayList getArrayListChildElementKeys() { + String listChildren = getListChildElementKeys(); + if ( listChildren == null || listChildren.length() == 0 ) { + return new ArrayList(); + } else { + ArrayList childElementKeys; + try { + childElementKeys = mapper.readValue(listChildren, ArrayList.class); + } catch (JsonParseException e) { + e.printStackTrace(); + return new ArrayList(); + } catch (JsonMappingException e) { + e.printStackTrace(); + return new ArrayList(); + } catch (IOException e) { + e.printStackTrace(); + return new ArrayList(); + } + return childElementKeys; + } + } + public void setListChildElementKeys(String value) { e.set(LIST_CHILD_ELEMENT_KEYS, value); } public boolean isUnitOfRetention() { - String listChild = getListChildElementKeys(); - String type = getElementType(); - if ( "array".equals(type) ) { - return true; - } - if ( listChild == null || listChild.length() == 0 || "[]".equals(listChild) ) { - return true; - } - return false; + return isUnitOfRetention; + } + + private void setNotUnitOfRetention() { + isUnitOfRetention = false; } /** @@ -233,8 +261,62 @@ public static List query(String tableId, String schem for (Entity e : list) { results.add(new DbColumnDefinitionsEntity(e)); } + markUnitOfRetention(results); return results; } + + /** + * This code needs to parallel that of the javascript in ODK Survey and the java + * code in ODK Tables and the ODK Database layer. + * + * @param defnList + */ + public static void markUnitOfRetention(List defnList) { + // for all arrays, mark all descendants of the array as not-retained + // because they are all folded up into the json representation of the array + Map defn = new HashMap(); + for ( DbColumnDefinitionsEntity colDefn : defnList ) { + defn.put(colDefn.getElementKey(), colDefn ); + } + + for (DbColumnDefinitionsEntity colDefn : defnList) { + if (!colDefn.isUnitOfRetention()) { + // this has already been processed + continue; + } + if ("array".equals(colDefn.getElementType())) { + ArrayList childElementKeys = colDefn.getArrayListChildElementKeys(); + ArrayList scratchArray = new ArrayList(); + while (!childElementKeys.isEmpty()) { + for (String childKey : childElementKeys) { + DbColumnDefinitionsEntity subDefn = defn.get(childKey); + if (!subDefn.isUnitOfRetention()) { + // this has already been processed + continue; + } + subDefn.setNotUnitOfRetention(); + if (subDefn.getListChildElementKeys() != null) { + scratchArray.addAll(subDefn.getArrayListChildElementKeys()); + } + } + childElementKeys = scratchArray; + } + } + } + // and mark any non-arrays with multiple fields as not retained + for (DbColumnDefinitionsEntity colDefn : defnList) { + if (!colDefn.isUnitOfRetention()) { + // this has already been processed + continue; + } + if (!"array".equals(colDefn.getElementType())) { + if (!colDefn.getArrayListChildElementKeys().isEmpty()) { + colDefn.setNotUnitOfRetention(); + } + } + } + } + /** * Return the actual database column names for the given table. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java index 938ad2bacd..49e2abf092 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java @@ -18,7 +18,6 @@ import java.io.Serializable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -45,8 +44,8 @@ public class Column implements Serializable { */ /** * The fully qualified key for this element. If this is a retained field, - * (see isUnitOfRetention, below) then this is the element's database - * column name. For composite types whose elements are individually retained + * then this is the element's database column name. For composite types + * whose elements are individually retained * (e.g., geopoint), this would be the elementName of the geopoint (e.g., * 'myLocation' concatenated with '_' and this elementName (e.g., * 'myLocation_latitude'). @@ -87,8 +86,8 @@ public class Column implements Serializable { * 'typename' is any other alpha-numeric name (user-definable data type). * * The (len) attribute, if present, identifies the VARCHAR storage - * requirements for the field when the field is a unit of retention - * (see isUnitOfRetention below). Ignored if not a unit of retention. + * requirements for the field when the field is a unit of retention. + * Ignored if not a unit of retention. * * The server stores: * @@ -108,7 +107,7 @@ public class Column implements Serializable { * * array is a JSON serialization expecting one child element key * that defines the data type in the array. Array fields - * MUST be units of retention (isUnitOfRetention == true). + * MUST be a unit of retention (or be nested within one). * * string is a string value * @@ -138,7 +137,7 @@ public class Column implements Serializable { */ @JsonProperty(required = false) private String listChildElementKeys; - + /** * If true, then this elementKey is a column in the backing * database table. If false, then either the elementKey is a @@ -164,7 +163,6 @@ private Column() { * @param elementName * @param elementType * @param listChildElementKeys - * @param isUnitOfRetention */ public Column(final String elementKey, final String elementName, final String elementType, final String listChildElementKeys) { @@ -192,20 +190,7 @@ public String getElementType() { public String getListChildElementKeys() { return this.listChildElementKeys; } - - @JsonIgnore - public boolean isUnitOfRetention() { - String listChild = getListChildElementKeys(); - String type = getElementType(); - if ( "array".equals(type) ) { - return true; - } - if ( listChild == null || listChild.length() == 0 || "[]".equals(listChild) ) { - return true; - } - return false; - } - + @Override public String toString() { return "Column(elementKey=" + this.getElementKey() From d5b3f7a2c7201e0eb44bb8fde12c22fd98ff22e0 Mon Sep 17 00:00:00 2001 From: mitchellsundt Date: Wed, 27 Aug 2014 08:51:08 -0700 Subject: [PATCH 2/2] Change sync state enum names --- .../aggregate/odktables/rest/SyncState.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/SyncState.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/SyncState.java index 05b94f943a..8dac6eceae 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/SyncState.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/SyncState.java @@ -27,18 +27,18 @@ * *
  * insert:
- *     state = INSERTING
+ *     state = new_row
  *
  * update:
- *     if state == REST:
- *        state = UPDATING
+ *     if state == synced:
+ *        state = changed
  *
  * delete:
- *     if state == REST or state == UPDATING:
- *        state = DELETING
+ *     if state == synced or state == changed:
+ *        state = deleted
  *        don't actually delete yet (defer until sync)
- *     else if state == INSERTING:
- *        actually delete
+ *     else if state == new_row:
+ *        actually delete row in database
  * 
*

* @@ -46,5 +46,5 @@ * */ public enum SyncState { - rest, inserting, updating, deleting, conflicting, rest_pending_files; + synced, new_row, changed, deleted, in_conflict, synced_pending_files; }