package fr.openwide.core.basicapp.web.application.history.column; import java.util.Collection; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.model.IModel; import org.apache.wicket.model.ResourceModel; import org.bindgen.BindingRoot; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import fr.openwide.core.basicapp.core.business.history.model.HistoryDifference; import fr.openwide.core.basicapp.core.business.history.model.HistoryLog; import fr.openwide.core.basicapp.core.util.binding.Bindings; import fr.openwide.core.basicapp.web.application.history.component.DefaultHistoryDifferencePanel; import fr.openwide.core.basicapp.web.application.history.component.HistoryLogDetailColumnPanel; import fr.openwide.core.basicapp.web.application.history.component.factory.CustomizableHistoryComponentFactory; import fr.openwide.core.basicapp.web.application.history.component.factory.IHistoryComponentFactory; import fr.openwide.core.commons.util.fieldpath.FieldPath; import fr.openwide.core.jpa.business.generic.model.GenericEntityReference; import fr.openwide.core.jpa.more.business.history.search.HistoryLogSort; import fr.openwide.core.wicket.more.markup.repeater.table.column.AbstractCoreColumn; /** * A customizable column that displays the detail (event type, differences) of an {@link HistoryLog}. * <p>This columns uses a {@link IHistoryComponentFactory} in order to create one component for each difference on * a given {@link HistoryLog}. * <p>Callers may restrict the displayed differences to a given list of fields, using the * {@link #showOnly(BindingRoot)}, {@link #showOnly(Class, FieldPath)} and {@link #showOnlyItem(BindingRoot)} methods. * In this case, only the differences on the given fields will be displayed. * <p>Callers may customize the way differences are displayed by using a {@link CustomizableHistoryComponentFactory}, or * even by providing their own {@link IHistoryComponentFactory}. */ public class HistoryLogDetailColumn extends AbstractCoreColumn<HistoryLog, HistoryLogSort> { private static final long serialVersionUID = 1L; private final IHistoryComponentFactory historyComponentFactory; private final Multimap<Class<?>, FieldPath> fieldsWhiteList = HashMultimap.create(); public HistoryLogDetailColumn() { this(DefaultHistoryDifferencePanel.factory()); } public HistoryLogDetailColumn(IHistoryComponentFactory historyComponentFactory) { super(new ResourceModel("business.history.detail")); this.historyComponentFactory = historyComponentFactory; } public HistoryLogDetailColumn showOnly(Class<?> clazz, FieldPath path) { fieldsWhiteList.put(clazz, path); return this; } public HistoryLogDetailColumn showOnly(BindingRoot<?, ?> binding) { return showOnly(binding.getRootBinding().getType(), FieldPath.fromBinding(binding)); } /** * To be used when the elements to be displayed don't refer to the collection field itself, but to <em>items</em> * of this collection. * <p>This is most likely what you want to do when dealing with collections, since the differences will generally * be computed on an item-by-item basis, and not on the collection as a whole. */ public HistoryLogDetailColumn showOnlyItem(BindingRoot<?, ?> binding) { return showOnly(binding.getRootBinding().getType(), FieldPath.fromBinding(binding).item()); } @Override public void populateItem(Item<ICellPopulator<HistoryLog>> cellItem, String componentId, IModel<HistoryLog> rowModel) { Predicate<HistoryDifference> filter = null; if (!fieldsWhiteList.isEmpty()) { GenericEntityReference<?, ?> mainObjectEntityReference = rowModel.getObject().getMainObject().getReference(); if (mainObjectEntityReference != null) { Collection<FieldPath> whiteList = fieldsWhiteList.get(mainObjectEntityReference.getType()); // com.google.common.collect.AbstractMapBasedMultimap$WrappedSet is not serializable... whiteList = Sets.newHashSet(fieldsWhiteList.get(mainObjectEntityReference.getType())); filter = Predicates.compose(Predicates.in(whiteList), Bindings.historyDifference().path().path()); } } cellItem.add(new HistoryLogDetailColumnPanel(componentId, rowModel, historyComponentFactory, filter)); } @Override public void detach() { super.detach(); historyComponentFactory.detach(); } }