package com.constellio.app.ui.pages.search; import static com.constellio.app.ui.i18n.i18n.$; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.joda.time.LocalDateTime; import com.constellio.app.ui.application.ConstellioUI; import com.constellio.app.ui.entities.MetadataVO; import com.constellio.app.ui.framework.buttons.IconButton; import com.constellio.app.ui.framework.components.BaseWindow; import com.constellio.app.ui.framework.components.converters.BaseStringToDoubleConverter; import com.constellio.app.ui.framework.components.converters.JodaDateTimeToUtilConverter; import com.constellio.app.ui.framework.components.fields.BaseTextField; import com.constellio.app.ui.framework.components.fields.date.BaseDateField; import com.constellio.app.ui.framework.components.fields.enumWithSmallCode.EnumWithSmallCodeComboBox; import com.constellio.app.ui.framework.components.fields.lookup.LookupRecordField; import com.constellio.app.ui.framework.components.fields.lookup.PathLookupField; import com.constellio.app.ui.pages.search.criteria.Criterion; import com.constellio.app.ui.pages.search.criteria.Criterion.BooleanOperator; import com.constellio.app.ui.pages.search.criteria.Criterion.SearchOperator; import com.constellio.app.ui.pages.search.criteria.RelativeCriteria.RelativeSearchOperator; import com.constellio.data.utils.TimeProvider; import com.constellio.model.entities.EnumWithSmallCode; import com.constellio.model.entities.schemas.AllowedReferences; import com.constellio.model.services.search.query.logical.criteria.MeasuringUnitTime; import com.vaadin.data.Property; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.server.Resource; import com.vaadin.server.ThemeResource; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.DateField; import com.vaadin.ui.Field; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; public class AdvancedSearchCriteriaComponent extends Table { public static final String LEFT_PARENS_FIELD = "leftParensField"; public static final String METADATA_FIELD = "metadataField"; public static final String VALUE_FIELD = "valueField"; public static final String RIGHT_PARENS_FIELD = "rightParensField"; public static final String OPERATOR_FIELD = "operatorField"; public static final String DELETE_BUTTON = "delete"; private final BeanItemContainer<Criterion> container; private String schemaType; public AdvancedSearchCriteriaComponent(SearchCriteriaPresenter presenter) { super(); container = new BeanItemContainer<>(Criterion.class); setContainerDataSource(container); addGeneratedColumn(LEFT_PARENS_FIELD, new ParensFieldGenerator("leftParens", "(")); addGeneratedColumn(METADATA_FIELD, new MetadataFieldGenerator(presenter)); addGeneratedColumn(VALUE_FIELD, new ValueFieldGenerator(presenter)); addGeneratedColumn(RIGHT_PARENS_FIELD, new ParensFieldGenerator("rightParens", ")")); addGeneratedColumn(OPERATOR_FIELD, new OperatorFieldGenerator()); addGeneratedColumn(DELETE_BUTTON, new DeleteButtonGenerator()); setColumnHeaderMode(ColumnHeaderMode.HIDDEN); setVisibleColumns(LEFT_PARENS_FIELD, METADATA_FIELD, VALUE_FIELD, RIGHT_PARENS_FIELD, OPERATOR_FIELD, DELETE_BUTTON); setColumnExpandRatio(VALUE_FIELD, 1); } public void setSchemaType(String schemaType) { this.schemaType = schemaType; for (Criterion criterion : container.getItemIds()) { criterion.setSchemaType(schemaType); } refreshRowCache(); } public AdvancedSearchCriteriaComponent addEmptyCriterion() { addItem(new Criterion(schemaType)); setPageLength(size()); return this; } public List<Criterion> getSearchCriteria() { List<Criterion> result = new ArrayList<>(); for (Criterion criterion : container.getItemIds()) { if (criterion.isNotEmpty()) { result.add(criterion); } } return result; } public void setSearchCriteria(List<Criterion> criteria) { container.removeAllItems(); container.addAll(criteria); setPageLength(criteria.size()); } public void clear() { setSearchCriteria(new ArrayList<Criterion>()); } public static class MetadataFieldGenerator implements ColumnGenerator { private SearchCriteriaPresenter presenter; public MetadataFieldGenerator(SearchCriteriaPresenter presenter) { this.presenter = presenter; } @Override public Component generateCell(Table source, Object itemId, Object columnId) { return buildMetadataField((Criterion) itemId, source); } private Component buildMetadataField(final Criterion criterion, final Table source) { ComboBox comboBox = new ComboBox(); comboBox.setItemCaptionMode(ItemCaptionMode.EXPLICIT); comboBox.setNullSelectionAllowed(false); if (criterion.getSchemaType() == null) { comboBox.setEnabled(false); return comboBox; } for (MetadataVO metadata : presenter.getMetadataAllowedInCriteria()) { comboBox.addItem(metadata); comboBox.setItemCaption(metadata, metadata.getLabel(ConstellioUI.getCurrentSessionContext().getCurrentLocale())); } MetadataVO metadataVO = presenter.getMetadataVO(criterion.getMetadataCode()); comboBox.setValue(metadataVO); comboBox.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { MetadataVO metadataVO = (MetadataVO) event.getProperty().getValue(); String enumClassName = null; if (metadataVO.getEnumClass() != null) { enumClassName = metadataVO.getEnumClass().getName(); } criterion.setMetadata(metadataVO.getCode(), metadataVO.getType(), enumClassName); source.refreshRowCache(); } }); comboBox.setPageLength(comboBox.size()); return comboBox; } } public static class ValueFieldGenerator implements ColumnGenerator { private final SearchCriteriaPresenter presenter; public ValueFieldGenerator(SearchCriteriaPresenter presenter) { this.presenter = presenter; } @Override public Component generateCell(Table source, Object itemId, Object columnId) { return generateCell((Criterion) itemId); } private Component generateCell(Criterion criterion) { if (criterion.getMetadataCode() == null) { return null; } switch (criterion.getMetadataType()) { case STRING: case TEXT: return criterion.getSearchOperator() == SearchOperator.IN_HIERARCHY ? buildHierarchyValueCriterion(criterion) : buildStringValueComponent(criterion); case DATE: case DATE_TIME: return buildDateValueComponent(criterion); case NUMBER: case INTEGER: return buildNumberValueComponent(criterion); case BOOLEAN: return buildBooleanValueComponent(criterion); case ENUM: return buildEnumValueComponent(criterion); case REFERENCE: return buildReferenceValueComponent(criterion); } return null; } private Component buildReferenceValueComponent(final Criterion criterion) { MetadataVO metadata = presenter.getMetadataVO(criterion.getMetadataCode()); final Field<?> value = buildReferenceEntryField(metadata.getAllowedReferences(), criterion); final ComboBox operator = buildIsEmptyIsNotEmptyComponent(criterion); operator.setNullSelectionAllowed(false); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { SearchOperator newOperator = (SearchOperator) operator.getValue(); if (newOperator != null) { criterion.setSearchOperator(newOperator); value.setVisible( !newOperator.equals(SearchOperator.IS_NULL) && !newOperator.equals(SearchOperator.IS_NOT_NULL)); } else { value.setVisible(true); } } }); HorizontalLayout component = new HorizontalLayout(operator, value); component.setComponentAlignment(value, Alignment.MIDDLE_RIGHT); component.setExpandRatio(value, 1); component.setWidth("100%"); component.setSpacing(true); return component; } private Field<?> buildReferenceEntryField(AllowedReferences references, final Criterion criterion) { String allowedSchemaType = references.getAllowedSchemaType(); Set<String> allowedSchemas = references.getAllowedSchemas(); String firstAllowedSchema = !allowedSchemas.isEmpty() ? allowedSchemas.iterator().next() : null; final LookupRecordField field = new LookupRecordField(allowedSchemaType, firstAllowedSchema); field.setWindowZIndex(BaseWindow.OVER_ADVANCED_SEARCH_FORM_Z_INDEX); field.setWidth("100%"); field.setValue((String) criterion.getValue()); field.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setValue(field.getValue()); } }); return field; } private Component buildStringValueComponent(final Criterion criterion) { final TextField value = new BaseTextField(); value.setWidth("100%"); value.setValue((String) criterion.getValue()); value.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setValue(value.getValue()); } }); final CheckBox exact = new CheckBox($("AdvancedSearchView.exactMatch")); exact.setValue(criterion.getSearchOperator() == SearchOperator.EQUALS); exact.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setSearchOperator(exact.getValue() ? SearchOperator.EQUALS : SearchOperator.CONTAINS_TEXT); } }); final SearchOperator searchOperator = criterion.getSearchOperator(); final ComboBox operator = buildIsEmptyIsNotEmptyComponent(criterion); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { SearchOperator newOperator = (SearchOperator) operator.getValue(); if (newOperator != null) { if(newOperator == SearchOperator.EQUALS || newOperator == SearchOperator.CONTAINS_TEXT) { criterion.setSearchOperator(exact.getValue() ? SearchOperator.EQUALS : SearchOperator.CONTAINS_TEXT); } else { criterion.setSearchOperator(newOperator); } value.setVisible( !newOperator.equals(SearchOperator.IS_NULL) && !newOperator.equals(SearchOperator.IS_NOT_NULL)); exact.setVisible( !newOperator.equals(SearchOperator.IS_NULL) && !newOperator.equals(SearchOperator.IS_NOT_NULL)); } else { criterion.setSearchOperator(searchOperator); value.setVisible(true); exact.setVisible(true); } } }); HorizontalLayout component = new HorizontalLayout(operator, value, exact); component.setComponentAlignment(exact, Alignment.MIDDLE_RIGHT); component.setExpandRatio(value, 1); component.setWidth("100%"); component.setSpacing(true); return component; } private Component buildHierarchyValueCriterion(final Criterion criterion) { final PathLookupField lookup = new PathLookupField(); lookup.setWindowZIndex(BaseWindow.OVER_ADVANCED_SEARCH_FORM_Z_INDEX); lookup.setValue((String) criterion.getValue()); lookup.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setValue(lookup.getValue()); } }); HorizontalLayout component = new HorizontalLayout(lookup); component.setExpandRatio(lookup, 1); component.setWidth("100%"); component.setSpacing(true); return component; } private Component buildBooleanValueComponent(final Criterion criterion) { final ComboBox operator = new ComboBox(); operator.addItem(SearchOperator.IS_TRUE); operator.setItemCaption(SearchOperator.IS_TRUE, $("AdvancedSearchView.isTrue")); operator.addItem(SearchOperator.IS_FALSE); operator.setItemCaption(SearchOperator.IS_FALSE, $("AdvancedSearchView.isFalse")); addIsEmptyIsNotEmpty(criterion, operator); operator.setItemCaptionMode(ItemCaptionMode.EXPLICIT); operator.setNullSelectionAllowed(false); operator.setValue(criterion.getSearchOperator()); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setSearchOperator((SearchOperator) operator.getValue()); } }); return operator; } private ComboBox buildIsEmptyIsNotEmptyComponent(final Criterion criterion) { final ComboBox operator = new ComboBox(); addIsEmptyIsNotEmpty(criterion, operator); operator.setWidth("100px"); operator.setItemCaptionMode(ItemCaptionMode.EXPLICIT); operator.setNullSelectionAllowed(true); operator.setValue(criterion.getSearchOperator()); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setSearchOperator((SearchOperator) operator.getValue()); } }); return operator; } private void addIsEmptyIsNotEmpty(final Criterion criterion, final ComboBox operator) { Object defaultValue = criterion.getSearchOperator() != null ? criterion.getSearchOperator() : SearchOperator.EQUALS; operator.addItem(SearchOperator.EQUALS); operator.setItemCaption(SearchOperator.EQUALS, "="); operator.addItem(SearchOperator.IS_NULL); operator.setItemCaption(SearchOperator.IS_NULL, $("AdvancedSearchView.isEmpty")); operator.addItem(SearchOperator.IS_NOT_NULL); operator.setItemCaption(SearchOperator.IS_NOT_NULL, $("AdvancedSearchView.isNotEmpty")); operator.setValue(defaultValue); } private Component buildEnumValueComponent(final Criterion criterion) { Class<?> enumClass; try { enumClass = Class.forName(criterion.getEnumClassName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } @SuppressWarnings("unchecked") final ComboBox value = new EnumWithSmallCodeComboBox<>((Class<? extends EnumWithSmallCode>) enumClass); value.setWidth("100%"); value.setNullSelectionAllowed(false); value.setValue(criterion.getValue()); value.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setValue(value.getValue()); } }); //value.setVisible(); final SearchOperator searchOperator = criterion.getSearchOperator(); final ComboBox operator = buildIsEmptyIsNotEmptyComponent(criterion); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { SearchOperator newOperator = (SearchOperator) operator.getValue(); if (newOperator != null) { criterion.setSearchOperator(newOperator); boolean visible = !newOperator.equals(SearchOperator.IS_NULL) && !newOperator.equals(SearchOperator.IS_NOT_NULL); value.setVisible(visible); if (!visible) { criterion.setValue(null); } } else { criterion.setSearchOperator(searchOperator); value.setVisible(true); } } }); HorizontalLayout component = new HorizontalLayout(operator, value); component.setComponentAlignment(value, Alignment.MIDDLE_RIGHT); component.setExpandRatio(value, 1); component.setWidth("100%"); component.setSpacing(true); return component; } private Component buildDateValueComponent(final Criterion criterion) { // We only want to display a date, but we need a full datetime, so we cannot use a JodaDateField here Component relativeSearchComponent = buildRelativeSearchComboBox(criterion, false); Component endRelativeSearchComponent = buildRelativeSearchComboBox(criterion, true); ComboBox operator = buildComparisonComboBox(criterion, relativeSearchComponent, endRelativeSearchComponent); HorizontalLayout horizontalLayout = new HorizontalLayout(); horizontalLayout.setSpacing(true); horizontalLayout.addComponents(operator, relativeSearchComponent); VerticalLayout verticalLayout = new VerticalLayout(horizontalLayout, endRelativeSearchComponent); verticalLayout.setSpacing(true); return verticalLayout; } private Component buildNumberValueComponent(final Criterion criterion) { final TextField value = new TextField(); value.setWidth("100px"); value.setNullRepresentation(""); value.setConverter(new BaseStringToDoubleConverter()); value.setConvertedValue(criterion.getValue()); value.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setValue(value.getConvertedValue()); } }); value.setVisible(true); final TextField endValue = new TextField(); endValue.setWidth("100px"); endValue.setNullRepresentation(""); endValue.setConverter(new BaseStringToDoubleConverter()); endValue.setConvertedValue(criterion.getValue()); endValue.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setEndValue(endValue.getConvertedValue()); } }); final Label label = new Label($("and")); label.setWidth("100px"); HorizontalLayout horizontalLayoutLabel = new HorizontalLayout(); horizontalLayoutLabel.addComponent(label); horizontalLayoutLabel.setComponentAlignment(label, Alignment.MIDDLE_CENTER); HorizontalLayout horizontalLayout = new HorizontalLayout(); horizontalLayout.setSpacing(true); horizontalLayout.addComponents(horizontalLayoutLabel, endValue); ComboBox operator = buildComparisonComboBox(criterion, value, horizontalLayout); HorizontalLayout component = new HorizontalLayout(operator, value, horizontalLayout); component.setSpacing(true); return component; } private ComboBox buildComparisonComboBox(final Criterion criterion, final Component firstComponent, final Component endComponent) { Object defaultValue = criterion.getSearchOperator() != null ? criterion.getSearchOperator() : SearchOperator.EQUALS; final ComboBox operator = new ComboBox(); operator.setWidth("150px"); operator.addItem(SearchOperator.EQUALS); operator.setItemCaption(SearchOperator.EQUALS, "="); operator.addItem(SearchOperator.LESSER_THAN); operator.setItemCaption(SearchOperator.LESSER_THAN, "<"); operator.addItem(SearchOperator.GREATER_THAN); operator.setItemCaption(SearchOperator.GREATER_THAN, ">"); operator.addItem(SearchOperator.BETWEEN); operator.setItemCaption(SearchOperator.BETWEEN, $("AdvancedSearchView.between")); addIsEmptyIsNotEmpty(criterion, operator); operator.setItemCaptionMode(ItemCaptionMode.EXPLICIT); operator.setValue(defaultValue); operator.setNullSelectionAllowed(false); operator.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { configureVisibility(operator, criterion, firstComponent, endComponent); } }); configureVisibility(operator, criterion, firstComponent, endComponent); return operator; } private void configureVisibility(ComboBox operator, Criterion criterion, Component firstComponent, Component endComponent) { SearchOperator newOperator = (SearchOperator) operator.getValue(); criterion.setSearchOperator(newOperator); criterion.getRelativeCriteria(); if (firstComponent != null) { if (newOperator.equals(SearchOperator.IS_NULL) || newOperator.equals(SearchOperator.IS_NOT_NULL)) { firstComponent.setVisible(false); endComponent.setVisible(false); } else if (newOperator.equals(SearchOperator.BETWEEN)) { firstComponent.setVisible(true); endComponent.setVisible(true); } else { firstComponent.setVisible(true); endComponent.setVisible(false); } } } private Component buildRelativeSearchComboBox(final Criterion criterion, final boolean isEndValue) { Object value; final MeasuringUnitTime measuringUnitTimeValue; if (!isEndValue) { value = criterion.getValue(); measuringUnitTimeValue = criterion.getRelativeCriteria().getMeasuringUnitTime(); } else { value = criterion.getEndValue(); measuringUnitTimeValue = criterion.getRelativeCriteria().getEndMeasuringUnitTime(); } final DateField date = new BaseDateField(); date.setWidth("150px"); date.setConverter(new JodaDateTimeToUtilConverter()); try { date.setConvertedValue(value); } catch (Exception e) { } date.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { if (!isEndValue) { criterion.setValue(expandToBeforeMidnight((LocalDateTime) date.getConvertedValue())); } else { criterion.setEndValue(expandToBeforeMidnight((LocalDateTime) date.getConvertedValue())); } } }); final TextField textValue = new TextField(); textValue.setWidth("100px"); textValue.setNullRepresentation(""); try { textValue.setConvertedValue(value); } catch (Exception e) { } textValue.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { Object convertedValue = textValue.getConvertedValue(); if (!isEndValue) { criterion.setValue(convertedValue); } else { criterion.setEndValue(convertedValue); } } }); final ComboBox measuringTimeField = new ComboBox(); measuringTimeField.setWidth("150px"); measuringTimeField.addItem(MeasuringUnitTime.DAYS); measuringTimeField.setItemCaption(MeasuringUnitTime.DAYS, $("MeasuringUnitTime.D")); measuringTimeField.addItem(MeasuringUnitTime.WEEKS); measuringTimeField.setItemCaption(MeasuringUnitTime.WEEKS, $("MeasuringUnitTime.W")); measuringTimeField.addItem(MeasuringUnitTime.MONTHS); measuringTimeField.setItemCaption(MeasuringUnitTime.MONTHS, $("MeasuringUnitTime.M")); measuringTimeField.addItem(MeasuringUnitTime.YEARS); measuringTimeField.setItemCaption(MeasuringUnitTime.YEARS, $("MeasuringUnitTime.Y")); measuringTimeField.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { MeasuringUnitTime measuringUnitTime = (MeasuringUnitTime) measuringTimeField.getValue(); if (!isEndValue) { criterion.getRelativeCriteria().setMeasuringUnitTime(measuringUnitTime); } else { criterion.getRelativeCriteria().setEndMeasuringUnitTime(measuringUnitTime); } } }); measuringTimeField.setValue(measuringUnitTimeValue); Object defaultRelativeSearchOperatorValue; if (isEndValue) { defaultRelativeSearchOperatorValue = criterion.getRelativeCriteria().getEndRelativeSearchOperator() != null ? criterion.getRelativeCriteria().getEndRelativeSearchOperator() : RelativeSearchOperator.EQUALS; } else { defaultRelativeSearchOperatorValue = criterion.getRelativeCriteria().getRelativeSearchOperator() != null ? criterion.getRelativeCriteria().getRelativeSearchOperator() : RelativeSearchOperator.EQUALS; } final ComboBox relativeSearchOperatorCombo = new ComboBox(); relativeSearchOperatorCombo.setWidth("150px"); relativeSearchOperatorCombo.addItem(RelativeSearchOperator.EQUALS); relativeSearchOperatorCombo.setItemCaption(RelativeSearchOperator.EQUALS, $("AdvancedSearchView.relativeSearchOperatorCombo.equals")); relativeSearchOperatorCombo.addItem(RelativeSearchOperator.TODAY); relativeSearchOperatorCombo.setItemCaption(RelativeSearchOperator.TODAY, $("AdvancedSearchView.relativeSearchOperatorCombo.today")); relativeSearchOperatorCombo.addItem(RelativeSearchOperator.PAST); relativeSearchOperatorCombo.setItemCaption(RelativeSearchOperator.PAST, $("AdvancedSearchView.relativeSearchOperatorCombo.past")); relativeSearchOperatorCombo.addItem(RelativeSearchOperator.FUTURE); relativeSearchOperatorCombo.setItemCaption(RelativeSearchOperator.FUTURE, $("AdvancedSearchView.relativeSearchOperatorCombo.future")); relativeSearchOperatorCombo.setItemCaptionMode(ItemCaptionMode.EXPLICIT); relativeSearchOperatorCombo.setValue(defaultRelativeSearchOperatorValue); relativeSearchOperatorCombo.setNullSelectionAllowed(false); relativeSearchOperatorCombo.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { configureVisibility(relativeSearchOperatorCombo, date, textValue, isEndValue, criterion, measuringTimeField); } }); final Label label = new Label($("and")); label.setWidth("150px"); HorizontalLayout horizontalLayoutLabel = new HorizontalLayout(); horizontalLayoutLabel.addComponent(label); horizontalLayoutLabel.setComponentAlignment(label, Alignment.MIDDLE_CENTER); horizontalLayoutLabel.setVisible(isEndValue); HorizontalLayout component = new HorizontalLayout(horizontalLayoutLabel, relativeSearchOperatorCombo, date, textValue, measuringTimeField); component.setComponentAlignment(horizontalLayoutLabel, Alignment.MIDDLE_CENTER); component.setSpacing(true); component.setVisible(!isEndValue); configureVisibility(relativeSearchOperatorCombo, date, textValue, isEndValue, criterion, measuringTimeField); return component; } private void configureVisibility(ComboBox relativeSearchOperatorCombo, DateField date, TextField textValue, boolean isEndValue, Criterion criterion, ComboBox measuringTimeField) { RelativeSearchOperator newRelativeSearchOperator = (RelativeSearchOperator) relativeSearchOperatorCombo .getValue(); if (newRelativeSearchOperator.equals(RelativeSearchOperator.EQUALS)) { date.setVisible(true); textValue.setVisible(false); } else if (newRelativeSearchOperator.equals(RelativeSearchOperator.TODAY)) { date.setVisible(false); textValue.setVisible(false); if (!isEndValue) { LocalDateTime ldt = TimeProvider.getLocalDateTime(); criterion.setValue(ldt); } else { LocalDateTime ldt = TimeProvider.getLocalDateTime(); criterion.setEndValue(ldt); } } else { date.setVisible(false); textValue.setVisible(true); } measuringTimeField.setVisible(textValue.isVisible()); if (!isEndValue) { criterion.getRelativeCriteria().setRelativeSearchOperator(newRelativeSearchOperator); } else { criterion.getRelativeCriteria().setEndRelativeSearchOperator(newRelativeSearchOperator); } } private LocalDateTime trimToMidnight(LocalDateTime date) { return date.withTime(0, 0, 0, 0); } private LocalDateTime expandToBeforeMidnight(LocalDateTime date) { return date.withTime(23, 59, 59, 999); } } public static class OperatorFieldGenerator implements ColumnGenerator { @Override public Component generateCell(Table source, Object itemId, Object columnId) { return buildOperatorField((Criterion) itemId); } private Component buildOperatorField(final Criterion criterion) { ComboBox comboBox = new ComboBox(); comboBox.addItem(BooleanOperator.AND); comboBox.setItemCaption(BooleanOperator.AND, $("AdvancedSearchView.AND")); comboBox.addItem(BooleanOperator.OR); comboBox.setItemCaption(BooleanOperator.OR, $("AdvancedSearchView.OR")); comboBox.addItem(BooleanOperator.AND_NOT); comboBox.setItemCaption(BooleanOperator.AND_NOT, $("AdvancedSearchView.AND_NOT")); comboBox.setItemCaptionMode(ItemCaptionMode.EXPLICIT); comboBox.setNullSelectionAllowed(false); comboBox.setValue(criterion.getBooleanOperator()); comboBox.setWidth("100px"); comboBox.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { criterion.setBooleanOperator((BooleanOperator) event.getProperty().getValue()); } }); return comboBox; } } public static class ParensFieldGenerator implements ColumnGenerator { private final String propertyId; private final String symbol; public ParensFieldGenerator(String propertyId, String symbol) { this.propertyId = propertyId; this.symbol = symbol; } @Override public Component generateCell(final Table source, final Object itemId, Object columnId) { TextField field = new TextField(); boolean active = (boolean) source.getItem(itemId).getItemProperty(propertyId).getValue(); field.setValue(active ? symbol : ""); field.setWidth("25px"); field.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { source.getItem(itemId).getItemProperty(propertyId).setValue(symbol.equals(event.getProperty().getValue())); } }); return field; } } public static class DeleteButtonGenerator implements ColumnGenerator { public static final Resource ICON_RESOURCE = new ThemeResource("images/commun/supprimer.gif"); @Override public Object generateCell(final Table source, final Object itemId, Object columnId) { Button delete = new IconButton(ICON_RESOURCE, $("delete"), true) { @Override protected void buttonClick(ClickEvent event) { source.removeItem(itemId); source.setPageLength(source.size()); } }; delete.setEnabled(source.size() > 1); return delete; } } public interface SearchCriteriaPresenter extends Serializable { void addCriterionRequested(); List<MetadataVO> getMetadataAllowedInCriteria(); MetadataVO getMetadataVO(String metadataCode); } }