| /* |
| * Copyright 2011 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.editor.client.impl; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.editor.client.Editor; |
| import com.google.gwt.editor.client.EditorDriver; |
| import com.google.gwt.editor.client.EditorError; |
| import com.google.gwt.editor.client.EditorVisitor; |
| import com.google.gwt.editor.client.LeafValueEditor; |
| import com.google.gwt.editor.client.impl.DelegateMap.KeyMethod; |
| import com.google.gwt.editor.client.testing.EditorHierarchyPrinter; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.validation.ConstraintViolation; |
| |
| /** |
| * Contains common code shared between the SimpleBeanEditorDriver and |
| * RequestFactoryEditorDriver. |
| * |
| * @param <T> the type of data being edited |
| * @param <E> the type of editor |
| */ |
| public abstract class BaseEditorDriver<T, E extends Editor<T>> { |
| private AbstractEditorDelegate<T, E> delegate; |
| /** |
| * Used for {@link #isDirty()} computations. |
| */ |
| private Map<LeafValueEditor<?>, Object> leafValueMap; |
| private E editor; |
| private List<EditorError> errors; |
| private T object; |
| |
| public abstract void accept(EditorVisitor visitor); |
| |
| public List<EditorError> getErrors() { |
| return errors; |
| } |
| |
| public boolean hasErrors() { |
| return !errors.isEmpty(); |
| } |
| |
| public boolean isDirty() { |
| DirtCollector c = new DirtCollector(); |
| accept(c); |
| return c.isDirty() || !leafValueMap.equals(c.getLeafValues()); |
| } |
| |
| public boolean setConstraintViolations( |
| final Iterable<ConstraintViolation<?>> violations) { |
| return doSetViolations(SimpleViolation.iterableFromConstrantViolations(violations)); |
| } |
| |
| @Override |
| public String toString() { |
| if (GWT.isProdMode()) { |
| return super.toString(); |
| } else { |
| return editor == null ? "Uninitialized" |
| : EditorHierarchyPrinter.toString(asEditorDriver()); |
| } |
| } |
| |
| protected void configureDelegate(AbstractEditorDelegate<T, E> rootDelegate) { |
| rootDelegate.initialize("", getEditor()); |
| } |
| |
| protected abstract AbstractEditorDelegate<T, E> createDelegate(); |
| |
| protected void doEdit(T object) { |
| checkEditor(); |
| object = delegate.ensureMutable(object); |
| this.object = object; |
| delegate.setObject(object); |
| accept(new Initializer()); |
| DirtCollector c = new DirtCollector(); |
| accept(c); |
| leafValueMap = c.getLeafValues(); |
| } |
| |
| protected void doFlush() { |
| checkObject(); |
| errors = new ArrayList<EditorError>(); |
| accept(new Flusher()); |
| accept(new ErrorCollector(errors)); |
| } |
| |
| protected void doInitialize(E editor) { |
| this.editor = editor; |
| delegate = createDelegate(); |
| configureDelegate(delegate); |
| } |
| |
| protected boolean doSetViolations(Iterable<SimpleViolation> violations) { |
| checkObject(); |
| SimpleViolation.pushViolations(violations, asEditorDriver(), |
| getViolationKeyMethod()); |
| |
| // Collect the errors, which will take care of co-editor chains. |
| errors = new ArrayList<EditorError>(); |
| accept(new ErrorCollector(errors)); |
| return hasErrors(); |
| } |
| |
| protected AbstractEditorDelegate<T, E> getDelegate() { |
| return delegate; |
| } |
| |
| protected E getEditor() { |
| return editor; |
| } |
| |
| protected T getObject() { |
| return object; |
| } |
| |
| protected KeyMethod getViolationKeyMethod() { |
| return DelegateMap.IDENTITY; |
| } |
| |
| /** |
| * This cast avoids the need to add another parameterization to |
| * BaseEditorDriver since the class cannot be declared to extend an unbound |
| * interface. |
| */ |
| private EditorDriver<?> asEditorDriver() { |
| return (EditorDriver<?>) this; |
| } |
| |
| private void checkEditor() { |
| if (editor == null) { |
| throw new IllegalStateException("Must call initialize() first"); |
| } |
| } |
| |
| private void checkObject() { |
| if (object == null) { |
| throw new IllegalStateException("Must call edit() first"); |
| } |
| } |
| } |