Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.mateu.mdd.vaadin.components.fieldBuilders.JPAOneToManyFieldBuilder Maven / Gradle / Ivy
package io.mateu.mdd.vaadin.components.fieldBuilders;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.vaadin.data.*;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.data.validator.BeanValidator;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.server.ClassResource;
import com.vaadin.server.ExternalResource;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.EffectAllowed;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.ui.*;
import com.vaadin.ui.dnd.DragSourceExtension;
import com.vaadin.ui.dnd.DropTargetExtension;
import com.vaadin.ui.themes.ValoTheme;
import io.mateu.mdd.core.MDD;
import io.mateu.mdd.core.app.AbstractAction;
import io.mateu.mdd.core.dataProviders.JPQLListDataProvider;
import io.mateu.mdd.core.interfaces.AbstractStylist;
import io.mateu.mdd.core.interfaces.Card;
import io.mateu.mdd.core.interfaces.GridDecorator;
import io.mateu.mdd.core.ui.MDDUIAccessor;
import io.mateu.mdd.shared.CSS;
import io.mateu.mdd.shared.annotations.*;
import io.mateu.mdd.shared.data.FareValue;
import io.mateu.mdd.shared.interfaces.IResource;
import io.mateu.mdd.shared.reflection.FieldInterfaced;
import io.mateu.mdd.vaadin.MateuUI;
import io.mateu.mdd.vaadin.components.views.ListViewComponent;
import io.mateu.mdd.vaadin.data.MDDBinder;
import io.mateu.mdd.vaadin.util.VaadinHelper;
import io.mateu.reflection.*;
import io.mateu.util.Helper;
import io.mateu.util.notification.Notifier;
import lombok.extern.slf4j.Slf4j;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.*;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class JPAOneToManyFieldBuilder extends AbstractFieldBuilder {
public boolean isSupported(FieldInterfaced field) {
//boolean ok = field.isAnnotationPresent(OneToMany.class) || field.isAnnotationPresent(ElementCollection.class) || field.isAnnotationPresent(ManyToMany.class);
boolean ok = Collection.class.isAssignableFrom(field.getType());
if (ok) {
Class gc = ReflectionHelper.getGenericClass(field, Collection.class, "E");
ok &= !(String.class.equals(gc) || Integer.class.equals(gc) || Long.class.equals(gc) || Float.class.equals(gc) || Double.class.equals(gc) || Boolean.class.equals(gc));
}
if (!ok) ok = Map.class.isAssignableFrom(field.getType());
return ok;
}
@Override
public Component build(VerticalLayout fieldGroup, HorizontalLayout fieldGroupHeader, FieldInterfaced field, Object object, Layout container, MDDBinder binder, Map> validators, AbstractStylist stylist, Map allFieldContainers, boolean forSearchFilter, Map> attachedActions) {
Component r = null;
if (forSearchFilter) {
// todo: añadir para contains
} else {
boolean owned = ReflectionHelper.isOwnedCollection(field);
if (Map.class.isAssignableFrom(field.getType())) {
r = buildMap(fieldGroup, fieldGroupHeader, field, object, container, binder, validators, stylist, allFieldContainers, forSearchFilter, owned, attachedActions);
} else {
r = buildList(field, object, container, binder, validators, stylist, allFieldContainers, forSearchFilter, owned, attachedActions);
}
}
if (r != null) r.addStyleName("test-" + field.getId());
return r;
}
private Component buildList(FieldInterfaced field, Object object, Layout container, MDDBinder binder, Map> validators, AbstractStylist stylist, Map allFieldContainers, boolean forSearchFilter, boolean owned, Map> attachedActions) {
Component r = null;
Method mh;
if (field.isAnnotationPresent(UseChips.class)) {
HorizontalLayout hl = new HorizontalLayout();
hl.addStyleName(CSS.NOPADDING);
CssLayout l = new CssLayout();
l.addStyleName(CSS.NOPADDING);
hl.addComponent(l);
Button b;
l.addComponent(b = new Button("Add"));
b.addStyleName(ValoTheme.BUTTON_LINK);
b.addClickListener(e -> MDDUIAccessor.go(field.getName()));
if (allFieldContainers != null) allFieldContainers.put(field, hl);
hl.setCaption(ReflectionHelper.getCaption(field));
addComponent(container, hl, attachedActions.get(field.getName()));
bind(binder, l, field);
addErrorHandler(field, l);
r = l;
} else if (field.isAnnotationPresent(UseTwinCols.class)) {
TwinColSelect tf = new TwinColSelect((container.getComponentCount() > 0)?ReflectionHelper.getCaption(field):null);
tf.setRows(10);
tf.setLeftColumnCaption("Available options");
tf.setRightColumnCaption("Selected options");
if (field.isAnnotationPresent(FullWidth.class)) tf.setWidth("100%");
//tf.addValueChangeListener(event -> Notification.show("Value changed:", String.valueOf(event.getValue()), Type.TRAY_NOTIFICATION));
addComponent(container, tf, attachedActions.get(field.getName()));
JPAManyToOneFieldBuilder.setDataProvider(tf, field, binder);
tf.addValueChangeListener(e -> updateReferences(binder, field, e));
FieldInterfaced fName = ReflectionHelper.getNameField(field.getGenericClass());
if (fName != null) tf.setItemCaptionGenerator((i) -> {
try {
return "" + ReflectionHelper.getValue(fName, i);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return "Error";
});
if (allFieldContainers != null) allFieldContainers.put(field, tf);
tf.setCaption(ReflectionHelper.getCaption(field));
bind(binder, tf, field);
addErrorHandler(field, tf);
r = tf;
} else if (field.isAnnotationPresent(UseLinkToListView.class)) {
HorizontalLayout hl = new HorizontalLayout();
Label l;
hl.addComponent(l = new Label(""));
l.addStyleName("collectionlinklabel");
hl.addStyleName(CSS.CLICKABLE);
hl.addLayoutClickListener(e -> {
//if (e.isDoubleClick())
MDDUIAccessor.go(field.getName());
});
hl.setCaption(ReflectionHelper.getCaption(field));
if (allFieldContainers != null) allFieldContainers.put(field, hl);
addComponent(container, hl, attachedActions.get(field.getName()));
bind(binder, l, field, null);
addErrorHandler(field, l);
r = l;
} else if (field.isAnnotationPresent(UseCheckboxes.class)) {
CheckBoxGroup cbg = new CheckBoxGroup();
JPAManyToOneFieldBuilder.setDataProvider(cbg, field, binder);
/*
cbg.addValueChangeListener(e -> {
updateReferences(binder, field, e);
});
*/
cbg.addValueChangeListener(e -> {
if (e.isUserOriginated()) {
try {
ReflectionHelper.setValue(field, binder.getBean(), e.getValue());
} catch (Exception ex) {
Notifier.alert(ex);
}
}
});
cbg.setCaption(ReflectionHelper.getCaption(field));
if (allFieldContainers != null) allFieldContainers.put(field, cbg);
addComponent(container, cbg, attachedActions.get(field.getName()));
bind(binder, cbg, field);
addErrorHandler(field, cbg);
r = cbg;
} else if ((mh = ReflectionHelper.getMethod(field.getDeclaringClass(), ReflectionHelper.getGetter(field.getName()) + "Html")) != null) {
VerticalLayout hl = new VerticalLayout();
hl.addStyleName("collectionlinklabel");
Label l;
hl.addComponent(l = new Label("", ContentMode.HTML));
hl.addStyleName(CSS.NOPADDING);
hl.addStyleName(CSS.CLICKABLE);
hl.addLayoutClickListener(e -> {
//if (e.isDoubleClick())
MDDUIAccessor.go(field.getName());
});
hl.setCaption(ReflectionHelper.getCaption(field));
if (allFieldContainers != null) allFieldContainers.put(field, hl);
addComponent(container, hl, attachedActions.get(field.getName()));
bind(binder, l, field, mh);
addErrorHandler(field, l);
r = l;
} else if (Card.class.isAssignableFrom(field.getGenericClass())) {
CssLayout hl = new CssLayout();
hl.addStyleName("collectionlinklabel");
hl.setCaption(ReflectionHelper.getCaption(field));
if (allFieldContainers != null) allFieldContainers.put(field, hl);
addComponent(container, hl, attachedActions.get(field.getName()));
bind(binder, hl, field, mh);
addErrorHandler(field, hl);
r = hl;
} else if (IResource.class.isAssignableFrom(field.getGenericClass())) {
CssLayout hl = new CssLayout();
hl.addStyleName(CSS.NOPADDING);
hl.setCaption(ReflectionHelper.getCaption(field));
if (allFieldContainers != null) allFieldContainers.put(field, hl);
hl.addStyleName(CSS.CLICKABLE);
hl.addLayoutClickListener(e -> {
//if (e.isDoubleClick())
MDDUIAccessor.go(field.getName());
});
addComponent(container, hl, attachedActions.get(field.getName()));
bindResourcesList(binder, hl, field);
addErrorHandler(field, hl);
r = hl;
} else if (false && field.isAnnotationPresent(UseTable.class)) {
VerticalLayout hl = new VerticalLayout();
hl.addStyleName("onetomanytable");
hl.addStyleName(CSS.CLICKABLE);
Label l;
hl.addComponent(l = new Label("", ContentMode.HTML));
hl.addStyleName(CSS.NOPADDING);
hl.addLayoutClickListener(e -> {
//if (e.isDoubleClick())
MDDUIAccessor.go(field.getName());
});
hl.setCaption(ReflectionHelper.getCaption(field));
addComponent(container, hl, attachedActions.get(field.getName()));
bind(binder, l, field);
addErrorHandler(field, l);
r = l;
} else {
Grid g = new Grid();
g.addStyleName("gridonetomany");
g.addStyleName("nooutput");
g.addStyleName("test-" + field.getId() + "-grid");
String colsFilter = "";
if (field.isAnnotationPresent(UseTable.class)) colsFilter = field.getAnnotation(UseTable.class).fields();
if (Strings.isNullOrEmpty(colsFilter) && field.isAnnotationPresent(FieldsFilter.class)) colsFilter = field.getAnnotation(FieldsFilter.class).value();
List colFields = getColumnFields(field, colsFilter);
List editableFields = ReflectionHelper.getAllEditableFields(ReflectionHelper.getGenericClass(field.getGenericType()), field.getDeclaringClass(), false, field);
List originalEditableFields = editableFields;
Class targetClass = field.getGenericClass();
Set subclasses = ReflectionHelper.getSubclasses(targetClass);
addErrorHandler(field, g);
r = g;
boolean inline = false;
if (owned && !field.isAnnotationPresent(UseTable.class)) {
inline = editableFields.size() <= colFields.size() && subclasses.size() == 0 && !field.isAnnotationPresent(NotInlineEditable.class);
inline = false;
if (inline) for (FieldInterfaced f : editableFields) {
if (!isEditableInline(f)) {
inline = false;
break;
}
}
if (inline ) {
g.addStyleName("inline");
boolean needsProxy = false;
for (FieldInterfaced f : editableFields) if (f.isAnnotationPresent(UseCheckboxes.class) && f.getAnnotation(UseCheckboxes.class).editableInline()) {
needsProxy = true;
break;
}
if (false && needsProxy) {
targetClass = ReflectionHelper.getProxy(MDD.getClassPool(), MDDBinder.class, MDD.getClassPool().getClassLoader(), field.isAnnotationPresent(FieldsFilter.class)?field.getAnnotation(FieldsFilter.class).value():null, targetClass, field, object, editableFields);
//si hemos creado una clase proxy, entonces cambian las columnas y los campos editables
if (ProxyClass.class.isAssignableFrom(targetClass)) {
colFields = getColumnFields(field, targetClass);
editableFields = ReflectionHelper.getAllEditableFields(targetClass);
}
inline = editableFields.size() <= colFields.size() && subclasses.size() == 0;
inline = false;
if (inline) for (FieldInterfaced f : colFields) {
if (!isEditableInline(f)) {
inline = false;
break;
}
}
}
}
}
ListViewComponent.buildColumns(null, g, colFields, false, inline, binder, field, field.isAnnotationPresent(FieldsFilter.class)?field.getAnnotation(FieldsFilter.class).value():null);
GridDecorator decorator = null;
try {
Method m = ReflectionHelper.getMethod(targetClass, "getGridDecorator");
if (m != null) {
if (Modifier.isStatic(m.getModifiers())) {
decorator = (GridDecorator) m.invoke(null);
} else {
decorator = (GridDecorator) m.invoke(ReflectionHelper.newInstance(targetClass));
}
} else {
if (GridDecorator.class.isAssignableFrom(targetClass)) {
decorator = (GridDecorator)ReflectionHelper.newInstance(targetClass);
}
}
if (decorator != null) {
decorator.decorateGrid(g);
}
} catch (Exception e) {
Notifier.alert(e);
}
g.setSelectionMode(Grid.SelectionMode.MULTI);
g.setCaption(ReflectionHelper.getCaption(field));
if (inline) {
g.getEditor().getBinder().addValueChangeListener(e -> {
Object bean = binder.getBean();
try {
ReflectionHelper.setValue(field, bean, ReflectionHelper.getValue(field, bean));
binder.setBean(bean);
} catch (Exception ex) {
Notifier.alert(ex);
}
});
}
int ancho = 0;
for (Grid.Column col : (List)g.getColumns()) ancho += col.getWidth();
if (ancho <= 0) ancho = 500;
boolean anchoCompleto = field.isAnnotationPresent(FullWidth.class) || ancho > 900;
anchoCompleto = true;
if (anchoCompleto) g.setWidth("100%");
else {
g.setWidth("" + (ancho + 55) + "px");
}
// añadimos columna para que no haga feo
if (anchoCompleto) {
if (g.getColumns().size() == 1) ((Grid.Column)g.getColumns().get(0)).setExpandRatio(1);
else g.addColumn((d) -> null).setWidthUndefined().setCaption("");
}
g.setHeightMode(HeightMode.UNDEFINED);
HorizontalLayout hl = new HorizontalLayout();
hl.addStyleName("botoneracampo");
Button b;
if (owned) {
//g.setHeightByRows(5);
bind(binder, g, field, targetClass, originalEditableFields, object);
if (field.isAnnotationPresent(ModifyValuesOnly.class) && (attachedActions.get(field.getName()) == null || attachedActions.get(field.getName()).size() == 0)) g.setSelectionMode(Grid.SelectionMode.NONE);
if (inline) {
g.getEditor().setEnabled(true);
g.getEditor().setBuffered(false);
if (!field.isAnnotationPresent(ModifyValuesOnly.class)) {
hl.addComponent(b = new Button(VaadinIcons.PLUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-add");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
ReflectionHelper.addToCollection(field, bean);
binder.setBean(bean, false);
} catch (Exception e1) {
Notifier.alert(e1);
}
});
}
} else {
g.addItemClickListener(e -> {
//if (MDDUIAccessor.isMobile() || e.getMouseEventDetails().isDoubleClick()) {
if (e.getColumn() != null) {
Object i = e.getItem();
if (i != null) {
editar(binder, field, i, e.getRowIndex());
}
}
//}
});
if (!field.isAnnotationPresent(ModifyValuesOnly.class) && ReflectionHelper.puedeAnadir(field)) {
hl.addComponent(b = new Button(VaadinIcons.PLUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-add");
b.addClickListener(e -> {
try {
Constructor con = ReflectionHelper.getConstructor(field.getGenericClass(), binder.getBeanType());
if (con == null) {
con = Arrays.stream(field.getGenericClass().getConstructors()).filter(c -> c.getParameterCount() == 0).findFirst().orElse(null);
}
if (con != null && Modifier.isPublic(con.getModifiers())) {
try {
Collection col;
Object i = Iterables.getLast(col = ReflectionHelper.addToCollection(field, binder.getBean()));
//editar(binder, field, i, col.size() - 1);
binder.setBean(binder.getBean(), false);
} catch (Exception ex) {
Notifier.alert(ex);
}
} else {
con = ReflectionHelper.getConstructor(field.getGenericClass());
if (con != null && con.getParameterCount() > 0) {
VaadinHelper.fill("I need some data", con, i -> {
try {
Collection col = ReflectionHelper.addToCollection(field, binder.getBean(), i);
//editar(binder, field, i, col.size() - 1);
binder.setBean(binder.getBean(), false);
} catch (Exception ex) {
Notifier.alert(ex);
}
}, () -> MDDUIAccessor.goBack());
} else Notifier.alert("No constructor found for " + field.getGenericClass().getSimpleName());
}
} catch (Exception ex) {
Notifier.alert(ex);
}
});
}
}
if (!field.isAnnotationPresent(ModifyValuesOnly.class)) {
if (ReflectionHelper.puedeClonar(field)) {
hl.addComponent(b = new Button(VaadinIcons.COPY));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-clone");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
for (Object o : g.getSelectedItems()) {
if (o instanceof ProxyClass) o = ((ProxyClass) o).toObject();
ReflectionHelper.addToCollection(field, bean, ReflectionHelper.clone(o));
}
binder.setBean(bean, false);
} catch (Exception e1) {
Notifier.alert(e1);
}
});
}
if (ReflectionHelper.puedeBorrar(field)) {
hl.addComponent(b = new Button(VaadinIcons.MINUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-delete");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
Set l = (Set) g.getSelectedItems().stream().map(o -> o != null && o instanceof ProxyClass ? ((ProxyClass) o).toObject() : o).collect(Collectors.toSet());
ReflectionHelper.setValue(field, bean, ReflectionHelper.removeAll((Collection) ReflectionHelper.getValue(field, bean), l));
binder.setBean(bean, false);
} catch (Throwable throwable) {
Notifier.alert(throwable);
}
});
}
if (ReflectionHelper.puedeOrdenar(field)) {
hl.addComponent(b = new Button(VaadinIcons.ARROW_UP));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-up");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
Collection col = (Collection) ReflectionHelper.getValue(field, bean);
if (col != null && col instanceof List) {
List l = new ArrayList(col);
Set sel = new HashSet(g.getSelectedItems());
boolean posible = true;
for (Object o : sel) {
int index = l.indexOf(o);
if (index == 0) {
posible = false;
break;
}
}
if (posible) {
for (Object o : (List) sel.stream().sorted((o1,o2) -> l.indexOf(o1) - l.indexOf(o2)).collect(Collectors.toList())) {
int index = l.indexOf(o);
if (index > 0) {
l.remove(o);
l.add(index - 1, o);
}
}
ReflectionHelper.setValue(field, bean, l);
binder.update(bean);
g.deselectAll();
sel.forEach(i -> g.select(i));
}
}
} catch (Exception e1) {
Notifier.alert(e1);
}
});
hl.addComponent(b = new Button(VaadinIcons.ARROW_DOWN));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-down");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
Collection col = (Collection) ReflectionHelper.getValue(field, bean);
if (col != null && col instanceof List) {
List l = new ArrayList(col);
Set sel = new HashSet(g.getSelectedItems());
boolean posible = true;
for (Object o : sel) {
int index = l.indexOf(o);
if (index == l.size() - 1) {
posible = false;
break;
}
}
if (posible) {
for (Object o : (List) sel.stream().sorted((o1,o2) -> l.indexOf(o2) - l.indexOf(o1)).collect(Collectors.toList())) {
int index = l.indexOf(o);
if (index < l.size() -1) {
l.remove(o);
l.add(index + 1, o);
}
}
ReflectionHelper.setValue(field, bean, l);
binder.update(bean);
g.deselectAll();
sel.forEach(i -> g.select(i));
}
}
} catch (Exception e1) {
Notifier.alert(e1);
}
});
}
}
} else {
DataProvider dpa = (field.isAnnotationPresent(DataProvider.class)) ? field.getAnnotation(DataProvider.class) : null;
boolean seleccion = false;
if (Set.class.isAssignableFrom(field.getType())) seleccion = true;
else if (dpa == null) {
Method mdp = ReflectionHelper.getMethod(field.getDeclaringClass(), ReflectionHelper.getGetter(field.getName()) + "DataProvider");
seleccion = mdp != null;
} else seleccion = true;
if (seleccion) { // queremos seleccionar valores de entre una lista
g.addStyleName("unclickable");
if (MDDUIAccessor.getPendingSelection() != null) {
g.setDataProvider(new ListDataProvider(MDDUIAccessor.getPendingSelection()));
MDDUIAccessor.setPendingSelection(null);
} else {
if (dpa != null) {
try {
g.setDataProvider((com.vaadin.data.provider.DataProvider) ReflectionHelper.newInstance(dpa.dataProvider()));
} catch (Exception e) {
Notifier.alert(e);
}
} else if (Set.class.isAssignableFrom(field.getType())) {
// estamos seleccionando valores que no hayan sido añadidos
try {
com.vaadin.data.provider.DataProvider dp = null;
FieldInterfaced mbf = ReflectionHelper.getMapper(field);
if (mbf != null && mbf.isAnnotationPresent(ManyToOne.class)) {
dp = new JPQLListDataProvider("select x from " + targetClass.getName() + " x where x." + mbf.getName() + " = null order by x." + ReflectionHelper.getIdField(targetClass).getName() + " asc");
} else {
dp = new JPQLListDataProvider(targetClass);
}
g.setDataProvider(dp);
} catch (Throwable throwable) {
Notifier.alert(throwable);
}
} else {
JPAManyToOneFieldBuilder.setDataProvider(g, field, binder);
}
}
bindSelection(binder, g, field);
} else {
bind(binder, g, field, targetClass, null);
{
g.addItemClickListener(e -> {
//if (MDDUIAccessor.isMobile() || e.getMouseEventDetails().isDoubleClick()) {
Object i = e.getItem();
if (i != null) {
MDDUIAccessor.go(field.getName());
}
//}
});
hl.addComponent(b = new Button(VaadinIcons.PLUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addClickListener(e -> MDDUIAccessor.go(field.getName()));
hl.addComponent(b = new Button(VaadinIcons.MINUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
Set l = g.getSelectedItems();
ReflectionHelper.setValue(field, bean, ReflectionHelper.removeAll((Collection) ReflectionHelper.getValue(field, bean), l));
binder.setBean(bean, false);
} catch (Throwable throwable) {
Notifier.alert(throwable);
}
});
}
}
}
if (hl.getComponentCount() > 0) {
VerticalLayout vl;
addComponent(container, vl = new VerticalLayout(g, hl), attachedActions.get(field.getName()));
vl.addStyleName(CSS.NOPADDING);
vl.addStyleName("contenedorbotoneracampo");
vl.addStyleName("conbotonera");
if (allFieldContainers != null) allFieldContainers.put(field, vl);
} else {
addComponent(container, g, attachedActions.get(field.getName()));
if (allFieldContainers != null) allFieldContainers.put(field, g);
}
}
return r;
}
private static void editar(MDDBinder binder, FieldInterfaced field, Object i, int indice) {
String state = MateuUI.get().getStack().getState(MateuUI.get().getStack().getLast());
if (!state.endsWith("/")) state += "/";
state += field.getName();
try {
//todo: ver como resolvemso esto de una manera más elegante
MDDUIAccessor.setPendingResult(indice);
MDDUIAccessor.goTo(state);
} catch (Exception e1) {
e1.printStackTrace();
}
}
//set
public static void bindSet(MDDBinder binder, Label l, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
Object v;
@Override
public void setValue(Object o) {
v = o;
try {
Collection elems = (Collection) o;
String s = "";
if (o == null || elems.size() == 0) s = "No item";
else {
for (Object x : elems) {
if (!"".equalsIgnoreCase(s)) s += ", ";
s += x;
}
}
l.setValue(s);
} catch (Throwable e) {
Notifier.alert(e);
}
}
@Override
public Object getValue() {
return v;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
aux.bind(field.getName());
}
//usetable
public static void bind(MDDBinder binder, Label l, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
Object v;
@Override
public void setValue(Object o) {
v = o;
try {
Collection elems = (Collection) o;
StringWriter sw;
PrintWriter pw = new PrintWriter(sw = new StringWriter());
String colsFilter = "";
if (field.isAnnotationPresent(UseTable.class)) colsFilter = field.getAnnotation(UseTable.class).fields();
List cols = getColumnFields(field, colsFilter);
pw.println("");
pw.println("");
cols.forEach(col -> pw.println("" + Helper.capitalize(col.getName()) + " "));
pw.println(" ");
pw.println("");
if (o == null || ((Collection)o).size() == 0) {
pw.println("----- Empty list ----- ");
} else {
for (Object e : elems) {
pw.println("");
for (FieldInterfaced col : cols) {
boolean num = false;
if (int.class.equals(col.getType()) || Integer.class.equals(col.getType())) {
num = true;
} else if (long.class.equals(col.getType()) || Long.class.equals(col.getType())) {
num = true;
} else if (double.class.equals(col.getType()) || Double.class.equals(col.getType())) {
num = true;
}
Object v = ReflectionHelper.getValue(col, e);
if (v != null) {
if (col.isAnnotationPresent(WeekDays.class)) {
boolean[] wds = (boolean[]) v;
String s = "";
for (int i = 0; i < wds.length; i++) s += wds[i]?"|":"-";
v = s;
}
}
pw.println("" + (v != null?v:"---") + " ");
}
pw.println(" ");
};
}
pw.println(" ");
pw.println("");
cols.forEach(col -> {
boolean num = false;
String s = "";
if (int.class.equals(col.getType()) || Integer.class.equals(col.getType())) {
int t = 0;
if (elems != null) for (Object elem : elems) {
try {
Object w = ReflectionHelper.getValue(col, elem);
t += (Integer) w;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
s += t;
num = true;
} else if (long.class.equals(col.getType()) || Long.class.equals(col.getType())) {
long t = 0;
if (elems != null) for (Object elem : elems) {
try {
Object w = ReflectionHelper.getValue(col, elem);
t += (Long) w;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
s += t;
num = true;
} else if (double.class.equals(col.getType()) || Double.class.equals(col.getType())) {
double t = 0;
if (elems != null) for (Object elem : elems) {
try {
Object w = ReflectionHelper.getValue(col, elem);
if (w != null) t += (Double) w;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
if (col.isAnnotationPresent(Money.class)) {
DecimalFormat df = new DecimalFormat("##,###,###,###,##0.00");
s = df.format(t);
} else {
s += t;
}
num = true;
}
pw.println("" + s + " ");
});
pw.println(" ");
pw.println("
");
l.setValue(sw.toString());
} catch (Throwable e) {
Notifier.alert(e);
}
}
@Override
public Object getValue() {
return v;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
aux.bind(field.getName());
}
private boolean isEditableInline(FieldInterfaced f) {
boolean editable = false;
if (true || !f.isAnnotationPresent(NotNull.class) && !f.isAnnotationPresent(NotEmpty.class)) {
if (Boolean.class.equals(f.getType()) || boolean.class.equals(f.getType())) {
editable = true;
} else if (String.class.equals(f.getType())) {
editable = true;
} else if (Integer.class.equals(f.getType()) || int.class.equals(f.getType())) {
editable = true;
} else if (Long.class.equals(f.getType()) || long.class.equals(f.getType())) {
editable = true;
} else if (Double.class.equals(f.getType()) || double.class.equals(f.getType())) {
editable = true;
} else if (LocalDate.class.equals(f.getType()) || LocalDateTime.class.equals(f.getType())) {
editable = true;
} else if (LocalTime.class.equals(f.getType()) || LocalTime.class.equals(f.getType())) {
editable = true;
} else if (f.getType().isEnum()) {
editable = true;
} else if (f.isAnnotationPresent(ManyToOne.class)) {
editable = !IResource.class.isAssignableFrom(f.getType());
} else if (f.isAnnotationPresent(UseCheckboxes.class)) {
editable = f.getAnnotation(UseCheckboxes.class).editableInline();
} else if (f.isAnnotationPresent(WeekDays.class)) {
editable = true;
} else if (FareValue.class.equals(f.getType())) {
editable = true;
}
}
return editable;
}
private Component buildMap(VerticalLayout fieldGroup, HorizontalLayout fieldGroupHeader, FieldInterfaced field, Object object, Layout container, MDDBinder binder, Map> validators, AbstractStylist stylist, Map allFieldContainers, boolean forSearchFilter, boolean owned, Map> attachedActions) {
Class keyType = ReflectionHelper.getGenericClass(field, Map.class, "K");
Class valueType = ReflectionHelper.getGenericClass(field, Map.class, "V");
Grid g = new Grid();
g.addStyleName("gridonetomany");
g.addStyleName("nooutput");
g.addStyleName("test-" + field.getId() + "-grid");
ListViewComponent.buildColumns(g, getColumnFields(field), false, false);
int ancho = 0;
for (Grid.Column col : (List)g.getColumns()) ancho += col.getWidth();
if (ancho <= 0) ancho = 500;
boolean anchoCompleto = field.isAnnotationPresent(FullWidth.class) || ancho > 900;
anchoCompleto = false;
if (anchoCompleto) g.setWidth("100%");
else {
g.setWidth("" + (ancho + 50) + "px");
}
// añadimos columna para que no haga feo
if (anchoCompleto) {
if (g.getColumns().size() == 1) ((Grid.Column)g.getColumns().get(0)).setExpandRatio(1);
else g.addColumn((d) -> null).setWidthUndefined().setCaption("");
}
g.setHeightMode(HeightMode.UNDEFINED);
g.setSelectionMode(Grid.SelectionMode.MULTI);
g.setCaption(ReflectionHelper.getCaption(field));
VerticalLayout vl = new VerticalLayout();
vl.addStyleName(CSS.NOPADDING);
vl.addStyleName("test-" + field.getId());
vl.addComponent(g);
bindMap(binder, g, field);
Layout lx = new VerticalLayout();
lx.addStyleName(CSS.NOPADDING);
List auxFields = new ArrayList<>();
auxFields.add(new FieldInterfacedFromType(ReflectionHelper.getGenericClass((ParameterizedType) field.getGenericType(), Map.class, "K"), "key"));
auxFields.add(new FieldInterfacedFromType(ReflectionHelper.getGenericClass((ParameterizedType) field.getGenericType(), Map.class, "V"), "value"));
MDDBinder auxbinder = new MDDBinder(auxFields);
Map m = new HashMap<>();
auxbinder.setBean(m);
Layout finalHl = lx;
auxFields.forEach(f -> {
AbstractFieldBuilder b = (AbstractFieldBuilder) MDDUIAccessor.getFieldBuilder(f);
if (b != null) b.build(fieldGroup, fieldGroupHeader, f, m, finalHl, auxbinder, null, null, null, false, attachedActions);
});
vl.addComponent(lx);
HorizontalLayout hl = new HorizontalLayout();
Button b;
g.setHeightMode(HeightMode.UNDEFINED);
g.addItemClickListener(e -> {
MapEntry value = (MapEntry) e.getItem();
try {
Map aux = (Map) auxbinder.getBean();
aux.put("key", value.getKey());
aux.put("value", value.getValue());
auxbinder.update(aux);
} catch (Exception ex) {
Notifier.alert(ex);
}
});
hl.addComponent(b = new Button("Put", VaadinIcons.PLUS));
b.addStyleName("test-" + field.getId() + "-put");
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addClickListener(e -> {
Object bean = binder.getBean();
Map aux = (Map) auxbinder.getBean();
Object k = aux.get("key");
Object v = aux.get("value");
try {
if (k != null) {
ReflectionHelper.addToMap(field, bean, k, v);
binder.setBean(bean, false);
}
} catch (Exception e1) {
Notifier.alert(e1);
}
});
hl.addComponent(b = new Button("Remove selected lines", VaadinIcons.MINUS));
b.addStyleName(ValoTheme.BUTTON_QUIET);
b.addStyleName(ValoTheme.BUTTON_TINY);
b.addStyleName("test-" + field.getId() + "-remove");
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
Set l = g.getSelectedItems();
ReflectionHelper.removeFromMap(field, bean, l);
binder.setBean(bean, false);
} catch (Exception e1) {
Notifier.alert(e1);
}
});
vl.addComponent(hl);
container.addComponent(vl);
addErrorHandler(field, g);
if (allFieldContainers != null) allFieldContainers.put(field, vl);
return g;
}
private void bind(MDDBinder binder, CheckBoxGroup g, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
private List listeners = new ArrayList<>();
@Override
public void setValue(Object o) {
Set items = null;
if (o == null) {
items = new HashSet();
} else {
if (o instanceof Set) {
items = (Set) o;
} else if (o instanceof List) {
items = new HashSet(((List)o));
}
}
try {
ReflectionHelper.setValue(field, binder.getBean(), items);
} catch (Exception e) {
Notifier.alert(e);
}
g.setValue(items);
//listeners.forEach(l -> l.valueChange(new ValueChangeEvent(g, null, true)));
}
@Override
public Object getValue() {
return g.getValue() != null?new HashSet<>(g.getValue()):null;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
listeners.add(valueChangeListener);
return new Registration() {
@Override
public void remove() {
listeners.remove(valueChangeListener);
}
};
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
aux.bind(field.getName());
}
private void bindMap(MDDBinder binder, Grid g, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
@Override
public void setValue(Object o) {
Collection items = null;
if (o == null) {
items = new ArrayList();
} else {
if (o instanceof Map) {
Class keyType = ReflectionHelper.getGenericClass(field, Map.class, "K");
if (keyType != null && keyType.isEnum()) {
//todo: prefill
//todo: añadir anotación @Prefill
}
items = ((Map) o).entrySet();
} else {
items = (Collection) o;
}
}
g.setDataProvider(new ListDataProvider(items));
}
@Override
public Object getValue() {
return ((ListDataProvider) g.getDataProvider()).getItems();
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
if (Map.class.isAssignableFrom(field.getType())) {
aux.withConverter(new Converter() {
@Override
public Result convertToModel(Object o, ValueContext valueContext) {
Map m = new HashMap();
if (o != null) {
((Collection)o).forEach(e -> m.put(((MapEntry)e).getKey(), ((MapEntry)e).getValue()));
}
return Result.ok((o != null)?m:null);
}
@Override
public Object convertToPresentation(Object o, ValueContext valueContext) {
return (o != null)?toList((Map) o):null;
}
});
}
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
aux.bind(field.getName());
}
private void updateReferences(MDDBinder binder, FieldInterfaced field, HasValue.ValueChangeEvent> e) {
Object bean = binder.getBean();
}
private Object toId(Object row) {
return ReflectionHelper.getId(row);
}
public static List getColumnFields(FieldInterfaced field, String filter) {
List l;
if (Strings.isNullOrEmpty(filter)) {
l = getColumnFields(field);
} else {
l = new ArrayList<>();
List aux = ReflectionHelper.getAllFields(field.getGenericClass());
String limpio = "";
for (String s : filter.split(",")) {
String n = s.trim();
if (n.contains("(")) n = n.substring(0, n.indexOf("("));
if (n.contains(" ")) n = n.substring(0, n.indexOf(" "));
if (!"".equals(limpio)) limpio += ",";
limpio += n;
}
List fns = Arrays.asList(limpio.replaceAll(" ", "").split(","));
for (String fn : fns) {
if (fn.contains(".")) {
l.add(new FieldInterfacedFromPath(field.getGenericClass(), fn));
} else {
List finalL = l;
aux.stream().filter(f -> fn.equals(f.getName())).findFirst().ifPresent(f -> finalL.add(f));
}
}
}
return l;
}
public static List getColumnFields(FieldInterfaced field) {
List l = null;
if (Map.class.isAssignableFrom(field.getType())) {
l = new ArrayList<>();
l.add(new FieldInterfacedFromType(ReflectionHelper.getGenericClass(field, Map.class, "K"), "key"));
l.add(new FieldInterfacedFromType(ReflectionHelper.getGenericClass(field, Map.class, "V"), "value"));
} else {
l = getColumnFields(field, field.getGenericClass());
}
return l;
}
public static List getColumnFields(FieldInterfaced field, Class rowType) {
List l = null;
l = ListViewComponent.getColumnFields(rowType, true, field.isAnnotationPresent(FieldsFilter.class)?field.getAnnotation(FieldsFilter.class).value():null, new ArrayList<>(), new HashMap<>());
// quitamos el campo mappedBy de las columnas, ya que se supone que siempre seremos nosotros
OneToMany aa;
if ((aa = field.getAnnotation(OneToMany.class)) != null) {
String mb = field.getAnnotation(OneToMany.class).mappedBy();
if (!Strings.isNullOrEmpty(mb)) {
FieldInterfaced mbf = null;
for (FieldInterfaced f : l) {
if (f.getName().equals(mb)) {
mbf = f;
break;
}
}
if (mbf != null) l.remove(mbf);
}
}
if (field.isAnnotationPresent(FieldsFilter.class)) {
List fns = Arrays.asList(field.getAnnotation(FieldsFilter.class).value().split(","));
fns = fns.stream().map(s -> s.trim()).collect(Collectors.toList());
List borrar = new ArrayList<>();
for (FieldInterfaced f : l) {
if (!fns.contains(f.getName())) {
borrar.add(f);
}
}
l.removeAll(borrar);
}
return l;
}
public Object convert(String s) {
return s;
}
public void addValidators(List validators) {
}
/*
private void bind(MDDBinder binder, CheckBoxGroup cbg, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(cbg);
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
aux.bind(field.getName());
}
*/
private void bindSelection(MDDBinder binder, Grid g, FieldInterfaced field) {
HasValue hv;
Binder.BindingBuilder aux = binder.forField(hv = new HasValue() {
List valueChangeListeners = new ArrayList<>();
{
g.getSelectionModel().addSelectionListener(e -> {
ValueChangeEvent vce = new ValueChangeEvent(g, this, null, e.isUserOriginated());
valueChangeListeners.forEach(l -> l.valueChange(vce));
});
}
@Override
public void setValue(Object o) {
g.deselectAll();
if (o != null) {
if (o instanceof Collection) ((Collection)o).forEach(i -> g.select(i));
else g.select(o);
}
}
@Override
public Object getValue() {
return g.getSelectedItems();
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
valueChangeListeners.add(valueChangeListener);
return new Registration() {
@Override
public void remove() {
valueChangeListeners.remove(valueChangeListener);
}
};
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
Binder.Binding b = aux.bind(field.getName());
hv.addValueChangeListener(e -> updateReferences(binder, field, e));
if (Set.class.isAssignableFrom(field.getType())) {
try {
ReflectionHelper.setValue(field, binder.getBean(), new HashSet<>());
} catch (Exception e) {
Notifier.alert(e);
}
}
}
private void bind(MDDBinder binder, CssLayout l, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
Object value;
@Override
public void setValue(Object o) {
value = o;
Button b = (Button) l.getComponent(l.getComponentCount() - 1);
l.removeAllComponents();
if (o == null || ((Collection)o).size() == 0) l.addComponent(new Label("Empty list"));
else {
for (Object x : (Collection)o) l.addComponent(createChip(binder, field, x));
}
l.addComponent(b);
}
@Override
public Object getValue() {
return value;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
completeBinding(aux, binder, field);
}
private Component createChip(MDDBinder binder, FieldInterfaced field, Object x) {
HorizontalLayout hl = new HorizontalLayout();
hl.addStyleName("chip");
Label l;
hl.addComponent(l = new Label(x.toString()));
Button b;
hl.addComponent(b = new Button(null, VaadinIcons.CLOSE_SMALL));
b.addClickListener(e -> {
try {
Object bean = binder.getBean();
ReflectionHelper.setValue(field, bean, ReflectionHelper.removeAll((Collection) ReflectionHelper.getValue(field, bean), Sets.newHashSet(x)));
binder.setBean(bean, false);
} catch (Throwable throwable) {
Notifier.alert(throwable);
}
});
return hl;
}
private void bindResourcesList(MDDBinder binder, Layout l, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
private Object v;
@Override
public void setValue(Object o) {
v = o;
l.removeAllComponents();
if (o == null || ((Collection)o).size() == 0) {
Label label;
l.addComponent(label = new Label(VaadinIcons.PLUS.getHtml()));
label.setContentMode(ContentMode.HTML);
label.addStyleName("fileicon");
}
else {
try {
for (Object i : (Collection)o) {
IResource file = (IResource) i;
boolean empty = true;
if (file != null && file.getName () != null) {
String u = file.toFileLocator().getUrl();
if (!Strings.isNullOrEmpty(u)) {
if (file.getName().toLowerCase().endsWith(".jpg")
|| file.getName().toLowerCase().endsWith(".jpeg")
|| file.getName().toLowerCase().endsWith(".gif")
|| file.getName().toLowerCase().endsWith(".png")
|| file.getName().toLowerCase().endsWith(".svg")
|| file.getName().toLowerCase().endsWith(".webp")) {
Image image = new Image();
image.setWidth("130px");
image.setSource(!Strings.isNullOrEmpty(u)?new ExternalResource(u):new ClassResource("/images/noimage.png"));
l.addComponent(image);
} else {
Label label;
l.addComponent(label = new Label(VaadinIcons.FILE.getHtml()));
label.setContentMode(ContentMode.HTML);
label.addStyleName("fileicon");
}
empty = false;
}
}
if (empty) {
Image image = new Image();
image.setWidth("130px");
image.setSource(new ClassResource("/images/noimage.png"));
l.addComponent(image);
}
}
} catch (Exception e) {
Notifier.alert(e);
}
}
}
@Override
public Object getValue() {
return v;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
completeBinding(aux, binder, field);
}
static void bind(MDDBinder binder, CssLayout l, FieldInterfaced field, Method htmlGetter) {
bind(binder, l, field, htmlGetter, false);
}
static void bind(MDDBinder binder, CssLayout l, FieldInterfaced field, Method htmlGetter, boolean output) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
private Object v;
@Override
public void setValue(Object o) {
v = o;
l.removeAllComponents();
if (o == null || ((Collection)o).size() == 0) {
HorizontalLayout clickable;
l.addComponent(clickable = new HorizontalLayout(new Label("Empty list")));
clickable.addStyleName(CSS.NOPADDING);
if (!output) {
clickable.addStyleName(CSS.CLICKABLE);
clickable.addLayoutClickListener(e -> {
//if (e.isDoubleClick())
MDDUIAccessor.go(field.getName());
});
}
} else {
int pos = 0;
for (Object i : ((Collection) o)) {
HorizontalLayout clickable;
Label lab;
l.addComponent(clickable = new HorizontalLayout(lab = new Label(((Card)i).toHtml(), ContentMode.HTML)));
clickable.addStyleName("carditem");
if (!output) {
clickable.addStyleName(CSS.CLICKABLE);
int finalPos = pos;
clickable.addLayoutClickListener(e -> {
//if (e.isDoubleClick()) {
if (i != null) {
editar(binder, field, i, finalPos);
}
//}
});
if (ReflectionHelper.puedeOrdenar(field)) {
DragSourceExtension dragSource = new DragSourceExtension<>(clickable);
// set the allowed effect
dragSource.setEffectAllowed(EffectAllowed.MOVE);
// set the text to transfer
dragSource.setDataTransferText("hello receiver");
// set other data to transfer (in this case HTML)
dragSource.setDataTransferData("text/html", "hello receiver ");
dragSource.addDragStartListener(event ->
dragSource.setDragData(i)
);
dragSource.addDragEndListener(event ->
dragSource.setDragData(null)
);
clickable.setPrimaryStyleName("zonadrop");
// make the layout accept drops
DropTargetExtension dropTarget = new DropTargetExtension<>(clickable);
// the drop effect must match the allowed effect in the drag source for a successful drop
dropTarget.setDropEffect(DropEffect.MOVE);
// catch the drops
dropTarget.addDropListener(event -> {
// if the drag source is in the same UI as the target
Optional dragSourcex = event.getDragSourceComponent();
if (dragSourcex.isPresent() && dragSourcex.get() instanceof HorizontalLayout) {
/*
// move the label to the layout
clickable.addComponent(dragSourcex.get());
// get possible transfer data
String message = event.getDataTransferData("text/html");
if (message != null) {
Notification.show("DropEvent with data transfer html: " + message);
} else {
// get transfer text
message = event.getDataTransferText();
Notification.show("DropEvent with data transfer text: " + message);
}
*/
// handle possible server side drag data, if the drag source was in the same UI
event.getDragData().ifPresent(data -> {
log.info("recibido: " + data);
if (!i.equals(data)) {
Object bean = binder.getBean();
try {
List l = new ArrayList((Collection) ReflectionHelper.getValue(field, bean));
l.remove(data);
l.add(l.indexOf(i), data);
ReflectionHelper.setValue(field, bean, l);
binder.update(bean);
} catch (Exception e) {
Notifier.alert(e);
}
}
});
}
});
}
}
pos++;
}
if (!output && ReflectionHelper.puedeOrdenar(field)) {
HorizontalLayout clickable;
Label lab;
l.addComponent(clickable = new HorizontalLayout(lab = new Label("
", ContentMode.HTML)));
clickable.setPrimaryStyleName("zonadrop");
// make the layout accept drops
DropTargetExtension dropTarget = new DropTargetExtension<>(clickable);
// the drop effect must match the allowed effect in the drag source for a successful drop
dropTarget.setDropEffect(DropEffect.MOVE);
// catch the drops
dropTarget.addDropListener(event -> {
// if the drag source is in the same UI as the target
Optional dragSourcex = event.getDragSourceComponent();
if (dragSourcex.isPresent() && dragSourcex.get() instanceof HorizontalLayout) {
// handle possible server side drag data, if the drag source was in the same UI
event.getDragData().ifPresent(data -> {
log.info("recibido: " + data);
Object bean = binder.getBean();
try {
List l = new ArrayList((Collection) ReflectionHelper.getValue(field, bean));
l.remove(data);
l.add(data);
ReflectionHelper.setValue(field, bean, l);
binder.update(bean);
} catch (Exception e) {
Notifier.alert(e);
}
});
}
});
}
}
}
@Override
public Object getValue() {
return v;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
completeBinding(aux, binder, field);
}
static void bind(MDDBinder binder, Label l, FieldInterfaced field, Method htmlGetter) {
Binder.BindingBuilder aux = binder.forField(new HasValue() {
private Object v;
@Override
public void setValue(Object o) {
v = o;
if (o == null || ((Collection)o).size() == 0) l.setValue("Empty list");
else {
try {
l.setValue(htmlGetter != null? (String) htmlGetter.invoke(binder.getBean()) :"" + ((Collection)o).size() + " items");
} catch (Exception e) {
Notifier.alert(e);
}
}
}
@Override
public Object getValue() {
return v;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
});
aux.withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
completeBinding(aux, binder, field);
}
public static void bind(MDDBinder binder, Grid g, FieldInterfaced field, Class targetClass, List originalEditableFields) {
bind(binder, g, field, targetClass, originalEditableFields, null);
}
public static void bind(MDDBinder binder, Grid g, FieldInterfaced field, Class targetClass, List originalEditableFields, Object owner) {
if (ProxyClass.class.isAssignableFrom(targetClass)) {
HasValue hv = new HasValue() {
private Object v;
@Override
public void setValue(Object o) {
v = o;
Collection items = null;
if (o == null) {
items = new ArrayList();
} else {
if (o instanceof Map) {
items = new ArrayList();
Class keyType = ReflectionHelper.getGenericClass(field, Map.class, "K");
if (keyType != null && keyType.isEnum()) {
//todo: prefill
//todo: añadir anotación @Prefill
}
items = ((Map) o).entrySet();
} else {
items = new ArrayList();
Map valoresPosiblesPorCampo = new HashMap<>();
for (FieldInterfaced f : originalEditableFields) {
if (f.isAnnotationPresent(UseCheckboxes.class) && f.getAnnotation(UseCheckboxes.class).editableInline()) {
Collection possibleValues = null;
String vmn = ReflectionHelper.getGetter(field.getName() + ReflectionHelper.getFirstUpper(f.getName())) + "Values";
Method mdp = ReflectionHelper.getMethod(field.getDeclaringClass(), vmn);
if (mdp != null) {
try {
possibleValues = (Collection) mdp.invoke(owner);
} catch (Exception e) {
Notifier.alert(e);
}
} else {
Notifier.alert("Missing " + vmn + " method at " + field.getDeclaringClass().getName());
}
int pos = 0;
if (possibleValues != null) {
Map l = valoresPosiblesPorCampo.get(f.getName());
if (l == null) valoresPosiblesPorCampo.put(f.getName(), l = new HashMap());
for (Object v : possibleValues)
if (v != null) {
l.put(pos, v);
pos++;
}
}
}
}
for (Object x : (Collection) o) {
//binder.getMergeables().add(x);
try {
items.add(targetClass.getConstructor(x.getClass(), Map.class, MDDBinder.class).newInstance(x, valoresPosiblesPorCampo, binder));
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
g.setDataProvider(new ListDataProvider(items));
}
@Override
public Object getValue() {
Collection items = new ArrayList();
for (Object o : ((ListDataProvider) g.getDataProvider()).getItems()) {
((ArrayList) items).add(((ProxyClass) o).toObject());
}
return items;
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
};
completeBinding(hv, binder, field);
} else {
HasValue hv = new HasValue() {
private Object v;
@Override
public void setValue(Object o) {
v = o;
Collection items = null;
if (o == null) {
items = new ArrayList();
} else {
if (o instanceof Map) {
Class keyType = ReflectionHelper.getGenericClass(field, Map.class, "K");
if (keyType != null && keyType.isEnum()) {
//todo: prefill
//todo: añadir anotación @Prefill
}
items = ((Map) o).entrySet();
} else {
items = (Collection) o;
}
}
g.setDataProvider(new ListDataProvider(items));
}
@Override
public Object getValue() {
return ((ListDataProvider) g.getDataProvider()).getItems();
}
@Override
public Registration addValueChangeListener(ValueChangeListener valueChangeListener) {
return null;
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
}
@Override
public boolean isRequiredIndicatorVisible() {
return false;
}
@Override
public void setReadOnly(boolean b) {
}
@Override
public boolean isReadOnly() {
return false;
}
};
completeBinding(hv, binder, field);
}
}
private static List toList(Map m) {
List l = new ArrayList<>();
if (m != null) m.entrySet().forEach(e -> l.add(new MapEntry(((Map.Entry)e).getKey(), ((Map.Entry)e).getValue())));
return (m != null)?l:null;
}
protected void bind(MDDBinder binder, TwinColSelect tf, FieldInterfaced field) {
Binder.BindingBuilder aux = binder.forField(tf).withValidator(new BeanValidator(field.getDeclaringClass(), field.getName()));
completeBinding(aux, binder, field);
}
}