package com.mycompany.client; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.core.DataClass; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.data.DataSource; import com.smartgwt.client.widgets.grid.ListGridRecord; public abstract class GwtRpcDataSource extends DataSource { static final String DO_NOT_HANDLE = "doNotHandle"; private static final String DO_NOT_PROPAGATE = "doNotPropagate"; private GwtRpcDataSourceEndpoint fetchEndpoint; private GwtRpcDataSourceEndpoint updateEndpoint; private GwtRpcDataSourceEndpoint addEndpoint; private GwtRpcDataSourceEndpoint removeEndpoint; private boolean batchMode = false; private Object[] parameters = new Object[0]; public GwtRpcDataSource() { setClientOnly(true); } public void setFetchEndpoint(GwtRpcDataSourceEndpoint fetchEndpoint) { this.fetchEndpoint = fetchEndpoint; } /* * Note if the GWT-RPC call fails the internal datasource data will be out of * sync with dependent widgets. This will become obvious the next time a * widget syncs to the datasource without triggering a fetch. One workaround * is to call fetchData again in postFailure, but since that kicks off an * extra server request that is not the default behavior. */ public void setUpdateEndpoint(GwtRpcDataSourceEndpoint updateEndpoint) { this.updateEndpoint = updateEndpoint; } public void setAddEndpoint(GwtRpcDataSourceEndpoint addEndpoint) { this.addEndpoint = addEndpoint; } public void setRemoveEndpoint(GwtRpcDataSourceEndpoint removeEndpoint) { this.removeEndpoint = removeEndpoint; } /* * If bulkMode is true the first parameter in the variable arguments for * update/add/remove will be a ListGridRecord[] instead of a ListGridRecord. * This means the endpoint will only be called once instead of n times where * n is the length of the ListGridRecord array. */ public void setBatchMode(boolean batchMode) { this.batchMode = batchMode; } public void setParameters(Object... parameters) { this.parameters = parameters; } @Override protected void transformResponse(DSResponse response, DSRequest request, Object data) { if (request.getOperationType() != null) { ListGridRecord[] records = response.getData(); switch (request.getOperationType()) { case ADD: if (request.getAttributeAsBoolean(DO_NOT_PROPAGATE) != null && request.getAttributeAsBoolean(DO_NOT_PROPAGATE).equals(Boolean.TRUE)) { response.setStatus(-1); } else if (request.getAttributeAsBoolean(DO_NOT_HANDLE) == null || request.getAttributeAsBoolean(DO_NOT_HANDLE).equals(Boolean.FALSE)) { response.setStatus(-1); executeAdd(records, request); } break; case FETCH: executeFetch(request); break; case REMOVE: if (request.getAttributeAsBoolean(DO_NOT_HANDLE) == null || request.getAttributeAsBoolean(DO_NOT_HANDLE).equals(Boolean.FALSE)) { executeRemove(records, request); response.setStatus(-1); } break; case UPDATE: if (request.getAttributeAsBoolean(DO_NOT_HANDLE) == null || request.getAttributeAsBoolean(DO_NOT_HANDLE).equals(Boolean.FALSE)) { response.setStatus(-1); executeUpdate(records, request); } break; default: break; } } super.transformResponse(response, request, data); } protected abstract void populateRecord(ListGridRecord record, T object); private void executeUpdate(final ListGridRecord[] records, DSRequest request) { if (batchMode) { updateEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { updateEndpoint.postFailure(caught); } public void onSuccess(Object result) { for (int i = 0; i < records.length; i++) { ListGridRecord listGridRecord = records[i]; DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); updateData(listGridRecord, null, req); updateEndpoint.postSuccess(result); } updateEndpoint.postSuccess(result); } }, request, (Object) records, parameters); } else { for (int i = 0; i < records.length; i++) { final ListGridRecord listGridRecord = records[i]; updateEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { updateEndpoint.postFailure(caught); } public void onSuccess(Object result) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); updateData(listGridRecord, null, req); updateEndpoint.postSuccess(result); } }, request, listGridRecord, parameters); } } } private void executeRemove(final ListGridRecord[] records, DSRequest request) { if (batchMode) { removeEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { for (int i = 0; i < records.length; i++) { ListGridRecord listGridRecord = records[i]; DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); addData(listGridRecord, null, req); } removeEndpoint.postFailure(caught); } public void onSuccess(Object result) { for (int i = 0; i < records.length; i++) { ListGridRecord listGridRecord = records[i]; DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_PROPAGATE, true); addData(listGridRecord, null, req); DSRequest req2 = new DSRequest(); req2.setAttribute(DO_NOT_HANDLE, true); removeData(listGridRecord, null, req2); } removeEndpoint.postSuccess(result); } }, request, (Object) records, parameters); } else { for (int i = 0; i < records.length; i++) { final ListGridRecord listGridRecord = records[i]; removeEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); addData(listGridRecord, null, req); removeEndpoint.postFailure(caught); } public void onSuccess(Object result) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_PROPAGATE, true); addData(listGridRecord, null, req); DSRequest req2 = new DSRequest(); req2.setAttribute(DO_NOT_HANDLE, true); removeData(listGridRecord, null, req2); removeEndpoint.postSuccess(result); } }, request, listGridRecord, parameters); } } } private void executeFetch(DSRequest request) { fetchEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { fetchEndpoint.postFailure(caught); } public void onSuccess(Object object) { Collection resultSet = fetchEndpoint.transformResult(object); DataClass[] testData = getTestData(); Map recordSet = new HashMap(); for (int i = 0; i < testData.length; i++) { recordSet.put(testData[i].getAttribute(getPrimaryKeyFieldName()), testData[i]); } for (final T result : resultSet) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); final ListGridRecord record = new ListGridRecord(); populateRecord(record, result); if (record.getAttribute(getPrimaryKeyFieldName()) != null) { Object primaryKey = record.getAttribute(getPrimaryKeyFieldName()); if (recordSet.containsKey(primaryKey)) { updateData(record, null, req); recordSet.remove(primaryKey); } else { addData(record, null, req); } } } for (Entry recordEntry : recordSet.entrySet()) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); ListGridRecord tempRecord = new ListGridRecord(); tempRecord.setAttribute(getPrimaryKeyFieldName(), recordEntry.getValue().getAttribute(getPrimaryKeyFieldName())); removeData(tempRecord, null, req); } fetchEndpoint.postSuccess(object); } }, request, parameters); } private void executeAdd(final ListGridRecord[] records, DSRequest request) { if (batchMode) { addEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { for (int i = 0; i < records.length; i++) { ListGridRecord listGridRecord = records[i]; DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); removeData(listGridRecord, null, req); } addEndpoint.postFailure(caught); } public void onSuccess(Object result) { for (int i = 0; i < records.length; i++) { ListGridRecord listGridRecord = records[i]; DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); addData(listGridRecord, null, req); } addEndpoint.postSuccess(result); } }, request, records, parameters); } else { for (int i = 0; i < records.length; i++) { final ListGridRecord listGridRecord = records[i]; addEndpoint.callEndpoint(new AsyncCallback() { public void onFailure(Throwable caught) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); removeData(listGridRecord, null, req); addEndpoint.postFailure(caught); } public void onSuccess(Object result) { DSRequest req = new DSRequest(); req.setAttribute(DO_NOT_HANDLE, true); addData(listGridRecord, null, req); addEndpoint.postSuccess(result); } }, request, listGridRecord, parameters); } } } }