Skip to content

Commit

Permalink
Improve presave interface with generics
Browse files Browse the repository at this point in the history
  • Loading branch information
cheungpat committed Jun 15, 2018
1 parent 15bcb2e commit 4da830b
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 63 deletions.
13 changes: 7 additions & 6 deletions skygear/src/main/java/io/skygear/skygear/Container.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import android.content.Context;

import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.Map;
import java.util.List;

Expand Down Expand Up @@ -220,10 +221,10 @@ public void callLambdaFunction(final String name, Object[] args, LambdaResponseH
final String lambdaName = name;
final Object[] lambdaArgs = args;
final LambdaResponseHandler responseHandler = handler;
this.publicDatabase.presave(args, new ResultCallback() {
this.publicDatabase.presave(Arrays.asList(args), new ResultCallback<List>() {
@Override
public void onSuccess(Object result) {
LambdaRequest request = new LambdaRequest(name, (List)result);
public void onSuccess(List result) {
LambdaRequest request = new LambdaRequest(name, result);
request.responseHandler = responseHandler;

Container.this.requestManager.sendRequest(request);
Expand All @@ -247,10 +248,10 @@ public void callLambdaFunction(String name, Map<String, Object> args, LambdaResp
final String lambdaName = name;
final Map<String, Object> lambdaArgs = args;
final LambdaResponseHandler responseHandler = handler;
this.publicDatabase.presave(args, new ResultCallback() {
this.publicDatabase.presave(args, new ResultCallback<Map>() {
@Override
public void onSuccess(Object result) {
LambdaRequest request = new LambdaRequest(lambdaName, (Map)result);
public void onSuccess(Map result) {
LambdaRequest request = new LambdaRequest(lambdaName, result);
request.responseHandler = responseHandler;

Container.this.requestManager.sendRequest(request);
Expand Down
147 changes: 90 additions & 57 deletions skygear/src/main/java/io/skygear/skygear/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
Expand Down Expand Up @@ -95,8 +96,9 @@ private static <T> List<T> findInObject(Object object, Class<T> klass) {
return Database.findInObject(((Record)object).getData(), klass);
} else if (object instanceof Map) {
List<T> wanted = new ArrayList<T>();
for (Map.Entry<String, Object> entry : ((Map<String, Object>)object).entrySet()) {
wanted.addAll(Database.findInObject(entry.getValue(), klass));

for (Object item : ((Map)object).values()) {
wanted.addAll(Database.findInObject(item, klass));
}
return wanted;

Expand All @@ -107,45 +109,59 @@ private static <T> List<T> findInObject(Object object, Class<T> klass) {
}
return wanted;
} else if (object instanceof Object[]) {
return Database.findInObject((List)object, klass);
return Database.findInObject(Arrays.asList(object), klass);
} else {
return new ArrayList<T>();
}
}

private static <T extends Object> Object replaceObject(Object object, Map<T, T> mapTable) {
private static Object replaceObject(Object object, Map mapTable) {
if (object == null) {
return null;
} else if (mapTable.containsKey(object)) {
return mapTable.get(object);
}

if (object instanceof Record) {
// TODO: It is better to create a clone of the Record object, but
// the Record class does not offer a clone method.
Record record = (Record)object;
record.set((Map)Database.replaceObject(record.getData(), mapTable));
return record;
return Database.replaceObject((Record)object, mapTable);
} else if (object instanceof Map) {
Map<String, Object> newMap = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : ((Map<String, Object>)object).entrySet()) {
newMap.put(entry.getKey(), Database.replaceObject(entry.getValue(), mapTable));
}
return newMap;
return Database.replaceObject((Map)object, mapTable);
} else if (object instanceof List) {
List<Object> newList = new ArrayList<Object>();
for (Object item : (List)object) {
newList.add(Database.replaceObject(item, mapTable));
}
return newList;
return Database.replaceObject((List)object, mapTable);
} else if (object instanceof Object[]) {
return Database.replaceObject(Arrays.asList((Object[])object), mapTable);
} else {
return object;
}
}

void presave(final Object object, final ResultCallback callback) { // package-private
private static Map replaceObject(Map object, Map mapTable) {
Map newMap = new HashMap();
Iterator it = object.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
newMap.put(entry.getKey(), Database.replaceObject(entry.getValue(), mapTable));
}
return newMap;
}

private static List replaceObject(List object, Map mapTable) {
List newList = new ArrayList();
for (Object item : object) {
newList.add(Database.replaceObject(item, mapTable));
}
return newList;
}

private static Record replaceObject(Record object, Map mapTable) {
// TODO: It is better to create a clone of the Record object, but
// the Record class does not offer a clone method.
Record record = (Record)object;
record.set((Map)Database.replaceObject(record.getData(), mapTable));
return record;
}

private void presaveAssets(final Object object, final ResultCallback<Map<Asset, Asset>> callback) {
List<Asset> assetsToUpload = new ArrayList<Asset>();
for (Asset asset : Database.findInObject(object, Asset.class)) {
if (asset.isPendingUpload()) {
Expand All @@ -154,23 +170,58 @@ void presave(final Object object, final ResultCallback callback) { // package-pr
}

if (assetsToUpload.size() > 0) {
this.uploadAssets(assetsToUpload, new ResultCallback<Map<Asset, Asset>>() {
@Override
public void onSuccess(Map<Asset, Asset> result) {
Object presavedObject = Database.replaceObject(object, result);
callback.onSuccess(presavedObject);
}

@Override
public void onFailure(Error error) {
callback.onFailure(error);
}
});
this.uploadAssets(assetsToUpload, callback);
} else {
callback.onSuccess(object);
callback.onSuccess(new HashMap<Asset, Asset>());
}
}

private void presave(final Record[] object, final ResultCallback<Record[]> callback) {
this.presaveAssets(object, new ResultCallback<Map<Asset, Asset>>() {
@Override
public void onSuccess(Map<Asset, Asset> result) {
Record[] newArray = new Record[object.length];
for (int i = 0; i < object.length; i++) {
newArray[i] = Database.replaceObject(object[i], result);
}
callback.onSuccess(newArray);
}

@Override
public void onFailure(Error error) {
callback.onFailure(error);
}
});
}

void presave(final List object, final ResultCallback<List> callback) { // package-private
this.presaveAssets(object, new ResultCallback<Map<Asset, Asset>>() {
@Override
public void onSuccess(Map<Asset, Asset> result) {
callback.onSuccess(Database.replaceObject(object, result));
}

@Override
public void onFailure(Error error) {
callback.onFailure(error);
}
});
}

void presave(final Map object, final ResultCallback<Map> callback) { // package-private
this.presaveAssets(object, new ResultCallback<Map<Asset, Asset>>() {
@Override
public void onSuccess(Map<Asset, Asset> result) {
callback.onSuccess(Database.replaceObject(object, result));
}

@Override
public void onFailure(Error error) {
callback.onFailure(error);
}
});
}

/**
* Save a record.
*
Expand All @@ -190,19 +241,10 @@ public void save(Record record, RecordSaveResponseHandler handler) {
public void save(final Record[] records, RecordSaveResponseHandler handler) {
final Record[] recordsToSave = records;
final RecordSaveResponseHandler responseHandler = handler;
this.presave(records, new ResultCallback() {
this.presave(records, new ResultCallback<Record[]>() {
@Override
public void onSuccess(Object result) {
Record[] presavedRecords = null;
if (result instanceof List) {
List<Record> theList = (List<Record>)result;
presavedRecords = theList.toArray(new Record[theList.size()]);
} else if (result instanceof Record[]) {
presavedRecords = (Record[])result;
} else {
presavedRecords = records;
}
RecordSaveRequest request = new RecordSaveRequest(presavedRecords, Database.this);
public void onSuccess(Record[] result) {
RecordSaveRequest request = new RecordSaveRequest(result, Database.this);
request.responseHandler = responseHandler;

Database.this.getContainer().sendRequest(request);
Expand Down Expand Up @@ -234,19 +276,10 @@ public void saveAtomically(Record record, RecordSaveResponseHandler handler) {
public void saveAtomically(final Record[] records, RecordSaveResponseHandler handler) {
final Record[] recordsToSave = records;
final RecordSaveResponseHandler responseHandler = handler;
this.presave(records, new ResultCallback() {
this.presave(records, new ResultCallback<Record[]>() {
@Override
public void onSuccess(Object result) {
Record[] presavedRecords = null;
if (result instanceof List) {
List<Record> theList = (List<Record>)result;
presavedRecords = theList.toArray(new Record[theList.size()]);
} else if (result instanceof Record[]) {
presavedRecords = (Record[])result;
} else {
presavedRecords = records;
}
RecordSaveRequest request = new RecordSaveRequest(presavedRecords, Database.this);
public void onSuccess(Record[] result) {
RecordSaveRequest request = new RecordSaveRequest(result, Database.this);
request.setAtomic(true);
request.responseHandler = responseHandler;

Expand Down

0 comments on commit 4da830b

Please sign in to comment.