| /* |
| * 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.editor.client.Editor; |
| import com.google.gwt.editor.client.EditorDriver; |
| import com.google.gwt.editor.client.impl.DelegateMap.KeyMethod; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.validation.ConstraintViolation; |
| |
| /** |
| * Abstraction of a ConstraintViolation or a RequestFactory Violation object. |
| * Also contains a factory method to create SimpleViolation instances from |
| * {@link ConstraintViolation} objects. |
| */ |
| public abstract class SimpleViolation { |
| /** |
| * Provides a source of SimpleViolation objects based on ConstraintViolations. |
| * This is re-used by the RequestFactoryEditorDriver implementation, which |
| * does not share a type hierarchy with the SimpleBeanEditorDriver. |
| */ |
| static class ConstraintViolationIterable implements Iterable<SimpleViolation> { |
| |
| private final Iterable<ConstraintViolation<?>> violations; |
| |
| public ConstraintViolationIterable( |
| Iterable<ConstraintViolation<?>> violations) { |
| this.violations = violations; |
| } |
| |
| public Iterator<SimpleViolation> iterator() { |
| // Use a fresh source iterator each time |
| final Iterator<ConstraintViolation<?>> source = violations.iterator(); |
| return new Iterator<SimpleViolation>() { |
| public boolean hasNext() { |
| return source.hasNext(); |
| } |
| |
| public SimpleViolation next() { |
| return new SimpleViolationAdapter(source.next()); |
| } |
| |
| public void remove() { |
| source.remove(); |
| } |
| }; |
| } |
| } |
| |
| /** |
| * Adapts the ConstraintViolation interface to the SimpleViolation interface. |
| */ |
| static class SimpleViolationAdapter extends SimpleViolation { |
| private final ConstraintViolation<?> v; |
| |
| public SimpleViolationAdapter(ConstraintViolation<?> v) { |
| this.v = v; |
| } |
| |
| @Override |
| public Object getKey() { |
| return v.getLeafBean(); |
| } |
| |
| @Override |
| public String getMessage() { |
| return v.getMessage(); |
| } |
| |
| @Override |
| public String getPath() { |
| /* |
| * TODO(bobv,nchalko): Determine the correct way to extract this |
| * information from the ConstraintViolation. |
| */ |
| return v.getPropertyPath().toString(); |
| } |
| |
| @Override |
| public Object getUserDataObject() { |
| return v; |
| } |
| } |
| |
| public static Iterable<SimpleViolation> iterableFromConstrantViolations( |
| Iterable<ConstraintViolation<?>> violations) { |
| return new ConstraintViolationIterable(violations); |
| } |
| |
| /** |
| * Maps an abstract representation of a violation into the appropriate |
| * EditorDelegate. |
| */ |
| public static void pushViolations(Iterable<SimpleViolation> violations, |
| EditorDriver<?> driver, KeyMethod keyMethod) { |
| DelegateMap delegateMap = DelegateMap.of(driver, keyMethod); |
| |
| // For each violation |
| for (SimpleViolation error : violations) { |
| Object key = error.getKey(); |
| List<AbstractEditorDelegate<?, ?>> delegateList = delegateMap.get(key); |
| 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.getDelegatesByPath(absolutePath); |
| List<Editor<?>> editors = delegateMap.getEditorByPath(absolutePath); |
| if (leafDelegates != null) { |
| for (AbstractEditorDelegate<?, ?> delegate : leafDelegates) { |
| delegate.recordError(error.getMessage(), null, |
| error.getUserDataObject()); |
| } |
| } else if (editors != null) { |
| // No EditorDelegate to attach it to, so fake the source |
| for (Editor<?> editor : editors) { |
| baseDelegate.recordError(error.getMessage(), null, |
| error.getUserDataObject(), error.getPath(), editor); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Typically constructed via factory methods. |
| */ |
| protected SimpleViolation() { |
| } |
| |
| /** |
| * Return the object that the violation is about. |
| */ |
| public abstract Object getKey(); |
| |
| /** |
| * Return a user-facing message describing the violation. |
| */ |
| public abstract String getMessage(); |
| |
| /** |
| * Return a dotted path describing the property. |
| */ |
| public abstract String getPath(); |
| |
| /** |
| * An object that should be available from |
| * {@link com.google.gwt.editor.client.EditorError#getUserData()}. |
| */ |
| public abstract Object getUserDataObject(); |
| } |