blob: 0e0a92c1f29f65b55fd90e485ceb6ca1716f6a42 [file]
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.requestfactory.client.impl;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.requestfactory.client.impl.DeltaValueStoreJsonImpl.ReturnRecord;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.RequestObject;
import com.google.gwt.requestfactory.shared.ServerFailure;
import com.google.gwt.requestfactory.shared.Violation;
import com.google.gwt.requestfactory.shared.impl.Property;
import com.google.gwt.requestfactory.shared.impl.RequestData;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* <p>
* <span style="color:red">Experimental API: This class is still under rapid
* development, and is very likely to be deleted. Use it at your own risk.
* </span>
* </p>
* Abstract implementation of {@link RequestObject}. Each request stores a
* {@link DeltaValueStoreJsonImpl}.
*
* @param <T> return type
* @param <R> type of this request object
*/
public abstract class AbstractRequest<T, R extends AbstractRequest<T, R>>
implements RequestObject<T> {
protected final RequestFactoryJsonImpl requestFactory;
protected DeltaValueStoreJsonImpl deltaValueStore;
private Receiver<T> receiver;
private final Set<String> propertyRefs = new HashSet<String>();
public AbstractRequest(RequestFactoryJsonImpl requestFactory) {
this.requestFactory = requestFactory;
ValueStoreJsonImpl valueStore = requestFactory.getValueStore();
this.deltaValueStore = new DeltaValueStoreJsonImpl(valueStore,
requestFactory);
}
@SuppressWarnings("unchecked")
public <P extends EntityProxy> P edit(P record) {
P returnRecordImpl = (P) ((ProxyImpl) record).getSchema().create(
((ProxyImpl) record).asJso(), ((ProxyImpl) record).isFuture());
((ProxyImpl) returnRecordImpl).setDeltaValueStore(deltaValueStore);
return returnRecordImpl;
}
public void fire(Receiver<T> receiver) {
assert null != receiver : "receiver cannot be null";
this.receiver = receiver;
requestFactory.fire(this);
}
/**
* @deprecated use {@link #with(String...)} instead.
* @param properties
*/
@Deprecated
public R forProperties(Collection<Property<?>> properties) {
for (Property<?> p : properties) {
with(p.getName());
}
return getThis();
}
/**
* @return the properties
*/
public Set<String> getPropertyRefs() {
return Collections.unmodifiableSet(propertyRefs);
}
public abstract RequestData getRequestData();
public void handleResponseText(String responseText) {
JsonResults results = JsonResults.fromResults(responseText);
JsonServerException cause = results.getException();
if (cause != null) {
fail(new ServerFailure(
cause.getMessage(), cause.getType(), cause.getTrace()));
return;
}
processRelated(results.getRelated());
// handle violations
JsArray<DeltaValueStoreJsonImpl.ReturnRecord> violationsArray = results.getViolations();
if (violationsArray != null) {
int length = violationsArray.length();
Set<Violation> errors = new HashSet<Violation>(length);
for (int i = 0; i < length; i++) {
ReturnRecord violationRecord = violationsArray.get(i);
String id = null;
if (violationRecord.hasFutureId()) {
id = violationRecord.getFutureId();
} else {
id = violationRecord.getId();
}
final EntityProxyIdImpl key = new EntityProxyIdImpl(id,
requestFactory.getSchema(violationRecord.getSchema()),
violationRecord.hasFutureId(), null);
assert violationRecord.hasViolations();
HashMap<String, String> violations = new HashMap<String, String>();
violationRecord.fillViolations(violations);
for (Map.Entry<String, String> entry : violations.entrySet()) {
final String path = entry.getKey();
final String message = entry.getValue();
errors.add(new Violation() {
public String getMessage() {
return message;
}
public String getPath() {
return path;
}
public EntityProxyId getProxyId() {
return key;
}
});
}
}
deltaValueStore.reuse();
receiver.onViolation(errors);
} else {
deltaValueStore.commit(results.getSideEffects());
handleResult(results.getResult());
}
}
public boolean isChanged() {
return deltaValueStore.isChanged();
}
/*
* used from the JSNI method processRelated.
*/
public void pushToValueStore(String schemaToken, JavaScriptObject jso) {
requestFactory.getValueStore().putInValueStore(
ProxyJsoImpl.create(jso, requestFactory.getSchema(schemaToken),
requestFactory));
}
public R with(String... propertyRef) {
for (String ref : propertyRef) {
propertyRefs.add(ref);
}
return getThis();
}
protected String asString(Object jso) {
return String.valueOf(jso);
}
protected void fail(ServerFailure failure) {
deltaValueStore.reuse();
receiver.onFailure(failure);
}
/**
* Subclasses must override to return {@code this}, to allow builder-style
* methods to do the same.
*/
protected abstract R getThis();
/**
* Process the response and call {@link #succeed(Object) or
* #fail(com.google.gwt.requestfactory.shared.ServerFailure).
*/
protected abstract void handleResult(Object result);
protected native void processRelated(JavaScriptObject related) /*-{
for(var recordKey in related) {
// Workaround for __gwt_ObjectId appearing in Chrome dev mode.
if (!related.hasOwnProperty(recordKey)) continue;
var schemaAndId = recordKey.split(/-/, 2);
var jso = related[recordKey];
this.@com.google.gwt.requestfactory.client.impl.AbstractRequest::pushToValueStore(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)(schemaAndId[0], jso);
}
}-*/;
protected void succeed(T t) {
receiver.onSuccess(t);
}
}