package com.constellio.app.ui.framework.components.table;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableFooterEvent;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableHeaderEvent;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableRowEvent;
import com.constellio.app.modules.rm.wrappers.DecommissioningList;
import com.constellio.app.ui.application.ConstellioUI;
import com.constellio.app.ui.entities.MetadataSchemaVO;
import com.constellio.app.ui.entities.MetadataVO;
import com.constellio.app.ui.entities.MetadataValueVO;
import com.constellio.app.ui.entities.RecordVO;
import com.constellio.app.ui.framework.components.MetadataDisplayFactory;
import com.constellio.app.ui.framework.components.contextmenu.BaseContextMenuTableListener;
import com.constellio.app.ui.framework.components.contextmenu.RecordContextMenu;
import com.constellio.app.ui.framework.components.contextmenu.RecordContextMenuHandler;
import com.constellio.app.ui.framework.components.menuBar.RecordMenuBarHandler;
import com.constellio.app.ui.framework.components.table.columns.RecordVOTableColumnsManager;
import com.constellio.app.ui.framework.components.table.columns.TableColumnsManager;
import com.constellio.app.ui.framework.containers.ContainerAdapter;
import com.constellio.app.ui.framework.containers.RecordVOLazyContainer;
import com.constellio.app.ui.framework.data.RecordVODataProvider;
import com.constellio.app.ui.framework.items.RecordVOItem;
import com.constellio.app.ui.util.FileIconUtils;
import com.constellio.app.ui.util.SchemaCaptionUtils;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.schemas.builders.CommonMetadataBuilder;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.shared.MouseEventDetails.MouseButton;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.Table;
public class RecordVOTable extends BaseTable {
public static final String STYLE_NAME = "record-table";
public static final String CLICKABLE_ROW_STYLE_NAME = "clickable-row";
public static final String MENUBAR_PROPERTY_ID = "menuBar";
private RecordContextMenu contextMenu;
private List<MetadataSchemaVO> schemaVOs = new ArrayList<>();
private MetadataDisplayFactory metadataDisplayFactory = new MetadataDisplayFactory();
public RecordVOTable() {
super(null);
init();
}
public RecordVOTable(Container dataSource) {
this(null, dataSource);
}
public RecordVOTable(String caption, Container dataSource) {
this(caption, dataSource, false);
}
public RecordVOTable(String caption) {
super(null, caption);
init();
}
public RecordVOTable(RecordVODataProvider dataProvider) {
super(null);
setContainerDataSource(new RecordVOLazyContainer(dataProvider));
init();
}
public RecordVOTable(String caption, Container dataSource, Boolean collapsingAllowed) {
super(null, caption);
setContainerDataSource(dataSource);
init();
setColumnCollapsingAllowed(collapsingAllowed);
}
@Override
protected String getTableId() {
String tableId;
if (!schemaVOs.isEmpty()) {
StringBuilder schemaVOSuffix = new StringBuilder();
for (MetadataSchemaVO schemaVO : schemaVOs) {
if (schemaVOSuffix.length() > 0) {
schemaVOSuffix.append("_");
}
schemaVOSuffix.append(schemaVO.getCode());
}
String componentId = getId();
String navigatorState = ConstellioUI.getCurrent().getNavigator().getState();
String navigatorStateWithoutParams;
if (navigatorState.indexOf("/") != -1) {
navigatorStateWithoutParams = StringUtils.substringBefore(navigatorState, "/");
} else {
navigatorStateWithoutParams = navigatorState;
}
tableId = navigatorStateWithoutParams + "." + schemaVOSuffix;
if (componentId != null) {
tableId += "." + componentId;
}
} else {
tableId = null;
}
return tableId;
}
@Override
protected TableColumnsManager newColumnsManager() {
return new RecordVOTableColumnsManager();
}
private void init() {
addStyleName(STYLE_NAME);
setCellStyleGenerator(new CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
String columnStyle;
if (isTitleColumn(propertyId)) {
RecordVO recordVO = getRecordVOForTitleColumn(getItem(itemId));
columnStyle = getTitleColumnStyle(recordVO);
} else {
columnStyle = null;
}
return columnStyle;
}
private boolean isTitleColumn(Object id) {
if (CommonMetadataBuilder.TITLE.equals(id)) {
return true;
}
if (id instanceof MetadataVO) {
MetadataVO metadata = (MetadataVO) id;
return metadata.codeMatches(CommonMetadataBuilder.TITLE);
}
return false;
}
});
}
protected String getTitleColumnStyle(RecordVO recordVO) {
String style;
if (recordVO != null) {
try {
String extension = FileIconUtils.getExtension(recordVO);
if (extension != null && !isDecomList(recordVO)) {
style = "file-icon-" + extension;
} else {
style = null;
}
} catch (Exception e) {
// Do Nothing;
style = null;
}
} else {
style = null;
}
return style;
}
private boolean isDecomList(RecordVO recordVO) {
if (recordVO.getSchema() != null) {
return recordVO.getSchema().getCode().startsWith(DecommissioningList.SCHEMA_TYPE);
}
return false;
}
@SuppressWarnings("rawtypes")
protected RecordVO getRecordVOForTitleColumn(Item item) {
if (item instanceof RecordVOItem) {
return ((RecordVOItem) item).getRecord();
}
if (item instanceof BeanItem) {
Object bean = ((BeanItem) item).getBean();
return (RecordVO) bean;
}
return null;
}
public boolean isContextMenuPossible() {
return true;
}
public final List<MetadataSchemaVO> getSchemas() {
return schemaVOs;
}
public final void setMetadataDisplayFactory(MetadataDisplayFactory metadataDisplayFactory) {
this.metadataDisplayFactory = metadataDisplayFactory;
}
@Override
public void setContainerDataSource(Container newDataSource) {
super.setContainerDataSource(newDataSource);
findSchemaVOs(newDataSource);
initSchemaVOs();
}
@Override
public Property<?> getContainerProperty(final Object itemId, final Object propertyId) {
Property<?> containerProperty;
if (propertyId instanceof MetadataVO) {
MetadataVO metadataVO = (MetadataVO) propertyId;
RecordVOItem recordVOItem = (RecordVOItem) getItem(itemId);
RecordVO recordVO = recordVOItem.getRecord();
MetadataValueVO metadataValue = recordVO.getMetadataValue(metadataVO);
Component metadataDisplay;
if (metadataValue != null) {
metadataDisplay = buildMetadataComponent(metadataValue, recordVO);
} else {
metadataDisplay = new Label("");
}
boolean instance = metadataDisplay instanceof Label;
boolean matchCode = metadataVO.codeMatches(Schemas.TITLE_CODE);
if (instance && matchCode) {
RecordVO titleRecordVO = getRecordVOForTitleColumn(getItem(itemId));
if (titleRecordVO != null) {
MetadataSchemaVO recordSchemaVO = titleRecordVO.getSchema();
String prefix = SchemaCaptionUtils.getCaptionForSchema(recordSchemaVO.getCode());
Label titleLabel = (Label) metadataDisplay;
String titleForRecordVO = getTitleForRecordVO(titleRecordVO, prefix, titleLabel.getValue());
titleLabel.setValue(titleForRecordVO);
}
}
containerProperty = new ObjectProperty<>(metadataDisplay, Component.class);
} else {
containerProperty = super.getContainerProperty(itemId, propertyId);
}
return containerProperty;
}
protected String getTitleForRecordVO(RecordVO titleRecordVO, String prefix, String title) {
return StringUtils.isNotBlank(prefix) ? prefix + " " + title : title;
}
protected Component buildMetadataComponent(MetadataValueVO metadataValue, RecordVO recordVO) {
return metadataDisplayFactory.build(recordVO, metadataValue);
}
@Override
public Class<?> getType(Object propertyId) {
Class<?> type;
if (propertyId instanceof MetadataVO) {
type = Component.class;
} else {
type = super.getType(propertyId);
}
return type;
}
private void findSchemaVOs(Container container) {
if (container instanceof RecordVOLazyContainer) {
RecordVOLazyContainer recordVOLazyContainer = (RecordVOLazyContainer) container;
schemaVOs = recordVOLazyContainer.getSchemas();
} else if (container instanceof ContainerAdapter) {
ContainerAdapter<?> containerAdapter = (ContainerAdapter<?>) container;
findSchemaVOs(containerAdapter.getNestedContainer());
}
}
private void initSchemaVOs() {
if (schemaVOs != null && !schemaVOs.isEmpty()) {
MetadataVO titleMetadata = schemaVOs.get(0).getMetadata(Schemas.TITLE.getCode());
setColumnExpandRatio(titleMetadata, 1);
if (isContextMenuPossible()) {
addContextMenu();
addMenuBarColumn();
}
}
}
protected RecordVO getRecordVO(Object itemId) {
RecordVOItem recordVOItem = (RecordVOItem) getItem(itemId);
return recordVOItem.getRecord();
}
protected void addContextMenu() {
for (MetadataSchemaVO schemaVO : schemaVOs) {
String schemaCode = schemaVO.getCode();
List<RecordContextMenuHandler> recordContextMenuHandlers = ConstellioUI.getCurrent().getRecordContextMenuHandlers();
for (RecordContextMenuHandler recordContextMenuHandler : recordContextMenuHandlers) {
if (recordContextMenuHandler.isContextMenuForSchemaCode(schemaCode)) {
contextMenu = recordContextMenuHandler.getForSchemaCode(schemaCode);
break;
}
}
if (contextMenu != null) {
contextMenu.setAsContextMenuOf(this);
BaseContextMenuTableListener contextMenuTableListener = new BaseContextMenuTableListener() {
@Override
public void onContextMenuOpenFromFooter(ContextMenuOpenedOnTableFooterEvent event) {
}
@Override
public void onContextMenuOpenFromHeader(ContextMenuOpenedOnTableHeaderEvent event) {
}
@Override
public void onContextMenuOpenFromRow(ContextMenuOpenedOnTableRowEvent event) {
Object itemId = event.getItemId();
RecordVO recordVO = getRecordVO(itemId);
contextMenu.openFor(recordVO);
}
};
contextMenu.addContextMenuTableListener(contextMenuTableListener);
break;
}
}
}
protected void addMenuBarColumn() {
boolean menuBarColumnGenerated = getColumnGenerator(MENUBAR_PROPERTY_ID) != null;
if (!menuBarColumnGenerated) {
boolean menuBarRequired = false;
for (MetadataSchemaVO schemaVO : schemaVOs) {
String schemaCode = schemaVO.getCode();
List<RecordMenuBarHandler> recordMenuBarHandlers = ConstellioUI.getCurrent().getRecordMenuBarHandlers();
for (RecordMenuBarHandler recordMenuBarHandler : recordMenuBarHandlers) {
if (recordMenuBarHandler.isMenuBarForSchemaCode(schemaCode)) {
menuBarRequired = true;
break;
}
}
}
if (menuBarRequired) {
addGeneratedColumn(MENUBAR_PROPERTY_ID, new ColumnGenerator() {
@Override
public Object generateCell(Table source, Object itemId, Object columnId) {
Item item = getItem(itemId);
RecordVO recordVO = getRecordVOForTitleColumn(item);
MenuBar menuBar = null;
if (recordVO != null) {
List<RecordMenuBarHandler> recordMenuBarHandlers = ConstellioUI.getCurrent().getRecordMenuBarHandlers();
for (RecordMenuBarHandler recordMenuBarHandler : recordMenuBarHandlers) {
menuBar = recordMenuBarHandler.get(recordVO);
if (menuBar != null) {
break;
}
}
}
return menuBar != null ? menuBar : new Label("");
}
});
setColumnHeader(MENUBAR_PROPERTY_ID, "");
setColumnCollapsible(MENUBAR_PROPERTY_ID, false);
}
}
}
@Override
public void addItemClickListener(final ItemClickListener listener) {
addStyleName(CLICKABLE_ROW_STYLE_NAME);
super.addItemClickListener(new ItemClickListener() {
@Override
public void itemClick(ItemClickEvent event) {
if (event.getButton() == MouseButton.LEFT || contextMenu != null) {
listener.itemClick(event);
}
}
});
}
public void setColumnCollapsed(String metadataCode, boolean collapsed) {
if (!isColumnCollapsingAllowed()) {
return;
}
Object[] visibleColumnIds = getVisibleColumns();
for (Object visibleColumnId : visibleColumnIds) {
if (visibleColumnId instanceof MetadataVO) {
MetadataVO metadataVO = (MetadataVO) visibleColumnId;
if (metadataVO.getCode().contains(metadataCode)) {
setColumnCollapsed(visibleColumnId, collapsed);
}
}
}
}
public RecordContextMenu getContextMenu() {
return contextMenu;
}
}