private void GetLatest() throws Exception {
    // clear the bookmarks table...
    getDatabase().ExecuteNonQuery(new SqlStatement("delete from bookmarks"), true);

    // get the bookmarks from the server...
    BookmarksService service = new BookmarksService();
    for (Bookmark bookmark : service.GetAll()) {
      // the bookmarks we get from the server have server ids populated.  we need to
      // remove the server id and save locally by creating a new item...

      // create and copy all of the fields except the key field...
      Bookmark newBookmark = new Bookmark();
      for (EntityField field : getEntityType().getFields()) {
        if (!(field.getIsKey()) && bookmark.getIsLoaded(field))
          newBookmark.SetValue(field, bookmark.GetValue(field), SetReason.UserSet);
      }

      // set local modified and deleted...
      newBookmark.setLocalModified(false);
      newBookmark.setLocalDeleted(false);

      // save...
      newBookmark.SaveChanges(this.getContextSource());
    }
  }
  private void PushChanges() throws Exception {
    BookmarkCollection updates = Bookmark.GetBookmarksForServerUpdate(getContextSource());
    BookmarkCollection deletes = Bookmark.GetBookmarksForServerDelete(this.getContextSource());
    if (updates.size() == 0 && deletes.size() == 0) return;

    // et...
    EntityType et = EntityType.GetEntityType(Bookmark.class);

    // get the server ones...
    BookmarksService service = new BookmarksService();
    BookmarkCollection fromServer = service.GetAll();

    // walk the locally updated items…
    for (Bookmark local : updates) {
      // find it in our server set...
      Bookmark toUpdate = null;
      for (Bookmark server : fromServer) {
        if (local.getOrdinal() == server.getOrdinal()) {
          toUpdate = server;
          break;
        }
      }

      // did we have one to change?
      if (toUpdate != null) {
        // walk the fields...
        int serverId = 0;
        for (EntityField field : et.getFields()) {
          if (!(field.getIsKey()))
            toUpdate.SetValue(field, local.GetValue(field), SetReason.UserSet);
          else serverId = toUpdate.getBookmarkId();
        }

        // send that up...
        service.PushUpdate(this.getContextSource(), toUpdate, serverId);
      } else {
        // we need to insert it...
        service.PushInsert(this.getContextSource(), local);
      }
    }

    // what about ones to delete?
    for (Bookmark local : deletes) {
      // find a matching ordinal on the server...
      for (Bookmark server : fromServer) {
        if (local.getOrdinal() == server.getOrdinal())
          service.PushDelete(this.getContextSource(), server, server.getBookmarkId());
      }
    }
  }
 private void AppendIdConstraint(
     StringBuffer builder, SqlStatement sql, EntityField key, Entity entity) throws Exception {
   // constraint by ID...
   builder.append(" WHERE ");
   builder.append(key.getNativeName());
   builder.append("=?");
   sql.AddParameterValue(entity.GetValue(key));
 }
  private SqlStatement GetUpdateStatement(Entity entity) throws Exception {
    StringBuffer builder = new StringBuffer();
    SqlStatement sql = new SqlStatement();

    // et...
    EntityType et = getEntityType();

    // update...
    builder.append("UPDATE ");
    builder.append(et.getNativeName());
    builder.append(" SET ");

    // walk...
    boolean first = true;
    EntityField key = null;
    for (int index = 0; index < et.getFields().size(); index++) {
      EntityField field = (EntityField) et.getFields().elementAt(index);
      if (field.getIsKey()) key = field;
      else if (entity.getIsModified(field)) {
        if (first) first = false;
        else builder.append(", ");

        // add the snippet...
        builder.append(field.getNativeName());
        builder.append("=?");

        // add the parameter...
        Object value = entity.GetValue(field);
        sql.AddParameterValue(value);
      }
    }

    // append...
    AppendIdConstraint(builder, sql, key, entity);

    // return...
    sql.setCommandText(builder.toString());
    return sql;
  }
  private SqlStatement GetInsertStatement(Entity entity) throws Exception {
    StringBuffer builder = new StringBuffer();
    SqlStatement sql = new SqlStatement();

    // et...
    EntityType et = getEntityType();

    // create...
    builder.append("INSERT INTO ");
    builder.append(et.getNativeName());
    builder.append(" (");
    boolean first = true;
    for (int index = 0; index < et.getFields().size(); index++) {
      EntityField field = (EntityField) et.getFields().elementAt(index);
      if (entity.getIsModified(field)) {
        if (first) first = false;
        else builder.append(", ");
        builder.append(field.getNativeName());
      }
    }
    builder.append(") VALUES (");
    first = true;
    for (int index = 0; index < et.getFields().size(); index++) {
      EntityField field = (EntityField) et.getFields().elementAt(index);
      if (entity.getIsModified(field)) {
        if (first) first = false;
        else builder.append(", ");
        builder.append("?");

        // add in the parameter....
        sql.AddParameterValue(entity.GetValue(field));
      }
    }
    builder.append(")");

    // return...
    sql.setCommandText(builder.toString());
    return sql;
  }
  /** visit a value */
  private void visitValue(final Object value) {

    if (value instanceof Map) {
      // if it's a location, then create a location field.
      if (EntityMap.isLocationField((Map) value)) {
        Map<String, Object> map = (Map) value;
        Map<String, Object> location = new HashMap<>(2);
        // normalize location field to use lat/lon for es
        location.put("lat", map.get("latitude"));
        location.put("lon", map.get("longitude"));
        fields.add(EntityField.create(fieldStack.peek(), location));
        return;
      }

      iterate((Map<String, ?>) value);
    }

    // TODO figure out our nested array structure
    else if (value instanceof Collection) {
      iterate((Collection) value);
    } else {
      visitPrimitive(value);
    }
  }
 private void visit(final float value) {
   fields.add(EntityField.create(fieldStack.peek(), value));
 }
 /** Visit al the primitive values */
 private void visit(final String value) {
   fields.add(EntityField.create(fieldStack.peek(), value.toLowerCase()));
 }