/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package de.unioninvestment.eai.portal.portlet.crud.mvp.views.ui; import java.util.Set; import org.vaadin.tokenfield.TokenField; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.server.Sizeable.Unit; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractField; import com.vaadin.ui.AbstractSelect; import com.vaadin.ui.AbstractSelect.ItemCaptionMode; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Component; import com.vaadin.ui.DefaultFieldFactory; import com.vaadin.ui.Field; import com.vaadin.ui.PopupDateField; import com.vaadin.ui.Table; import com.vaadin.ui.TableFieldFactory; import com.vaadin.ui.TextArea; import de.unioninvestment.eai.portal.portlet.crud.config.DateDisplayType; import de.unioninvestment.eai.portal.portlet.crud.domain.container.CheckBoxSupport; import de.unioninvestment.eai.portal.portlet.crud.domain.container.DatePickerSupport; import de.unioninvestment.eai.portal.portlet.crud.domain.container.SelectSupport; import de.unioninvestment.eai.portal.portlet.crud.domain.container.TokenFieldSupport; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ContainerRow; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ContainerRowId; import de.unioninvestment.eai.portal.portlet.crud.domain.model.DataContainer; import de.unioninvestment.eai.portal.portlet.crud.domain.model.OptionList; import de.unioninvestment.eai.portal.portlet.crud.domain.model.SelectionContext; import de.unioninvestment.eai.portal.portlet.crud.domain.model.SelectionTableColumn; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Table.Mode; import de.unioninvestment.eai.portal.portlet.crud.domain.model.TableColumn; import de.unioninvestment.eai.portal.portlet.crud.scripting.domain.TableColumnSelectionContext; import de.unioninvestment.eai.portal.support.vaadin.context.Context; import de.unioninvestment.eai.portal.support.vaadin.table.DisplaySupport; /** * TableFieldFactory feur die Crud Datentabelle. Delegiert an * datentypspezifische Implementierungen von {@link DisplaySupport}. * * @author markus.bonsch */ public class DefaultCrudFieldFactory implements TableFieldFactory, CrudFieldFactory { private enum Target { FORM, TABLE } private static final int DEFAULT_ROWS = 1; private static final long serialVersionUID = 1L; private static final int HUNDRED = 100; private final DataContainer dataContainer; private final Table vaadinTable; private final de.unioninvestment.eai.portal.portlet.crud.domain.model.Table modelTable; private boolean createFormFieldForTable = true; /** * @param vaadinTable * die Tabelle * @param tableColumns * Spaltenkonfiguration aus XML */ public DefaultCrudFieldFactory( Table vaadinTable, de.unioninvestment.eai.portal.portlet.crud.domain.model.Table modelTable) { this.vaadinTable = vaadinTable; this.modelTable = modelTable; this.dataContainer = modelTable.getContainer(); } public void setCreateFormFieldForTable(boolean createFormFieldForTable) { this.createFormFieldForTable = createFormFieldForTable; } @Override public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) { if (createFormFieldForTable && isSelectedRow(itemId)) { Item item = container.getItem(itemId); Field<?> field = createField(item, propertyId, false, Target.TABLE); if (field != null && field.isReadOnly()) { return null; } return field; } return null; } @Override public Field<?> createField(Item item, Object propertyId) { return createField(item, propertyId, true, Target.FORM); } private Field<?> createField(Item item, Object propertyId, boolean createReadonlyFields, Target target) { ContainerRow row = dataContainer.convertItemToRow(item, false, true); Property<?> property = item.getItemProperty(propertyId); String propertyIdString = propertyId.toString(); DisplaySupport displayer = dataContainer .findDisplayer(propertyIdString); if (displayer != null) { boolean readonly = isReadonly(row, propertyId, propertyIdString); Field<?> field = getFieldFromDisplayer(property.getType(), row, propertyId, displayer, property, readonly); applyCommonFieldSettings(field, propertyId, target); field.setReadOnly(readonly); return field; } return null; } private boolean isReadonly(ContainerRow row, Object propertyId, String propertyIdString) { if (!modelTable.isEditable()) { return true; } if (modelTable.getMode() == Mode.VIEW) { return true; } boolean fieldIsReadonlyByContainer = row.getFields().get(propertyId) .isReadonly(); if (fieldIsReadonlyByContainer) { return true; } if (modelTable.getColumns() != null) { if (!modelTable.isRowEditable(row)) { return true; } TableColumn column = modelTable.getColumns().get(propertyIdString); boolean cellIsConfiguredAsReadonly = !column.isEditable(row); if (cellIsConfiguredAsReadonly) { return true; } } return false; } private void fillSelections(AbstractSelect select, ContainerRowId rowId, Object propertyId) { OptionListContainer container = createOptionListContainer(rowId, propertyId); select.setContainerDataSource(container); select.setItemCaptionMode(ItemCaptionMode.ITEM); } private void fillSelections(TokenField tokens, ContainerRowId rowId, Object propertyId) { OptionListContainer container = createOptionListContainer(rowId, propertyId); tokens.setContainerDataSource(container); tokens.setTokenCaptionMode(ItemCaptionMode.ITEM); } private OptionListContainer createOptionListContainer(ContainerRowId rowId, Object propertyId) { SelectionContext context = new TableColumnSelectionContext(rowId, propertyId.toString()); OptionList selection = modelTable.getColumns().getDropdownSelections( (String) propertyId); OptionListContainer container = new OptionListContainer(selection, context); return container; } private boolean isSelectedRow(Object itemId) { if (itemId != null && vaadinTable.isSelectable()) { if (vaadinTable.isMultiSelect()) { Set<?> selection = (Set<?>) vaadinTable.getValue(); if (selection.size() == 1) { return itemId.equals(selection.iterator().next()); } } else { if (vaadinTable.getValue() != null) { return itemId.equals(vaadinTable.getValue()); } } } return false; } private Field<?> getFieldFromDisplayer(Class<?> type, ContainerRow row, Object propertyId, DisplaySupport displayer, Property<?> property, boolean readonly) { if (isComboBox(propertyId, displayer)) { AbstractSelect select = ((SelectSupport) displayer).createSelect( type, propertyId, dataContainer.getFormat(propertyId.toString())); fillSelections(select, row.getId(), propertyId); return select; } else if (isTokenField(propertyId, displayer)) { String delimiter = ((SelectionTableColumn) modelTable.getColumns() .get((String) propertyId)).getSeparator(); TokenField tokens = ((TokenFieldSupport) displayer) .createTokenField(type, propertyId, delimiter, dataContainer.getFormat(propertyId.toString())); fillSelections(tokens, row.getId(), propertyId); return tokens; } else if (isCheckbox(propertyId, displayer)) { de.unioninvestment.eai.portal.portlet.crud.domain.model.CheckBoxTableColumn checkBoxModel = modelTable .getColumns().getCheckBox(propertyId.toString()); CheckBox checkBox = ((CheckBoxSupport) displayer).createCheckBox( type, checkBoxModel.getCheckedValue(), checkBoxModel.getUncheckedValue(), dataContainer.getFormat(propertyId.toString())); if (readonly) { checkBox.setEnabled(false); } return checkBox; } else if (!readonly && isDatePicker(propertyId, displayer)) { String format = modelTable.getColumns() == null ? null : modelTable .getColumns().get(propertyId.toString()).getDisplayFormat(); PopupDateField datePicker = ((DatePickerSupport) displayer) .createDatePicker(type, propertyId, null, format); datePicker.setLocale(Context.getLocale()); return datePicker; } else { String prompt = null; if (modelTable.getColumns() != null) { prompt = modelTable.getColumns().getInputPrompt( propertyId.toString()); } return displayer.createField(type, propertyId, isMultiline(propertyId), prompt, dataContainer.getFormat(propertyId.toString())); } } private boolean isDatePicker(Object propertyId, DisplaySupport displayer) { String columnName = propertyId.toString(); return modelTable.getColumns() != null && modelTable.getColumns().isDate(columnName) && modelTable.getColumns().getDateColumn(columnName) .getDateDisplayType() == DateDisplayType.PICKER && displayer instanceof DatePickerSupport; } private boolean isMultiline(Object propertyId) { boolean multiline = false; if (modelTable.getColumns() != null) { multiline = modelTable.getColumns().isMultiline( propertyId.toString()); } return multiline; } private int getRows(Object propertyId) { if (modelTable.getColumns() != null) { Integer rows = modelTable.getColumns().get(propertyId.toString()) .getRows(); if (rows != null) { return rows; } } return DEFAULT_ROWS; } private boolean isComboBox(Object propertyId, DisplaySupport displayer) { return modelTable.getColumns() != null && modelTable.getColumns().isComboBox(propertyId.toString()) && displayer instanceof SelectSupport; } private boolean isTokenField(Object propertyId, DisplaySupport displayer) { return modelTable.getColumns() != null && modelTable.getColumns().isTokenfield(propertyId.toString()) && displayer instanceof TokenFieldSupport; } private boolean isEditForm() { return modelTable.getColumns() != null && modelTable.isFormEditEnabled(); } private boolean isCheckbox(Object propertyId, DisplaySupport displayer) { return modelTable.getColumns() != null && modelTable.getColumns().isCheckbox(propertyId.toString()) && displayer instanceof CheckBoxSupport; } private void applyCommonFieldSettings(Field<?> field, Object propertyId, Target target) { setCaptionAndTooltipIfGiven(field, propertyId, target); field.setWidth(HUNDRED, Unit.PERCENTAGE); field.setBuffered(true); passThroughConversionExceptionMessage(field); if (field instanceof TextArea) { TextArea area = (TextArea) field; if (isEditForm()) { area.setRows(getRows(propertyId)); } else { area.setHeight(getRows(propertyId), Unit.EM); } } } private void passThroughConversionExceptionMessage(Field<?> field) { if (field instanceof AbstractField<?>) { AbstractField<?> abstractField = (AbstractField<?>) field; abstractField.setConversionError("{1}"); } } private void setCaptionAndTooltipIfGiven(Field<?> field, Object propertyId, Target target) { boolean leaveCaptionEmpty = (field instanceof CheckBox && target == Target.TABLE); if (modelTable.getColumns() != null) { TableColumn column = modelTable.getColumns().get( propertyId.toString()); String longTitle = column.getLongTitle(); if (longTitle != null) { if (field instanceof AbstractComponent) { ((AbstractComponent) field).setDescription(longTitle); } } String title = column.getTitle(); if (title != null && !leaveCaptionEmpty) { field.setCaption(title); return; } } if (!leaveCaptionEmpty) { field.setCaption(DefaultFieldFactory .createCaptionByPropertyId(propertyId)); } } }