aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2017-03-13 16:33:45 +0200
committerGitHub <noreply@github.com>2017-03-13 16:33:45 +0200
commit40974e9d8388b6fd77421ad02704f027470aa252 (patch)
tree7fb8e6314f739d71130aef615e6b5ffc337ace06 /server/src/main
parent6c567a4ef5b8e1c9b13876a0a2df6c117d2adf59 (diff)
downloadvaadin-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.java136
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);
}