diff options
author | Artur <artur@vaadin.com> | 2017-03-13 16:33:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-13 16:33:45 +0200 |
commit | 40974e9d8388b6fd77421ad02704f027470aa252 (patch) | |
tree | 7fb8e6314f739d71130aef615e6b5ffc337ace06 /server/src/main | |
parent | 6c567a4ef5b8e1c9b13876a0a2df6c117d2adf59 (diff) | |
download | vaadin-framework-40974e9d8388b6fd77421ad02704f027470aa252.tar.gz vaadin-framework-40974e9d8388b6fd77421ad02704f027470aa252.zip |
Read/write Grid item type to declarative and create columns correctly (#8769)
Fixes #8467
Diffstat (limited to 'server/src/main')
-rw-r--r-- | server/src/main/java/com/vaadin/ui/Grid.java | 136 |
1 files changed, 118 insertions, 18 deletions
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 3611726ecd..cfd0ff2006 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -72,6 +72,7 @@ import com.vaadin.server.SerializableComparator; import com.vaadin.server.SerializableFunction; import com.vaadin.server.SerializableSupplier; import com.vaadin.server.Setter; +import com.vaadin.server.VaadinServiceClassLoaderUtil; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.Registration; import com.vaadin.shared.data.DataCommunicatorConstants; @@ -135,6 +136,8 @@ import elemental.json.JsonValue; public class Grid<T> extends AbstractListing<T> implements HasComponents, HasDataProvider<T>, SortNotifier<GridSortOrder<T>> { + private static final String DECLARATIVE_DATA_ITEM_TYPE = "data-item-type"; + /** * A callback method for fetching items. The callback is provided with a * list of sort orders, offset index and limit. @@ -2038,7 +2041,9 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, private Editor<T> editor; - private final PropertySet<T> propertySet; + private PropertySet<T> propertySet; + + private Class<T> beanType = null; /** * Creates a new grid without support for creating columns based on property @@ -2079,6 +2084,7 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, */ public Grid(Class<T> beanType) { this(BeanPropertySet.get(beanType)); + this.beanType = beanType; } /** @@ -2093,24 +2099,14 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, * the property set implementation to use, not <code>null</code>. */ protected Grid(PropertySet<T> propertySet) { - Objects.requireNonNull(propertySet, "propertySet cannot be null"); - this.propertySet = propertySet; - registerRpc(new GridServerRpcImpl()); - setDefaultHeaderRow(appendHeaderRow()); - setSelectionModel(new SingleSelectionModelImpl<>()); detailsManager = new DetailsManager<>(); addExtension(detailsManager); addDataGenerator(detailsManager); - editor = createEditor(); - if (editor instanceof Extension) { - addExtension((Extension) editor); - } - addDataGenerator((item, json) -> { String styleName = styleGenerator.apply(item); if (styleName != null && !styleName.isEmpty()) { @@ -2124,12 +2120,38 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, } }); + setPropertySet(propertySet); + // Automatically add columns for all available properties propertySet.getProperties().map(PropertyDefinition::getName) .forEach(this::addColumn); } /** + * Sets the property set to use for this grid. Does not create or update + * columns in any way but will delete and re-create the editor. + * <p> + * This is only meant to be called from constructors and readDesign, at a + * stage where it does not matter if you throw away the editor. + * + * @param propertySet + * the property set to use + */ + protected void setPropertySet(PropertySet<T> propertySet) { + Objects.requireNonNull(propertySet, "propertySet cannot be null"); + this.propertySet = propertySet; + + if (editor instanceof Extension) { + removeExtension((Extension) editor); + } + editor = createEditor(); + if (editor instanceof Extension) { + addExtension((Extension) editor); + } + + } + + /** * Creates a grid using a custom {@link PropertySet} implementation for * creating a default set of columns and for resolving property names with * {@link #addColumn(String)} and @@ -2201,6 +2223,19 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, this(caption, DataProvider.ofCollection(items)); } + /** + * Gets the bean type used by this grid. + * <p> + * The bean type is used to automatically set up a column added using a + * property name. + * + * @return the used bean type or <code>null</code> if no bean type has been + * defined + */ + public Class<T> getBeanType() { + return beanType; + } + public <V> void fireColumnVisibilityChangeEvent(Column<T, V> column, boolean hidden, boolean userOriginated) { fireEvent(new ColumnVisibilityChangeEvent(this, column, hidden, @@ -3574,6 +3609,11 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, @Override protected void doReadDesign(Element design, DesignContext context) { Attributes attrs = design.attributes(); + if (design.hasAttr(DECLARATIVE_DATA_ITEM_TYPE)) { + String itemType = design.attr(DECLARATIVE_DATA_ITEM_TYPE); + setBeanType(itemType); + } + if (attrs.hasKey("selection-mode")) { setSelectionMode(DesignAttributeHandler.readAttribute( "selection-mode", attrs, SelectionMode.class)); @@ -3598,9 +3638,59 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, } } + /** + * Sets the bean type to use for property mapping. + * <p> + * This method is responsible also for setting or updating the property set + * so that it matches the given bean type. + * <p> + * Protected mostly for Designer needs, typically should not be overridden + * or even called. + * + * @param beanTypeClassName + * the fully qualified class name of the bean type + */ + @SuppressWarnings("unchecked") + protected void setBeanType(String beanTypeClassName) { + setBeanType((Class<T>) resolveClass(beanTypeClassName)); + } + + /** + * Sets the bean type to use for property mapping. + * <p> + * This method is responsible also for setting or updating the property set + * so that it matches the given bean type. + * <p> + * Protected mostly for Designer needs, typically should not be overridden + * or even called. + * + * @param beanType + * the bean type class + */ + protected void setBeanType(Class<T> beanType) { + this.beanType = beanType; + setPropertySet(BeanPropertySet.get(beanType)); + } + + private Class<?> resolveClass(String qualifiedClassName) { + try { + Class<?> resolvedClass = Class.forName(qualifiedClassName, true, + VaadinServiceClassLoaderUtil.findDefaultClassLoader()); + return resolvedClass; + } catch (ClassNotFoundException | SecurityException e) { + throw new IllegalArgumentException( + "Unable to find class " + qualifiedClassName, e); + } + + } + @Override protected void doWriteDesign(Element design, DesignContext designContext) { Attributes attr = design.attributes(); + if (this.beanType != null) { + design.attr(DECLARATIVE_DATA_ITEM_TYPE, + this.beanType.getCanonicalName()); + } DesignAttributeHandler.writeAttribute("selection-allowed", attr, isReadOnly(), false, Boolean.class, designContext); @@ -3679,14 +3769,24 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, for (Element col : colgroups.get(0).getElementsByTag("col")) { String id = DesignAttributeHandler.readAttribute("column-id", col.attributes(), null, String.class); - DeclarativeValueProvider<T> provider = new DeclarativeValueProvider<>(); - Column<T, String> column = new Column<>(provider, - new HtmlRenderer()); - addColumn(getGeneratedIdentifier(), column); - if (id != null) { - column.setId(id); + + // If there is a property with a matching name available, + // map to that + Optional<PropertyDefinition<T, ?>> property = propertySet + .getProperties().filter(p -> p.getName().equals(id)) + .findFirst(); + Column<T, ?> column; + if (property.isPresent()) { + column = addColumn(id); + } else { + DeclarativeValueProvider<T> provider = new DeclarativeValueProvider<>(); + column = new Column<>(provider, new HtmlRenderer()); + addColumn(getGeneratedIdentifier(), column); + if (id != null) { + column.setId(id); + } + providers.add(provider); } - providers.add(provider); column.readDesign(col, context); } |