blob: 50fd17159b522e387b6d8aae8b24c4214c762143 [file] [log] [blame]
/*
* 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.editor.client.Editor;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.impl.AbstractEditorDelegate;
import com.google.gwt.editor.client.impl.DelegateMap;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.Violation;
import java.util.ArrayList;
import java.util.List;
/**
* Contains utility methods for top-level driver implementations.
*
* @param <R> the type of Record
* @param <E> the type of Editor
*/
public abstract class AbstractRequestFactoryEditorDriver<R, E extends Editor<R>>
implements RequestFactoryEditorDriver<R, E> {
private static final DelegateMap.KeyMethod PROXY_ID_KEY = new DelegateMap.KeyMethod() {
public Object key(Object object) {
if (object instanceof EntityProxy) {
return ((EntityProxy) object).stableId();
}
return null;
}
};
private RequestFactoryEditorDelegate<R, E> delegate;
private DelegateMap delegateMap = new DelegateMap(PROXY_ID_KEY);
private E editor;
private EventBus eventBus;
private List<EditorError> errors;
private List<String> paths = new ArrayList<String>();
private RequestFactory requestFactory;
private RequestContext saveRequest;
public void display(R object) {
edit(object, null);
}
public void edit(R object, RequestContext saveRequest) {
checkEditor();
this.saveRequest = saveRequest;
delegate = createDelegate();
delegate.initialize(eventBus, requestFactory, "", object, editor,
delegateMap, saveRequest);
delegateMap.put(object, delegate);
}
public RequestContext flush() {
checkDelegate();
checkSaveRequest();
errors = new ArrayList<EditorError>();
delegate.flush(errors);
return saveRequest;
}
public List<EditorError> getErrors() {
return errors;
}
public String[] getPaths() {
return paths.toArray(new String[paths.size()]);
}
public boolean hasErrors() {
return !errors.isEmpty();
}
public void initialize(E editor) {
doInitialize(null, null, editor);
}
public void initialize(EventBus eventBus, RequestFactory requestFactory,
E editor) {
assert eventBus != null : "eventBus must not be null";
assert requestFactory != null : "requestFactory must not be null";
doInitialize(eventBus, requestFactory, editor);
}
public void initialize(RequestFactory requestFactory, E editor) {
initialize(requestFactory.getEventBus(), requestFactory, editor);
}
public boolean setViolations(Iterable<Violation> violations) {
checkDelegate();
// For each violation
for (Violation error : violations) {
/*
* Find the delegates that are attached to the object. Use getRaw() here
* since the violation doesn't include an EntityProxy reference
*/
List<AbstractEditorDelegate<?, ?>> delegateList = delegateMap.getRaw(error.getProxyId());
if (delegateList != null) {
// For each delegate editing some record...
for (AbstractEditorDelegate<?, ?> baseDelegate : delegateList) {
// compute its base path in the hierarchy...
String basePath = baseDelegate.getPath();
// and the absolute path of the leaf editor receiving the error.
String absolutePath = (basePath.length() > 0 ? basePath + "." : "")
+ error.getPath();
// Find the leaf editor's delegate.
List<AbstractEditorDelegate<?, ?>> leafDelegates = delegateMap.getPath(absolutePath);
if (leafDelegates != null) {
// Only attach the error to the first delegate in a co-editor chain.
leafDelegates.get(0).recordError(error.getMessage(), null, error);
} else {
// No EditorDelegate to attach it to, stick it on the base.
baseDelegate.recordError(error.getMessage(), null, error,
error.getPath());
}
}
}
}
// Flush the errors, which will take care of co-editor chains.
errors = new ArrayList<EditorError>();
delegate.flushErrors(errors);
return !errors.isEmpty();
}
protected abstract RequestFactoryEditorDelegate<R, E> createDelegate();
protected E getEditor() {
return editor;
}
protected abstract void traverseEditors(List<String> paths);
private void checkDelegate() {
if (delegate == null) {
throw new IllegalStateException("Must call edit() first");
}
}
private void checkEditor() {
if (editor == null) {
throw new IllegalStateException("Must call initialize() first");
}
}
private void checkSaveRequest() {
if (saveRequest == null) {
throw new IllegalStateException("edit() was called with a null Request");
}
}
private void doInitialize(EventBus eventBus, RequestFactory requestFactory,
E editor) {
this.eventBus = eventBus;
this.requestFactory = requestFactory;
this.editor = editor;
traverseEditors(paths);
}
}