| /* |
| * 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.editor.rebind.model; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.typeinfo.JClassType; |
| import com.google.gwt.core.ext.typeinfo.TypeOracle; |
| import com.google.gwt.editor.client.CompositeEditor; |
| import com.google.gwt.editor.client.HasEditorDelegate; |
| import com.google.gwt.editor.client.HasEditorErrors; |
| import com.google.gwt.editor.client.LeafValueEditor; |
| import com.google.gwt.editor.client.ValueAwareEditor; |
| |
| |
| /** |
| * Describes how an Editor is related to bean properties. This type contains |
| * answers to questions asked by the generator code. |
| */ |
| public class EditorData { |
| /** |
| * Used to construct EditorData objects. |
| */ |
| public static class Builder { |
| private EditorAccess access; |
| private EditorData data = new EditorData(); |
| private final TreeLogger logger; |
| private EditorData parent; |
| |
| public Builder(TreeLogger logger) { |
| this.logger = logger; |
| } |
| |
| public Builder access(EditorAccess access) throws UnableToCompleteException { |
| this.access = access; |
| data.declaredPath = access.getPath(); |
| data.editorType = access.getEditorType(); |
| data.editedType = EditorModel.calculateEditedType(logger, data.editorType); |
| data.simpleExpression = access.getExpresson(); |
| |
| TypeOracle oracle = data.editorType.getOracle(); |
| JClassType leafType = oracle.findType(LeafValueEditor.class.getName()); |
| data.isLeaf = leafType.isAssignableFrom(data.editorType); |
| |
| JClassType composedType = oracle.findType(CompositeEditor.class.getName()); |
| data.isCompositeEditor = composedType.isAssignableFrom(data.editorType); |
| |
| JClassType hasDelegateType = oracle.findType(HasEditorDelegate.class.getName()); |
| JClassType hasEditorErrorsType = oracle.findType(HasEditorErrors.class.getName()); |
| data.isDelegateRequired = hasDelegateType.isAssignableFrom(data.editorType) |
| || hasEditorErrorsType.isAssignableFrom(data.editorType) |
| || !ModelUtils.isValueType(oracle, data.editedType); |
| |
| JClassType valueAwareType = oracle.findType(ValueAwareEditor.class.getName()); |
| data.isValueAware = valueAwareType.isAssignableFrom(data.editorType); |
| |
| return this; |
| } |
| |
| public Builder beanOwnerExpression(String value) { |
| data.beanOwnerExpression = value; |
| return this; |
| } |
| |
| public Builder beanOwnerGuard(String value) { |
| data.beanOwnerGuard = value; |
| return this; |
| } |
| |
| public EditorData build() throws UnableToCompleteException { |
| if (data == null) { |
| throw new IllegalStateException(); |
| } |
| try { |
| data.editorExpression = (parent == null ? "" |
| : (parent.getExpression() + ".")) |
| + access.getExpresson(); |
| data.path = (parent == null ? "" : (parent.getPath() + ".")) |
| + access.getPath(); |
| |
| if (data.isCompositeEditor) { |
| TreeLogger compositeLogger = logger.branch(TreeLogger.DEBUG, |
| "Examining composite editor at " + data.path); |
| JClassType subEditorType = EditorModel.calculateCompositeTypes(data.editorType)[1]; |
| data.composedData = new Builder(compositeLogger).access( |
| EditorAccess.root(subEditorType)).parent(data).build(); |
| } |
| return data; |
| } finally { |
| data = null; |
| } |
| } |
| |
| public Builder getterName(String value) { |
| data.getterName = value; |
| return this; |
| } |
| |
| public Builder parent(EditorData value) { |
| parent = value; |
| return this; |
| } |
| |
| public Builder propertyOwnerType(JClassType ownerType) { |
| data.propertyOwnerType = ownerType; |
| return this; |
| } |
| |
| public Builder setterName(String value) { |
| data.setterName = value; |
| return this; |
| } |
| } |
| |
| private String beanOwnerExpression = ""; |
| private String beanOwnerGuard = "true"; |
| private EditorData composedData; |
| private String declaredPath; |
| private JClassType editedType; |
| private JClassType editorType; |
| private String editorExpression; |
| private String getterName; |
| private boolean isLeaf; |
| private boolean isCompositeEditor; |
| private boolean isDelegateRequired; |
| private boolean isValueAware; |
| private String path; |
| private JClassType propertyOwnerType; |
| private String setterName; |
| private String simpleExpression; |
| |
| private EditorData() { |
| } |
| |
| public String getBeanOwnerExpression() { |
| return beanOwnerExpression; |
| } |
| |
| public String getBeanOwnerGuard(String ownerExpression) { |
| return String.format(beanOwnerGuard, ownerExpression); |
| } |
| |
| public EditorData getComposedData() { |
| return composedData; |
| } |
| |
| /** |
| * Gets the path specified by the {@code @Path} annotation or inferred via |
| * convention. |
| */ |
| public String getDeclaredPath() { |
| return declaredPath; |
| } |
| |
| public JClassType getEditedType() { |
| return editedType; |
| } |
| |
| public JClassType getEditorType() { |
| return editorType; |
| } |
| |
| /** |
| * Returns a complete expression to retrieve the editor. |
| */ |
| public String getExpression() { |
| return editorExpression; |
| } |
| |
| public String getGetterName() { |
| return getterName; |
| } |
| |
| /** |
| * Returns the complete path of the editor, relative to the root object. |
| */ |
| public String getPath() { |
| return path; |
| } |
| |
| public String getPropertyName() { |
| return getPath().substring(getPath().lastIndexOf('.') + 1); |
| } |
| |
| /** |
| * Mainly useful for nested properties where there may not be an editor for |
| * the enclosing instance (e.g. <code>person.manager.name</code>). |
| */ |
| public JClassType getPropertyOwnerType() { |
| return propertyOwnerType; |
| } |
| |
| public String getSetterName() { |
| return setterName; |
| } |
| |
| /** |
| * Returns an expression relative to the enclosing Editor to retrieve the |
| * editor. |
| */ |
| public String getSimpleExpression() { |
| return simpleExpression; |
| } |
| |
| /** |
| * Indicates if the Editor is a {@link ComposedEditor . |
| */ |
| public boolean isCompositeEditor() { |
| return isCompositeEditor; |
| } |
| |
| /** |
| * Returns <code>true</code> if the editor "reaches through" an interstitial |
| * property. |
| */ |
| public boolean isDeclaredPathNested() { |
| return declaredPath.contains("."); |
| } |
| |
| /** |
| * Returns <code>true<code> if the editor requires an EditorDelegate. |
| */ |
| public boolean isDelegateRequired() { |
| return isDelegateRequired; |
| } |
| |
| /** |
| * Indicates if the Editor extends {@link LeafValueEditor}. |
| */ |
| public boolean isLeafValueEditor() { |
| return isLeaf; |
| } |
| |
| /** |
| * Indicates if the Editor extends {@link ValueAwareEditor}. |
| */ |
| public boolean isValueAwareEditor() { |
| return isValueAware; |
| } |
| |
| /** |
| * For debugging use only. |
| */ |
| @Override |
| public String toString() { |
| return getPath() + " = " + getEditorType(); |
| } |
| } |