/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2014, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.activiti.ftarchive; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.ObjectProperty; import com.vaadin.data.util.PropertysetItem; import com.vaadin.ui.ComboBox; import ru.codeinside.gses.beans.DirectoryBeanProvider; import ru.codeinside.gses.lazyquerycontainer.LazyQueryContainer; import ru.codeinside.gses.lazyquerycontainer.LazyQueryDefinition; import ru.codeinside.gses.lazyquerycontainer.Query; import ru.codeinside.gses.lazyquerycontainer.QueryDefinition; import ru.codeinside.gses.lazyquerycontainer.QueryFactory; import ru.codeinside.gses.vaadin.customfield.CustomField; import java.io.Serializable; import java.util.ArrayList; import java.util.List; final public class DirectoryField extends CustomField { private final ComboBox comboBox; int insideListener = 0; public DirectoryField(String directoryId, String name) { comboBox = new ComboBox(name); comboBox.setWidth("400px"); DirectoryLazyQuery directoryLazyQuery = new DirectoryLazyQuery(directoryId); final LazyQueryContainer container = new LazyQueryContainer(directoryLazyQuery, directoryLazyQuery); container.sort(new String[]{"values"}, new boolean[]{true}); comboBox.setContainerDataSource(container); comboBox.setItemCaptionPropertyId("value"); comboBox.setEnabled(true); comboBox.setRequired(false); comboBox.setImmediate(true); comboBox.setInvalidAllowed(true); comboBox.setInvalidCommitted(false); setImmediate(true); // связать изменение в связном элементе с контейнером comboBox.addListener(new ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { insideListener++; try { Object newValue = event.getProperty().getValue(); if (newValue == null) { setValue(null); } else { setValue(getPropertyByIndex(newValue, "key")); } } finally { insideListener--; } } }); setCompositionRoot(comboBox); } @Override public Class<?> getType() { return Void.class; } @Override public Object getValue() { Object index = comboBox.getValue(); if (index == null) { return null; } return getPropertyByIndex(index, "key"); } public String getValueCaption() { Object index = comboBox.getValue(); if (index == null) { return null; } return (String) getPropertyByIndex(index, "value"); } @Override public void setValue(Object newValue) throws ReadOnlyException, ConversionException { if (insideListener == 0) { if (newValue == null || !setIndexByKey(newValue)) { comboBox.setValue(null); super.setValue(null); } else { super.setValue(newValue); } } else { super.setValue(newValue); } } Object getPropertyByIndex(Object index, String property) { return comboBox.getItem(index).getItemProperty(property).getValue(); } boolean setIndexByKey(Object newValue) { LazyQueryContainer container = (LazyQueryContainer) comboBox.getContainerDataSource(); int size = container.size(); for (int i = 0; i < size; i++) { if ((i % 100) == 0) { container.refresh(); // prevent OOM } Item item = container.getItem(i); if (item == null) { return false; } if (newValue.equals(item.getItemProperty("key").getValue())) { comboBox.setValue(i); return true; } } return false; } @Override public void setRequired(boolean required) { super.setRequired(required); comboBox.setRequired(required); } @Override public void setReadOnly(boolean readOnly) { super.setReadOnly(readOnly); comboBox.setReadOnly(readOnly); } @Override public String getRequiredError() { return comboBox.getRequiredError(); } @Override public void setRequiredError(String requiredMessage) { super.setRequiredError(requiredMessage); comboBox.setRequiredError(requiredMessage); } final static class DirectoryLazyQuery extends LazyQueryDefinition implements QueryFactory, Serializable { private final String dir; /** * Constructor which sets the batch size. */ public DirectoryLazyQuery(String dir) { super(false, 10); this.dir = dir; addProperty("key", String.class, null, true, true); addProperty("value", String.class, null, true, true); } @Override public void setQueryDefinition(QueryDefinition queryDefinition) { } @Override public Query constructQuery(Object[] sortPropertyIds, boolean[] asc) { return new QueryImpl(dir, convertTypes(sortPropertyIds), asc); } private String[] convertTypes(final Object[] objects) { boolean notEmpty = objects != null && objects.length > 0; String[] strings = null; if (notEmpty) { strings = new String[objects.length]; for (int i = 0; i < objects.length; i++) { strings[i] = (String) objects[i]; } } return strings; } } final static class QueryImpl implements Query, Serializable { private static final long serialVersionUID = 1L; final String dir; final String[] ids; final boolean[] asc; public QueryImpl(String dir, String[] ids, boolean[] asc) { this.dir = dir; this.ids = ids; this.asc = asc; } @Override public int size() { return DirectoryBeanProvider.get().getCountValues(dir); } @Override public List<Item> loadItems(final int start, final int count) { final List<Object[]> values = DirectoryBeanProvider.get().getValues(dir, start, count, ids, asc); final List<Item> items = new ArrayList<Item>(values.size()); for (final Object[] s : values) { final PropertysetItem item = new PropertysetItem(); item.addItemProperty("key", new ObjectProperty<String>((String) s[0])); item.addItemProperty("value", new ObjectProperty<String>((String) s[1])); items.add(item); } return items; } @Override public void saveItems(List<Item> addedItems, List<Item> modifiedItems, List<Item> removedItems) { throw new UnsupportedOperationException(); } @Override public boolean deleteAllItems() { throw new UnsupportedOperationException(); } @Override public Item constructItem() { throw new UnsupportedOperationException(); } } }