/**
 *                                                                            
 *  Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) 
 *                                                                            
 *  All rights reserved. This program and the accompanying materials           
 *  are made available under the terms of the Eclipse Public License 2.0        
 *  which accompanies this distribution, and is available at                  
 *  https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 *  SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 *  Contributors:                                                      
 * 	   Florian Pirchner - Initial implementation
 * 
 */
package org.eclipse.osbp.ecview.extension.grid.presentation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveImpl;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.IEmbeddableEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.IFieldEditpart;
import org.eclipse.osbp.ecview.core.common.model.binding.YBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YConverter;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableCollectionEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableMultiSelectionEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableSelectionEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YField;
import org.eclipse.osbp.ecview.core.databinding.emf.model.ECViewModelBindable;
import org.eclipse.osbp.ecview.core.extension.model.extension.YSearchField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YSelectionType;
import org.eclipse.osbp.ecview.core.ui.core.editparts.extension.ISearchFieldEditpart;
import org.eclipse.osbp.ecview.core.util.emf.ModelUtil;
import org.eclipse.osbp.ecview.extension.grid.CxGrid;
import org.eclipse.osbp.ecview.extension.grid.CxGridCellStyleGenerator;
import org.eclipse.osbp.ecview.extension.grid.CxGridColumn;
import org.eclipse.osbp.ecview.extension.grid.CxGridFactory;
import org.eclipse.osbp.ecview.extension.grid.CxGridFooterRow;
import org.eclipse.osbp.ecview.extension.grid.CxGridGroupable;
import org.eclipse.osbp.ecview.extension.grid.CxGridGroupedCell;
import org.eclipse.osbp.ecview.extension.grid.CxGridHeaderRow;
import org.eclipse.osbp.ecview.extension.grid.CxGridMetaCell;
import org.eclipse.osbp.ecview.extension.grid.CxGridPackage;
import org.eclipse.osbp.ecview.extension.grid.CxGridSortable;
import org.eclipse.osbp.ecview.extension.grid.editparts.IGridCellStyleGeneratorEditpart;
import org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart;
import org.eclipse.osbp.ecview.extension.grid.editparts.IGridEditpart;
import org.eclipse.osbp.ecview.extension.grid.editparts.presentation.IGridPresentation;
import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMemento;
import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoColumn;
import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoFactory;
import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoSortable;
import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNestedConverter;
import org.eclipse.osbp.runtime.common.annotations.DtoUtils;
import org.eclipse.osbp.runtime.common.dispose.AbstractDisposable;
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent;
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand;
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherDataTag;
import org.eclipse.osbp.runtime.common.event.IEventDispatcher;
import org.eclipse.osbp.runtime.common.i18n.II18nService;
import org.eclipse.osbp.runtime.common.state.ISharedStateContext;
import org.eclipse.osbp.runtime.designer.api.IDesignerService.IDesignListener;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.IBindingManager;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractEmbeddedWidgetPresenter;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal.util.Util;
import org.eclipse.osbp.runtime.web.vaadin.common.data.BeanServiceLazyLoadingContainer;
import org.eclipse.osbp.runtime.web.vaadin.common.data.DeepResolvingBeanItemContainer;
import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchService;
import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory;
import org.eclipse.osbp.runtime.web.vaadin.common.data.INestedPropertyAble;
import org.eclipse.osbp.runtime.web.vaadin.components.fields.search.ISearchField;
import org.eclipse.osbp.runtime.web.vaadin.databinding.VaadinProperties;
import org.eclipse.osbp.runtime.web.vaadin.databinding.values.IVaadinObservableList;
import org.eclipse.osbp.runtime.web.vaadin.databinding.values.IVaadinObservableValue;
import org.eclipse.osbp.runtime.web.vaadin.databinding.values.SetToListAdapter;
import org.eclipse.osbp.ui.api.user.IUser;
import org.eclipse.osbp.ui.api.useraccess.IUserAccessService;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.Action;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.Group;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.data.Container;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.FieldGroup.CommitEvent;
import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.data.sort.Sort;
import com.vaadin.data.sort.SortOrder;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.filter.And;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.event.SortEvent;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.ui.Component;
import com.vaadin.ui.Field;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.ColumnReorderEvent;
import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent;
import com.vaadin.ui.Grid.FooterRow;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.renderers.Renderer;

/**
 * This presenter is responsible to render a text field on the given layout.
 */
public class GridPresentation extends AbstractEmbeddedWidgetPresenter<Grid> implements IGridPresentation<Grid>, // NOSONAR
		IDesignListener {

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger(GridPresentation.class);

	/** The grid. */
	private CustomGrid grid;

	/** The model access. */
	private ModelAccess modelAccess;

	/** The user changed handler. */
	private UserChangedHandler userChangedHandler = new UserChangedHandler();

	/** The create columns. */
	private boolean createColumns;

	/** The columns. */
	private Set<ColumnWrapper> columns = new HashSet<>();

	/** The grouping headers. */
	private Map<CxGridHeaderRow, HeaderRow> groupingHeaders = new HashMap<>();

	/** The grouping footers. */
	private Map<CxGridFooterRow, FooterRow> groupingFooters = new HashMap<>();

	/** The filtering header. */
	private HeaderRow filteringHeader;

	/** The filtering header fields. */
	private Map<CxGridColumn, ISearchFieldEditpart> filteringHeaderFields = new HashMap<>();

	/** The selection binding. */
	private Binding selectionBinding;

	/** The filter changed tracker. */
	// to handle changed filters
	private WritableValue filterChangedTracker;

	/** The current memento. */
	private CxGridMemento currentMemento;

	/** The cell filters. */
	private GridCellFilter cellFilters;

	/**
	 * The constructor.
	 * 
	 * @param editpart
	 *            The editpart of that editpart.
	 */
	public GridPresentation(IElementEditpart editpart) {
		super((IGridEditpart) editpart);
		this.modelAccess = new ModelAccess((CxGrid) editpart.getModel());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#doUpdateLocale(java.util.Locale)
	 */
	@Override
	protected void doUpdateLocale(Locale locale) {
		// no need to set the locale to the ui elements. Is handled by vaadin
		// internally.

		// update the captions
		applyCaptions();
	}

	/**
	 * Applies the labels to the widgets.
	 */
	protected void applyCaptions() {

		// applies the column properties
		if (createColumns) {
			createColumns();
		}

		Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(), grid);

		grid.setEditorCancelCaption(Util.getCaption(getI18nService(), "Cancel",
				modelAccess.yField.getEditorCancelI18nLabelKey(), getLocale()));
		grid.setEditorSaveCaption(
				Util.getCaption(getI18nService(), "Save", modelAccess.yField.getEditorSaveI18nLabelKey(), getLocale()));

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation.
	 * IGridPresentation#setFilter(java.util.Map)
	 */
	@Override
	public void setFilter(Map<String, Object> filter) {
		List<Container.Filter> filters = new ArrayList<>();
		for (Map.Entry<String, Object> entry : filter.entrySet()) {
			filters.add(new Compare.Equal(entry.getKey(), entry.getValue()));
		}

		Container.Filterable filterable = (Container.Filterable) grid.getContainerDataSource();
		filterable.removeAllContainerFilters();
		filterable.addContainerFilter(new And(filters.toArray(new Container.Filter[filters.size()])));
	}

	/**
	 * Applies the column setting to the grid.
	 */
	protected void createColumns() {

		resetHeader();
		resetFooter();
		
		// reset the column reference in the editparts
		for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) {
			IGridColumnEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxColumn);
			editpart.setColumnReference(null);
		}

		// set the visible columns and icons
		List<String> visibleColumns = new ArrayList<>();
		List<CxGridColumn> visibleColumnObjs = new ArrayList<>();
		Collection<?> propertyIds = grid.getContainerDataSource().getContainerPropertyIds();
		for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) {
			if (!cxColumn.isHidden()
					&& (propertyIds.contains(cxColumn.getPropertyPath()) || isNestedColumn(cxColumn))) {
				visibleColumns.add(cxColumn.getPropertyPath());
				visibleColumnObjs.add(cxColumn);
				if(cxColumn.getLabelI18nKey() == null || cxColumn.getLabelI18nKey().equals("")){
					cxColumn.setLabelI18nKey(cxColumn.getPropertyPath());
				}
				YConverter converter = cxColumn.getConverter();
				if (converter instanceof CxGridNestedConverter) {
					CxGridNestedConverter nestedConverter = (CxGridNestedConverter) converter;
				}
			}
		}

		if (visibleColumns.size() > 0) {
			// reset all columns
			grid.removeAllColumns();
		}

		// add nested properties
		if (grid.getContainerDataSource() instanceof INestedPropertyAble) {
			INestedPropertyAble<?> container = (INestedPropertyAble<?>) grid.getContainerDataSource();
			for (String property : visibleColumns) {
				if (property.contains(".")) {
					container.addNestedContainerProperty(property);
				}
			}
		}

		if (visibleColumns.size() > 0) {
			// create the columns based on the model or the persist at user
			//
			visibleColumns = getColumnOrder(visibleColumns);
			grid.setColumns(visibleColumns.toArray(new Object[visibleColumns.size()]));
			grid.setColumnOrder(visibleColumns.toArray(new Object[visibleColumns.size()]));

			// traverse the columns again and set other properties
			for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) {
				if (!cxColumn.isHidden()
						&& (propertyIds.contains(cxColumn.getPropertyPath()) || isNestedColumn(cxColumn))) {
					String columnId = cxColumn.getPropertyPath();

					IGridColumnEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxColumn);
					Grid.Column column = grid.getColumn(columnId);

					editpart.setColumnReference(new ColumnWrapper(cxColumn, column));
					editpart.initializeColumn();
				}
			}
// #479 TODO (JCD): Not needed anymore. Gridxmi provides now all the columns even when no attribute is defined in the grammar
//		} else {
//			// Previous saved column order
//			List<String> columnOrderUser = getColumnOrderUser();
//			// Column order exists at user properties
//			if ((columnOrderUser != null) && !(columnOrderUser.isEmpty())){
//				try {
//					/* required before the setColumnOrder to equalize this column order with the state column order. 
//					 * Otherwise the column order list will be increased by the state column order list 
//					 * which produce a IllegalArgumentException and therefore a initial column order. */ 
//					removeNotUsedColumns();
//					grid.setColumnOrder(columnOrderUser.toArray());
//				} catch (IllegalArgumentException e) {
//					// In case of an incomplete setting of the column order by the user properties
//					createInitialColumnOrder();
//					/* required after the creation of a initial column order that creates the columns 
//					 * based on all existing field names. */
//					removeNotUsedColumns();
//				}
//			} else {
//			// Otherwise new column order is created based on the filed names
//				createInitialColumnOrder();
//				/* required after the creation of a initial column order that creates the columns 
//				 * based on all existing field names. */
//				removeNotUsedColumns();
//			}
//
		}

		// #479 TODO (JCD): Not needed anymore. Unauthorized columns were managed at the creation of the grid.
//		hideUnauthorizedColumns();

		updateCellStyleGenerator();
		createHeaderMetaCells();
		createFilteringHeader();
		createFooterMetaCells();
		createSortOrder();
	}

	private List<String> getColumnOrder(List<String> visibleColumns) {
		List<String> columnOrderUser = getColumnOrderUser();
		if ( null == columnOrderUser || visibleColumns.size() != columnOrderUser.size()) {
			return visibleColumns;
		}
		boolean unchangedColumns = true;
		for (String columnOrderUserItem : columnOrderUser){
			boolean containsFlag = visibleColumns.contains(columnOrderUserItem);
			unchangedColumns = unchangedColumns && containsFlag;
		}
		if (unchangedColumns) {
			return columnOrderUser;
		}
		return visibleColumns;
	}

	@SuppressWarnings("unchecked")
	private List<String> getColumnOrderUser() {
		IUser user = getViewContext().getService(IUser.class.getName());
		String gridName = modelAccess.yField.getProperties().get("GRIDSOURCE_ID");
		return (List<String>) user.getProperty(gridName);
	}
	
	private void removeNotUsedColumns() {
		// remove not used fields
		for (Grid.Column col : new ArrayList<>(grid.getColumns())) {
			String propId = (String) col.getPropertyId();
			if (!propId.contains(".")) {
				// only check not nested fields
				Class<?> rootType = modelAccess.yField.getType();
				if (DtoUtils.isIdField(rootType, propId) || DtoUtils.isVersionField(rootType, propId)
						|| DtoUtils.isDisposeField(rootType, propId) || DtoUtils.isDirtyField(rootType, propId)) {
					grid.removeColumn(propId);
				}
			}
		}
	}

	// TODO (JCD) delete if it is clear that the gridsource_xmi solution works.
//	private void hideUnauthorizedColumns() {
//		IUserAccessService userAccessService = getViewContext().getService(IUserAccessService.class.getName());
//		Class<?> dtoObjectClass = modelAccess.yField.getType();
//		for (Grid.Column column : new ArrayList<>(grid.getColumns())) {
//			String dtoProperty = (String) column.getPropertyId();
//			columnPermission(userAccessService, dtoObjectClass, column, dtoProperty);
//		}
//	}
//	
//	private void columnPermission(IUserAccessService userAccessService, Class<?> dtoObjectClass, Column column, String dtoProperty) {
//		if (dtoProperty.split("\\.").length > 1) {
//			String refName = dtoProperty.split("\\.")[0];
//			String newDtoProperty = dtoProperty.substring(dtoProperty.indexOf(".") + 1);
//			for (java.lang.reflect.Field ref : DtoUtils.getOwnerDomainReferences(dtoObjectClass)){
//				if (refName.equals(ref.getName())){
//					Class<?> newDtoObjectClass = ref.getType();
//					columnPermission(userAccessService, newDtoObjectClass, column, newDtoProperty);
//					break;
//				}
//			}
//		} else {
//			column.setHidden(false);
//			column.setEditable(false);
//			if (userAccessService == null) {
//				column.setHidden(true);
//			} else {
//				String dtoName = dtoObjectClass.getCanonicalName();
//				boolean dtoGrant = userAccessService.isGranted(Group.DTO, Action.READABLE, dtoName);
//				boolean beanGrant = userAccessService.isGranted(Group.BEAN, Action.READABLE, dtoName);
//				boolean columnHidden = true;
//				boolean columnEditable = false;
//				boolean columnEnabled = false;
//				if (dtoGrant) {
//					columnHidden = userAccessService.isVetoed(Group.DTO, Action.INVISIBLE ,dtoName, dtoProperty);
//					columnEditable = !userAccessService.isVetoed(Group.DTO, Action.NONEDITABLE ,dtoName, dtoProperty);
//					columnEnabled = !userAccessService.isVetoed(Group.DTO, Action.DISABLED ,dtoName, dtoProperty);
//				} else if (beanGrant) {
//					columnHidden = userAccessService.isVetoed(Group.BEAN, Action.INVISIBLE, dtoName, dtoProperty);
//					columnEditable = !userAccessService.isVetoed(Group.BEAN, Action.NONEDITABLE ,dtoName, dtoProperty);
//					columnEnabled = !userAccessService.isVetoed(Group.BEAN, Action.DISABLED ,dtoName, dtoProperty);
//				}
//				if (!columnHidden) {
//					if(column.isEditable()) {
//						// do not set editable true, if editable false
//						column.setEditable(columnEditable && columnEnabled);
//					}
//				} else {
//					if(!column.isHidden()){
//						// do not unhide hidden columns
//						column.setHidden(columnHidden);
//					}
//				}
//
//			}
//		}
//	}
//
	private void createInitialColumnOrder() {
		Class<?> rootType = modelAccess.yField.getType();
		// order columns by field order in rootType
		List<String> fieldNames = DtoUtils.getFieldNames(rootType);
		for (Iterator<String> iterator = fieldNames.iterator(); iterator.hasNext();) {
			String name = iterator.next();
			if (grid.getColumn(name) == null) {
				iterator.remove();
			}
		}
		grid.setColumnOrder(fieldNames.toArray(new Object[fieldNames.size()]));
	}

	/**
	 * Creates the sort order.
	 */
	protected void createSortOrder() {
		CxGrid cxGrid = modelAccess.yField;

		if (cxGrid.getSortOrder().size() > 0) {
			Sort sort = null;
			for (CxGridSortable memSort : cxGrid.getSortOrder()) {
				if (sort == null) {
					sort = Sort.by(memSort.getColumn().getPropertyId(), toDirection(memSort));
				} else {
					sort = sort.then(memSort.getColumn().getPropertyId(), toDirection(memSort));
				}
			}
			grid.sort(sort);
		}
	}

	/**
	 * Creates the header meta cells.
	 */
	protected void createHeaderMetaCells() {

		resetHeader();

		// create the new header
		CxGrid cxGrid = modelAccess.yField;

		for (CxGridHeaderRow cxHeader : cxGrid.getHeaders()) {

			boolean addedCells = false;
			HeaderRow headerRow = grid.prependHeaderRow();
			groupingHeaders.put(cxHeader, headerRow);

			// create the grouping headers
			//
			for (CxGridGroupedCell groupingColumn : cxHeader.getGroupings()) {
				Collection<CxGridGroupable> hiddenColumns = new ArrayList<>();
				for (CxGridGroupable groupable : groupingColumn.getGroupables()){
					if ((groupable instanceof CxGridColumn) && (((CxGridColumn)groupable).isHidden())){
						hiddenColumns.add(groupable);
					}
				}
//				groupingColumn.getGroupables().clear();
				groupingColumn.getGroupables().removeAll(hiddenColumns);
				if (groupingColumn.getGroupables().size() <= 1) {
					continue;
				}
				addedCells = true;

				List<Grid.HeaderCell> headerCells = getCells(headerRow, groupingColumn);
				Grid.HeaderCell cell = headerRow.join(headerCells.toArray(new Grid.HeaderCell[headerCells.size()]));

				// apply the caption of the cell
				String caption = Util.getCaption(getI18nService(), groupingColumn.getLabel(),
						groupingColumn.getLabelI18nKey(), getLocale());

				if (groupingColumn.isUseHTML()) {
					cell.setHtml(caption);
				} else {
					cell.setText(caption);
				}
			}

			if (!addedCells) {
				grid.removeHeaderRow(headerRow);
			}

			// create the custom cells
			//
			for (CxGridMetaCell cxCell : cxHeader.getCustomCells()) {
				Grid.HeaderCell cell = headerRow.getCell(cxCell.getTarget().getPropertyId());
				if (cell == null) {
					continue;
				}

				if (cxCell.getElement() != null) {
					IEmbeddableEditpart ep = ModelUtil.getEditpart(getViewContext(), cxCell.getElement());
					if (ep != null) {
						Component component = (Component) ep.render(null);
						cell.setComponent(component);
					}
				} else {
					String caption = Util.getCaption(getI18nService(), cxCell.getLabel(), cxCell.getLabelI18nKey(),
							getLocale());
					if (cxCell.isUseHTML()) {
						cell.setHtml(caption);
					} else {
						cell.setText(caption);
					}
				}
			}
		}
	}

	/**
	 * Reset header.
	 */
	protected void resetHeader() {
		// reset the old header
		for (int i = 0; i < groupingHeaders.size(); i++) {
			grid.removeHeaderRow(i);
		}
		groupingHeaders.clear();

		// dispose the cell component field
		//
		for (CxGridHeaderRow cxHeader : modelAccess.yField.getHeaders()) {
			for (CxGridMetaCell cxCell : cxHeader.getCustomCells()) {
				if (cxCell.getElement() != null) {
					IEmbeddableEditpart ep = ModelUtil.findEditpart(cxCell.getElement());
					if (ep != null && !ep.isDisposed()) {
						ep.requestDispose();
					}
				}
			}
		}
	}

	/**
	 * Reset filter.
	 */
	protected void resetFilter() {
		// dispose all the rendered search fields
		for (ISearchFieldEditpart ep : filteringHeaderFields.values()) {
			ep.dispose();
		}
		filteringHeaderFields.clear();

		if (cellFilters != null) {
			cellFilters.destroy();
			cellFilters = null;
		} else {
			// reset the old header
			if (filteringHeader != null) {
				grid.removeHeaderRow(filteringHeader);
			}
		}

		filteringHeader = null;
	}

	/**
	 * Creates the filtering header.
	 */
	protected void createFilteringHeader() {

		resetFilter();

		CxGrid cxGrid = modelAccess.yField;
		if (!cxGrid.isFilteringVisible()) {
			return;
		}

		if (cxGrid.isCustomFilters()) {
			createCustomFilters(cxGrid);
		} else {
			createAutoFilters();
		}
	}

	/**
	 * Creates the auto filters.
	 */
	protected void createAutoFilters() {
		cellFilters = new GridCellFilter(grid);
		for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) {
			if (!cxColumn.isHidden()){
				Class<?> propertyType = cxColumn.getType();
	
				String propertyPath = cxColumn.getPropertyPath();
				String filterPropertyPath = cxColumn.getPropertyPath();
				if (cxColumn.isEditsDto()) {
					// if the column edits a dto, its property path points to
					// the dto. Eg. person.country.
					// So we need to use a special path for filtering which
					// points
					// to the domainkey. person.country.isoCode
					filterPropertyPath = cxColumn.getFilterPropertyPathForEditsDto();
				}
				if (Number.class.isAssignableFrom(propertyType) || isPrimitiveNumber(propertyType)) {
					cellFilters.setNumberFilter(propertyPath, filterPropertyPath);
				} else if (propertyType == String.class) {
					cellFilters.setTextFilter(propertyPath, filterPropertyPath, true, false, null);
				} else if (propertyType == Date.class) {
					cellFilters.setDateFilter(propertyPath, filterPropertyPath);
					// otherwise the column is to wide
					if (grid.getColumn(propertyPath)!=null){
						grid.getColumn(propertyPath).setMaximumWidth(175);
					}
				} else if (propertyType == Boolean.class || propertyType == Boolean.TYPE) {
					cellFilters.setBooleanFilter(propertyPath, filterPropertyPath);
				} else if (propertyType.isEnum()) {
					cellFilters.setComboBoxFilter(propertyPath, filterPropertyPath,
							Arrays.asList(propertyType.getEnumConstants()));
				} else if (DtoUtils.getDomainKeyField(propertyType) != null) {
					cellFilters.setDtoFilter(propertyPath, propertyType, "");
				}
			}
		}
	}

	/**
	 * Checks if is primitive number.
	 *
	 * @param propertyType
	 *            the property type
	 * @return true, if is primitive number
	 */
	private boolean isPrimitiveNumber(Class<?> propertyType) {
		return propertyType == Byte.TYPE || propertyType == Double.TYPE || propertyType == Float.TYPE
				|| propertyType == Integer.TYPE || propertyType == Long.TYPE || propertyType == Short.TYPE;
	}

	/**
	 * Creates the custom filters.
	 *
	 * @param cxGrid
	 *            the cx grid
	 */
	protected void createCustomFilters(CxGrid cxGrid) {
		filteringHeader = grid.appendHeaderRow();
		for (CxGridColumn cxColumn : cxGrid.getColumns()) {
			Grid.HeaderCell cell = filteringHeader.getCell(cxColumn.getPropertyId());
			if (cell == null) {
				continue;
			}

			// render the search field
			YSearchField cxSearchField = cxColumn.getSearchField();
			if (cxSearchField != null) {
				ISearchFieldEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxSearchField);
				filteringHeaderFields.put(cxColumn, editpart);
				ISearchField component = (ISearchField) editpart.render(null);
				component.bindFilterChanged(filterChangedTracker);

				cell.setComponent((Component) component);
			}
		}
	}

	/**
	 * Refresh filter.
	 *
	 * @return the object
	 */
	private Object refreshFilter() {
		Set<Container.Filter> filters = new HashSet<>();
		for (ISearchFieldEditpart ep : filteringHeaderFields.values()) {
			Container.Filter f = (Container.Filter) ep.getFilter();
			if (f != null) {
				filters.add(f);
			}
		}

		try {
			Container.Filterable filterable = (Container.Filterable) grid.getContainerDataSource();
			filterable.removeAllContainerFilters();
			filterable.addContainerFilter(new And(filters.toArray(new Container.Filter[filters.size()])));
		} catch (Exception e) {
			LOGGER.error("{}", e);
		}

		return null;
	}

	/**
	 * Creates the footer meta cells.
	 */
	protected void createFooterMetaCells() {

		resetFooter();

		// create the new header
		CxGrid cxGrid = modelAccess.yField;

		for (CxGridFooterRow cxFooter : cxGrid.getFooters()) {
			FooterRow footerRow = grid.appendFooterRow();
			groupingFooters.put(cxFooter, footerRow);
			for (CxGridGroupedCell groupingColumn : cxFooter.getGroupings()) {
				List<Grid.FooterCell> footerCells = getCells(footerRow, groupingColumn);
				Grid.FooterCell cell = footerRow.join(footerCells.toArray(new Grid.FooterCell[footerCells.size()]));

				// apply the caption of the cell
				String caption = Util.getCaption(getI18nService(), groupingColumn.getLabel(),
						groupingColumn.getLabelI18nKey(), getLocale());

				if (groupingColumn.isUseHTML()) {
					cell.setHtml(caption);
				} else {
					cell.setText(caption);
				}
			}

			// create the custom cells
			//
			for (CxGridMetaCell cxCell : cxFooter.getCustomCells()) {
				Grid.FooterCell cell = footerRow.getCell(cxCell.getTarget().getPropertyId());
				if (cell == null) {
					continue;
				}

				if (cxCell.getElement() != null) {
					IEmbeddableEditpart ep = ModelUtil.getEditpart(getViewContext(), cxCell.getElement());
					if (ep != null) {
						Component component = (Component) ep.render(null);
						cell.setComponent(component);
					}
				} else {
					String caption = Util.getCaption(getI18nService(), cxCell.getLabel(), cxCell.getLabelI18nKey(),
							getLocale());
					if (cxCell.isUseHTML()) {
						cell.setHtml(caption);
					} else {
						cell.setText(caption);
					}
				}
			}
		}
	}

	/**
	 * Reset footer.
	 */
	protected void resetFooter() {
		// reset the old header
		for (FooterRow header : groupingFooters.values()) {
			grid.removeFooterRow(header);
		}
		groupingFooters.clear();

		// dispose the cell component field
		//
		for (CxGridFooterRow cxFooter : modelAccess.yField.getFooters()) {
			for (CxGridMetaCell cxCell : cxFooter.getCustomCells()) {
				if (cxCell.getElement() != null) {
					IEmbeddableEditpart ep = ModelUtil.findEditpart(cxCell.getElement());
					if (ep != null && !ep.isDisposed()) {
						ep.requestDispose();
					}
				}
			}
		}
	}

	/**
	 * Gets the cells.
	 *
	 * @param row
	 *            the row
	 * @param groupingColumn
	 *            the grouping column
	 * @return the cells
	 */
	private List<Grid.HeaderCell> getCells(HeaderRow row, CxGridGroupedCell groupingColumn) {
		List<Grid.HeaderCell> cells = new ArrayList<>();
		for (CxGridGroupable column : groupingColumn.getGroupables()) {
			if (column instanceof CxGridColumn) {
				// if it is a column, then use the property id to get the cell
				//
				String id = ((CxGridColumn) column).getPropertyId();
				Grid.HeaderCell cell = row.getCell(id);
				if (cell != null) {
					cells.add(cell);
				}
			} else if (column instanceof CxGridGroupedCell) {
				// if it is a grouped cell, then collect all properties of it
				//
				cells.addAll(getCells(row, (CxGridGroupedCell) column));
			}
		}
		return cells;
	}

	/**
	 * Gets the cells.
	 *
	 * @param row
	 *            the row
	 * @param groupingColumn
	 *            the grouping column
	 * @return the cells
	 */
	private List<Grid.FooterCell> getCells(FooterRow row, CxGridGroupedCell groupingColumn) {
		List<Grid.FooterCell> cells = new ArrayList<>();
		for (CxGridGroupable column : groupingColumn.getGroupables()) {
			if (column instanceof CxGridColumn) {
				// if it is a column, then use the property id to get the cell
				//
				String id = ((CxGridColumn) column).getPropertyId();
				Grid.FooterCell cell = row.getCell(id);
				if (cell != null) {
					cells.add(cell);
				}
			} else if (column instanceof CxGridGroupedCell) {
				// if it is a grouped cell, then collect all properties of it
				//
				cells.addAll(getCells(row, (CxGridGroupedCell) column));
			}
		}
		return cells;
	}

	/**
	 * Checks if is nested column.
	 *
	 * @param cxColumn
	 *            the cx column
	 * @return true, if is nested column
	 */
	protected boolean isNestedColumn(CxGridColumn cxColumn) {
		return cxColumn.getPropertyPath() != null && cxColumn.getPropertyPath().contains(".");
	}

	/**
	 * Returns the column header.
	 *
	 * @param cxColumn
	 *            the cx column
	 * @return the column header
	 */
	private String getColumnHeader(CxGridColumn cxColumn) {
		String result = null;
		II18nService service = getI18nService();
		if (service != null && cxColumn.getLabelI18nKey() != null) {
			result = service.getValue(cxColumn.getLabelI18nKey(), getLocale());
		}

		if (result == null || result.equals("")) {
			result = cxColumn.getLabel();
		}

		if (result == null || result.equals("")) {
			result = cxColumn.getPropertyPath();
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#doCreateWidget(java.lang.Object)
	 */
	@SuppressWarnings({ "unchecked", "rawtypes", "serial" })
	@Override
	public Grid doCreateWidget(Object parent) {
		if (grid == null) {

			// tracks changes in the filters
			filterChangedTracker = new WritableValue();
			filterChangedTracker.addValueChangeListener(e -> refreshFilter());

			CxGrid cxGrid = modelAccess.yField;

			grid = new CustomGrid();
			setupComponent(grid, getCastedModel());

			associateWidget(grid, cxGrid);

			if (modelAccess.isCssIdValid()) {
				grid.setId(modelAccess.getCssID());
			} else {
				grid.setId(getEditpart().getId());
			}

			if (modelAccess.isCssClassValid()) {
				grid.addStyleName(modelAccess.getCssClass());
			} else {
				grid.addStyleName(CSS_CLASS_CONTROL);
			}

			cxGrid.eAdapters().add(new AdapterImpl() {
				@Override
				public void notifyChanged(Notification msg) {
					if (msg.getFeature() == CxGridPackage.Literals.CX_GRID__SELECTION) {
						Class<?> bean = modelAccess.yField.getType();
						if (bean != null) {
							IEventDispatcher eventDispatcher = getViewContext()
									.getService(IEventDispatcher.class.getName());
							if (eventDispatcher == null) {
								return;
							}
							MPerspective perspective = getViewContext().getService(MPerspective.class.getName());
							EventDispatcherEvent evnt = new EventDispatcherEvent(perspective,EventDispatcherCommand.SELECT, bean.getName(), toString());
							if (msg.getNewValue() != null) {
								evnt.addItem(EventDispatcherDataTag.ID, DtoUtils.getIdValue(msg.getNewValue()));
								eventDispatcher.sendEvent(evnt);
							/**
							 * this doesn't work for updates on the dto as grid completely removes content and sends this event with null dto
							 */
//							} else {
//								evnt.addItem(EventDispatcherDataTag.ID, null);
							}
						}
					}
				}
			});

			createColumns = false;
			if (cxGrid.getType() == String.class) {
				IndexedContainer datasource = new IndexedContainer();
				grid.setContainerDataSource(datasource);
			} else {
				if (cxGrid.getType() != null) {
					IBeanSearchService<?> service = null;
					IBeanSearchServiceFactory factory = getViewContext()
							.getService(IBeanSearchServiceFactory.class.getName());
					if (factory != null) {
						service = factory.createService(cxGrid.getType());
					}
					if (cxGrid.isUseBeanService() && service != null) {
						ISharedStateContext sharedState = getViewContext()
								.getService(ISharedStateContext.class.getName());
						IEventDispatcher eventDispatcher = (IEventDispatcher) getViewContext()
								.getService(IEventDispatcher.class.getName());
						BeanServiceLazyLoadingContainer<?> datasource = new BeanServiceLazyLoadingContainer(service,
								cxGrid.getType(), sharedState, eventDispatcher);

						grid.setContainerDataSource(datasource);
					} else {
						DeepResolvingBeanItemContainer datasource = new DeepResolvingBeanItemContainer(
								cxGrid.getType());
						grid.setContainerDataSource(datasource);
					}
					createColumns = true;
				} else {
					IndexedContainer container = new IndexedContainer();
					container.addContainerProperty("for", String.class, null);
					container.addContainerProperty("preview", String.class, null);
					container.addItem(new String[] { "Some value", "other" });
					grid.setContainerDataSource(container);
				}
			}

			// updates the selection type
			updateSelectionType();

			// creates the binding for the field
			createBindings(cxGrid, grid);

			if (modelAccess.isCssClassValid()) {
				grid.addStyleName(modelAccess.getCssClass());
			}

			// notify field about save
			grid.getEditorFieldGroup().addCommitHandler(new FieldGroup.CommitHandler() {
				@Override
				public void preCommit(CommitEvent commitEvent) throws CommitException {

				}

				@Override
				public void postCommit(CommitEvent commitEvent) throws CommitException {
					Object itemId = grid.getEditedItemId();
					modelAccess.yField.setEditorSaved(itemId);
					grid.refreshRows(itemId);
				}
			});
			
			// persists the changed column width into the user properties map
			grid.addColumnResizeListener(new Grid.ColumnResizeListener() {
				
				@Override
		    	public void columnResize(com.vaadin.ui.Grid.ColumnResizeEvent event) {
					
					CxGrid cxGrid = modelAccess.yField;
					String gridName = cxGrid.getProperties().get("GRIDSOURCE_ID");
		    		// Get the new width of the resized column
		    		double width = event.getColumn().getWidth();
		    		
		    		// Get the property ID of the resized column
		    		Object columnId = event.getColumn().getPropertyId();
		    		IUser user = getViewContext().getService(IUser.class.getName());
		    		user.addToProperties(gridName + "." + columnId.toString(), String.valueOf(width));
		    	}
		    });
			
			// persists the changed column width into the user properties map
			grid.addColumnReorderListener(new Grid.ColumnReorderListener() {
				
				@Override
				public void columnReorder(ColumnReorderEvent event) {
					CxGrid cxGrid = modelAccess.yField;
					String gridName = cxGrid.getProperties().get("GRIDSOURCE_ID");
					IUser user = getViewContext().getService(IUser.class.getName());
					List<Column> gridColumns = grid.getColumns();
					List<Object> columnPropertyIds = new ArrayList<>();
					for(Column column : gridColumns){
						Object propertyId = column.getPropertyId();
						columnPropertyIds.add(propertyId);
					}
					user.addToProperties(gridName, columnPropertyIds);
				}
			});
		    // Must be immediate to send the resize events immediately
		    grid.setImmediate(true);
			
			applyCaptions();
			
			// DO NOT MOVE THE FOLLOWING CODE LINES! 
			// The setting of the COLUMN WIDTHS and the COLUMN ORDER from the persisted user properties only works after the call of "applyCaptions()" 
			// due to the possible new creation of the columns in it.
			IUser user = getViewContext().getService(IUser.class.getName());
			String gridName = cxGrid.getProperties().get("GRIDSOURCE_ID");
			// Temporarily deactivate to test memento ########### TODO #############
			// COLUMN WIDTH
			List<Column> gridColumns = grid.getColumns();
			for (Column column : gridColumns) {
				String columnWidthStr = user.getColumnUtil().getColumnWidth(gridName + "." + column.getPropertyId());
				if (columnWidthStr != null){
					column.setWidth(Double.parseDouble(columnWidthStr));
				}
			} 
			// COLUMN ORDER
			Object[] columnOrder = ((List<String>) user.getProperty(gridName)).toArray();
			try {
				grid.setColumnOrder(columnOrder);
			} catch (IllegalArgumentException e) {
				// In case of an incomplete setting of the column order by the user properties
				createInitialColumnOrder();
			}
			removeNotUsedColumns();
			setupUserCallbacks(cxGrid);
		}
		return grid;
	}

	/**
	 * // * Creates a predefined filter for the grid. // * // * @return //
	 */
	// private Filter createFilter() {
	// CxGrid grid = modelAccess.yField;
	// if (grid.getFilters().isEmpty()) {
	// return null;
	// }
	//
	// List<Filter> filters = new ArrayList<>();
	// for (YFilter yFilter : grid.getFilters()) {
	// Filter filter = new Compare.Equal(yFilter.getPropertyPath(),
	// yFilter.getFilterValue());
	// filters.add(filter);
	// }
	// return new And(filters.toArray(new Filter[filters.size()]));
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#castEObject(java.lang.Object)
	 */
	@Override
	protected CxGrid castEObject(Object model) {
		return (CxGrid) super.castEObject(model);
	}

	/**
	 * Creates the bindings.
	 *
	 * @param yGrid
	 *            the y grid
	 * @param widget
	 *            the widget
	 */
	@SuppressWarnings("rawtypes")
	protected void createBindings(CxGrid yGrid, Grid widget) {
		super.createBindings(yGrid, widget, null);

		// bind the editorEnabled property
		IVaadinObservableValue editorEnabledUiObservable = VaadinProperties.accessor(Grid.class, "editorEnabled")
				.observe(widget);
		IObservableValue editorEnabledModelObservable = EMFObservables.observeValue(castEObject(yGrid),
				CxGridPackage.eINSTANCE.getCxGrid_EditorEnabled());
		registerBinding(createBindings(editorEnabledUiObservable, editorEnabledModelObservable));

		// bind the footerVisible property
		IVaadinObservableValue footerVisibleUiObservable = VaadinProperties.accessor(Grid.class, "footerVisible")
				.observe(widget);
		IObservableValue footerVisibleModelObservable = EMFObservables.observeValue(castEObject(yGrid),
				CxGridPackage.eINSTANCE.getCxGrid_FooterVisible());
		registerBinding(createBindings(footerVisibleUiObservable, footerVisibleModelObservable));
		// add a value change listener to update the memento
		footerVisibleModelObservable.addValueChangeListener(e -> {
			if (currentMemento == null || currentMemento.isFooterVisible() != grid.isFooterVisible()) {
				updateMemento();
			}
		});

		// bind the headerVisible property
		IVaadinObservableValue headerVisibleUiObservable = VaadinProperties.accessor(Grid.class, "headerVisible")
				.observe(widget);
		IObservableValue headerVisibleModelObservable = EMFObservables.observeValue(castEObject(yGrid),
				CxGridPackage.eINSTANCE.getCxGrid_HeaderVisible());
		registerBinding(createBindings(headerVisibleUiObservable, headerVisibleModelObservable));
		// add a value change listener to update the memento
		headerVisibleModelObservable.addValueChangeListener(e -> {
			if (currentMemento == null || currentMemento.isHeaderVisible() != grid.isHeaderVisible()) {
				updateMemento();
			}
		});

		// bind the columnReorderingAllowed property
		IVaadinObservableValue columnReorderingAllowedUiObservable = VaadinProperties
				.accessor(Grid.class, "columnReorderingAllowed").observe(widget);
		IObservableValue columnReorderingAllowedModelObservable = EMFObservables.observeValue(castEObject(yGrid),
				CxGridPackage.eINSTANCE.getCxGrid_ColumnReorderingAllowed());
		registerBinding(createBindings(columnReorderingAllowedUiObservable, columnReorderingAllowedModelObservable));

		// bind the editorEnabled property
		IVaadinObservableValue refreshUiObservable = VaadinProperties.accessor(CustomGrid.class, "refresh")
				.observe(widget);
		IObservableValue refreshModelObservable = EMFObservables.observeValue(castEObject(yGrid),
				CxGridPackage.eINSTANCE.getCxGrid_SetLastRefreshTime());
		registerBinding(createBindings(refreshUiObservable, refreshModelObservable));

		if (!modelAccess.yField.isUseBeanService()) {
			// if use bean service, the container is responsible to collect
			// data. So we must not have a binding from the container to the
			// YGrid#collection attribute.
			Container.Indexed container = grid.getContainerDataSource();
			// bind the rows
			registerBinding(createBindings_ContainerContents(castEObject(getModel()),
					CxGridPackage.Literals.CX_GRID__COLLECTION, (Container.ItemSetChangeNotifier) container,
					yGrid.getType()));
		}
		// update the selection binding
		updateSelectionBinding();
	}

	/**
	 * Updates the selection binding for the grid.
	 */
	protected void updateSelectionBinding() {

		CxGrid yGrid = modelAccess.yField;

		if (selectionBinding != null) {
			unregisterBinding(selectionBinding);
			selectionBinding = null;
		}

		// create the model binding from widget to ECView-model
		if (yGrid.getSelectionType() == YSelectionType.MULTI) {
			selectionBinding = createBindingsMultiSelection(castEObject(getModel()),
					CxGridPackage.Literals.CX_GRID__MULTI_SELECTION, grid, yGrid.getType());
			// create the model binding from widget to ECView-model
			registerBinding(selectionBinding);
		} else {
			// create the model binding from widget to ECView-model
			selectionBinding = createBindingsSingleSelection(castEObject(getModel()),
					CxGridPackage.Literals.CX_GRID__SELECTION, grid, yGrid.getType());
			registerBinding(selectionBinding);
		}
	}

	@Override
	public void updateSelectionType() {

		if (modelAccess.yField.getSelectionType() == YSelectionType.MULTI) {
			grid.setSelectionMode(Grid.SelectionMode.MULTI);
		} else {
			grid.setSelectionModel(new CustomSelectionModel());
		}

		updateSelectionBinding();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
	 * getWidget()
	 */
	@Override
	public Grid getWidget() {
		return grid;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
	 * isRendered()
	 */
	@Override
	public boolean isRendered() {
		return grid != null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#internalDispose()
	 */
	@Override
	protected void internalDispose() {
		try {
			unrender();
		} finally {
			super.internalDispose();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#doUnrender()
	 */
	@Override
	public void doUnrender() {
		if (grid != null) {

			// unbind all active bindings
			unbind();

			// remove assocations
			unassociateWidget(grid);

			resetFooter();
			resetHeader();
			resetFilter();

			currentMemento = null;
			grid = null;
		}
	}

	/**
	 * Creates the bindings single selection.
	 *
	 * @param model
	 *            the model
	 * @param modelFeature
	 *            the model feature
	 * @param field
	 *            the field
	 * @param collectionType
	 *            the collection type
	 * @return the binding
	 */
	protected Binding createBindingsSingleSelection(CxGrid model, EStructuralFeature modelFeature, final Grid field,
			Class<?> collectionType) {
		IBindingManager bindingManager = getViewContext()
				.getService(org.eclipse.osbp.ecview.core.common.binding.IECViewBindingManager.class.getName());
		if (bindingManager != null) {
			// bind the value of yText to textRidget
			IObservableValue modelObservable = EMFProperties.value(modelFeature).observe(model);
			IVaadinObservableValue uiObservable = VaadinProperties.propertyGridSelectionValueProperty(collectionType)
					.observe(field);
			final Binding binding = bindingManager.bindValue(uiObservable, modelObservable, null, null);

			return binding;
		}
		return null;
	}

	/**
	 * Creates the bindings multi selection.
	 *
	 * @param model
	 *            the model
	 * @param modelFeature
	 *            the model feature
	 * @param field
	 *            the field
	 * @param collectionType
	 *            the collection type
	 * @return the binding
	 */
	protected Binding createBindingsMultiSelection(CxGrid model, EStructuralFeature modelFeature, final Grid field,
			Class<?> collectionType) {
		IBindingManager bindingManager = getViewContext()
				.getService(org.eclipse.osbp.ecview.core.common.binding.IECViewBindingManager.class.getName());
		if (bindingManager != null) {
			// bind the value of yText to textRidget
			IObservableList modelObservable = EMFProperties.list(modelFeature).observe(model);
			IVaadinObservableList uiObservable = new SetToListAdapter(
					VaadinProperties.propertyGridSelectionSetPropertyAsSet(collectionType).observe(field), field);

			final Binding binding = bindingManager.bindList(uiObservable, modelObservable, null, null);

			return binding;
		}
		return null;
	}

	/**
	 * Is used by the editpart to update the header.
	 */
	@Override
	public void updateHeader() {
		createHeaderMetaCells();
		updateMemento();
	}

	/**
	 * Is used by the editpart to update the footer.
	 */
	@Override
	public void updateFooter() {
		createFooterMetaCells();
		updateMemento();
	}

	/**
	 * Is used by the editpart to update the columns.
	 */
	@Override
	public void updateColumns() {
		createColumns();
		updateMemento();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation.
	 * IGridPresentation#updateFilter()
	 */
	@Override
	public void updateFilter() {
		createFilteringHeader();
		updateMemento();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation.
	 * IGridPresentation#updateCellStyleGenerator()
	 */
	@Override
	public void updateCellStyleGenerator() {
		CxGridCellStyleGenerator cxGenerator = modelAccess.yField.getCellStyleGenerator();
		if (cxGenerator != null) {
			IGridCellStyleGeneratorEditpart ep = ModelUtil.getEditpart(getViewContext(), cxGenerator);
			Grid.CellStyleGenerator generator = (Grid.CellStyleGenerator) ep.getDelegate();
			grid.setCellStyleGenerator(generator);
		} else {
			grid.setCellStyleGenerator(null);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.osbp.runtime.common.memento.IMementoHandler#applyMemento(java
	 * .lang.Object)
	 */
	@Override
	public void applyMemento(Object value) {
		boolean isRendered = isRendered();
		try {
			if (isRendered) {
				// unrender the grid to increase performance
				getEditpart().requestUnrender();
			}

			doApplyMemento(value);
		} finally {
			if (isRendered) {
				// render the grid again
				getEditpart().requestRender();
			}
		}
	}

	/**
	 * Do apply memento.
	 *
	 * @param value
	 *            the value
	 */
	protected void doApplyMemento(Object value) {
		CxGrid cxGrid = modelAccess.yField;

		CxGridMemento cxMemento = (CxGridMemento) value;
		currentMemento = cxMemento;

		// apply the grid properties
		//
		cxGrid.setEditorEnabled(cxMemento.isEditorEnabled());
		cxGrid.setFilteringVisible(cxMemento.isFilterVisible());
		cxGrid.setHeaderVisible(cxMemento.isHeaderVisible());
		cxGrid.setFooterVisible(cxMemento.isFooterVisible());

		// apply the columns to the grid and the setting to each column
		//
		List<CxGridColumn> tempColumns = new ArrayList<>(cxGrid.getColumns());
		List<CxGridColumn> cxOrderedColumns = new ArrayList<>(cxGrid.getColumns().size());
		for (CxGridMementoColumn memColumn : cxMemento.getColumns()) {
			CxGridColumn cxColumn = findCxColumn(memColumn.getPropertyId());
			if (cxColumn != null) {
				// add the columns in the order of the memento
				cxOrderedColumns.add(cxColumn);
				tempColumns.remove(cxColumn);

				cxColumn.setEditable(memColumn.isEditable());
				cxColumn.setHidden(memColumn.isHidden());
				cxColumn.setHideable(memColumn.isHideable());
				cxColumn.setSortable(memColumn.isSortable());
				cxColumn.setExpandRatio(memColumn.getExpandRatio());
				if (memColumn.getWidth() > 0) {
					cxColumn.setWidth(memColumn.getWidth());
				}
			}
		}

		// set all columns that are not in the memento as hidden
		//
		for (CxGridColumn cxColumn : tempColumns) {
			cxColumn.setHideable(true);
			cxColumn.setHidden(true);
		}

		// set the new columns to the grid
		cxGrid.getColumns().clear();
		cxGrid.getColumns().addAll(cxOrderedColumns);

		// update the sortorder
		//
		List<CxGridSortable> cxSortables = new ArrayList<>(cxMemento.getSortOrders().size());
		if (cxMemento.getSortOrders().size() > 0) {
			for (CxGridMementoSortable memSort : cxMemento.getSortOrders()) {

				CxGridColumn cxColumn = findCxColumn(memSort.getColumn().getPropertyId());
				if (cxColumn != null) {
					CxGridSortable cxSortable = CxGridFactory.eINSTANCE.createCxGridSortable();
					cxSortable.setColumn(cxColumn);
					cxSortable.setDescending(memSort.isDescending());
					cxSortables.add(cxSortable);
				}
			}
			cxGrid.getSortOrder().addAll(cxSortables);
		}
	}

	/**
	 * To direction.
	 *
	 * @param cxSortable
	 *            the cx sortable
	 * @return the sort direction
	 */
	private SortDirection toDirection(CxGridSortable cxSortable) {
		return cxSortable.isDescending() ? SortDirection.DESCENDING : SortDirection.ASCENDING;
	}

	/**
	 * Gets the memento.
	 *
	 * @return the memento
	 */
	private Object getMemento() {
		CxGridMemento cxMemento = CxGridMementoFactory.eINSTANCE.createCxGridMemento();

		currentMemento = cxMemento;

		cxMemento.setId(getMementoId());
		cxMemento.setGridId(getCastedModel().getId());
		cxMemento.setEditorEnabled(grid.isEditorEnabled());
		cxMemento.setHeaderVisible(grid.isHeaderVisible());
		cxMemento.setFooterVisible(grid.isFooterVisible());
		cxMemento.setFilterVisible(filteringHeader != null);

		Map<Object, CxGridMementoColumn> tempColumns = new HashMap<>();
		for (Grid.Column column : grid.getColumns()) {
			CxGridMementoColumn cxColumn = CxGridMementoFactory.eINSTANCE.createCxGridMementoColumn();
			cxColumn.setEditable(column.isEditable());
			cxColumn.setExpandRatio(column.getExpandRatio());
			cxColumn.setHideable(column.isHidable());
			cxColumn.setHidden(column.isHidden());
			cxColumn.setSortable(column.isSortable());
			cxColumn.setWidth((int) column.getWidth());
			cxColumn.setPropertyId((String) column.getPropertyId());
			cxMemento.getColumns().add(cxColumn);

			tempColumns.put(cxColumn.getPropertyId(), cxColumn);
		}

		for (SortOrder sortOrder : grid.getSortOrder()) {
			CxGridMementoSortable cxSortable = CxGridMementoFactory.eINSTANCE.createCxGridMementoSortable();
			CxGridMementoColumn cxColumn = tempColumns.get(sortOrder.getPropertyId());
			if (cxColumn == null) {
				LOGGER.warn("Column is not available :" + sortOrder.getPropertyId());
				continue;
			}

			cxSortable.setColumn(cxColumn);
			cxSortable.setDescending(sortOrder.getDirection() == SortDirection.DESCENDING);

			cxMemento.getSortOrders().add(cxSortable);
		}

		return cxMemento;
	}

	/**
	 * Gets the memento id.
	 *
	 * @return the memento id
	 */
	protected String getMementoId() {
		return castEObject(getCastedModel()).getMementoId();
	}

	/**
	 * Handles the memento, if it is enabled by the grid.
	 *
	 * @param cxGrid
	 *            the new up user callbacks
	 */
	protected void setupUserCallbacks(CxGrid cxGrid) {
		// then add listeners to the grid
		//
		grid.addColumnReorderListener(e -> {
			if (e.isUserOriginated()) {
				userChangedHandler.userChangedColumnOrder();
				updateMemento();
			}
		});

		grid.addColumnVisibilityChangeListener(e -> {
			if (e.isUserOriginated()) {
				userChangedHandler.userChangedColumnVisibility(e);
				updateMemento();
			}
		});

		grid.addSortListener(e -> {
			if (e.isUserOriginated()) {
				userChangedHandler.userChangedSortOrder(e);
				updateMemento();
			}
		});
	}

	/**
	 * Find column wrapper.
	 *
	 * @param column
	 *            the column
	 * @return the column wrapper
	 */
	private ColumnWrapper findColumnWrapper(Grid.Column column) {
		return columns.stream().filter(e -> e.column == column).findFirst().orElse(null);
	}

	/**
	 * Find column wrapper.
	 *
	 * @param propertyId
	 *            the property id
	 * @return the column wrapper
	 */
	private ColumnWrapper findColumnWrapper(String propertyId) {
		return columns.stream().filter(e -> e.column.getPropertyId().equals(propertyId)).findFirst().orElse(null);
	}

	/**
	 * Find cx column.
	 *
	 * @param propertyId
	 *            the property id
	 * @return the cx grid column
	 */
	private CxGridColumn findCxColumn(String propertyId) {
		CxGrid cxGrid = modelAccess.yField;
		return cxGrid.getColumns().stream().filter(e -> e.getPropertyId().equals(propertyId)).findFirst().orElse(null);
	}

	/**
	 * Updates the memento.
	 */
	protected void updateMemento() {
		if (modelAccess.yField.isMementoEnabled()) {
			IGridEditpart ep = (IGridEditpart) getEditpart();
			ep.saveMemento(getMemento());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
	 * AbstractVaadinWidgetPresenter#internalGetObservableEndpoint(org.eclipse.
	 * osbp.ecview.core.common.model.core. YEmbeddableBindingEndpoint)
	 */
	@Override
	protected IObservable internalGetObservableEndpoint(YEmbeddableBindingEndpoint bindableValue) {
		if (bindableValue == null) {
			throw new IllegalArgumentException("BindableValue must not be null!");
		}

		if (bindableValue instanceof YEmbeddableCollectionEndpoint) {
			addAutoBindingEndpoint((YBindingEndpoint) bindableValue);
			return internalGetCollectionEndpoint();
		} else if (bindableValue instanceof YEmbeddableSelectionEndpoint) {
			return internalGetSelectionEndpoint((YEmbeddableSelectionEndpoint) bindableValue);
		} else if (bindableValue instanceof YEmbeddableMultiSelectionEndpoint) {
			return internalGetMultiSelectionEndpoint();
		}
		throw new IllegalArgumentException("Not a valid input: " + bindableValue);
	}

	/**
	 * Returns the observable to observe the collection.
	 *
	 * @return the i observable list
	 */
	protected IObservableList internalGetCollectionEndpoint() {
		// return the observable value for text
		return EMFProperties.list(CxGridPackage.Literals.CX_GRID__COLLECTION).observe(getModel());
	}

	/**
	 * Returns the observable to observe the selection.
	 *
	 * @param yEndpoint
	 *            the y endpoint
	 * @return the i observable value
	 */
	@SuppressWarnings("restriction")
	protected IObservableValue internalGetSelectionEndpoint(YEmbeddableSelectionEndpoint yEndpoint) {

		String attributePath = ECViewModelBindable.getAttributePath(CxGridPackage.Literals.CX_GRID__SELECTION,
				yEndpoint.getAttributePath());

		// return the observable value
		return ECViewModelBindable.observeValue(castEObject(getModel()), attributePath, modelAccess.yField.getType(),
				modelAccess.yField.getEmfNsURI());
	}

	/**
	 * Returns the observable to observe the selection.
	 *
	 * @return the i observable list
	 */
	protected IObservableList internalGetMultiSelectionEndpoint() {
		// return the observable value for text
		return EMFProperties.list(CxGridPackage.Literals.CX_GRID__SELECTION).observe(getModel());
	}

	/**
	 * An internal helper class.
	 */
	private static class ModelAccess {

		/** The y field. */
		private final CxGrid yField;

		/**
		 * Instantiates a new model access.
		 *
		 * @param yLayout
		 *            the y layout
		 */
		public ModelAccess(CxGrid yLayout) {
			super();
			this.yField = yLayout;
		}

		/**
		 * Gets the css class.
		 *
		 * @return the css class
		 * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssClass()
		 */
		public String getCssClass() {
			return yField.getCssClass();
		}

		/**
		 * Returns true, if the css class is not null and not empty.
		 *
		 * @return true, if is css class valid
		 */
		public boolean isCssClassValid() {
			return getCssClass() != null && !getCssClass().equals("");
		}

		/**
		 * Gets the css id.
		 *
		 * @return the css id
		 * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssID()
		 */
		public String getCssID() {
			return yField.getCssID();
		}

		/**
		 * Returns true, if the css id is not null and not empty.
		 *
		 * @return true, if is css id valid
		 */
		public boolean isCssIdValid() {
			return getCssID() != null && !getCssID().equals("");
		}

		/**
		 * Returns the label.
		 *
		 * @return the label
		 */
		public String getLabel() {
			return yField.getLabel();
		}

		/**
		 * Returns the label I18n key.
		 *
		 * @return the label i18n key
		 */
		public String getLabelI18nKey() {
			return yField.getLabelI18nKey();
		}
	}

	/**
	 * The Class ColumnWrapper.
	 */
	private class ColumnWrapper extends AbstractDisposable implements IGridColumnEditpart.ColumnReference {

		/** The cx column. */
		private CxGridColumn cxColumn;

		/** The column. */
		private Grid.Column column;

		/**
		 * Instantiates a new column wrapper.
		 *
		 * @param cxColumn
		 *            the cx column
		 * @param column
		 *            the column
		 */
		public ColumnWrapper(CxGridColumn cxColumn, Grid.Column column) {
			super();
			this.cxColumn = cxColumn;
			this.column = column;

			columns.add(this);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart.
		 * ColumnReference#setConverter(java.lang.Object)
		 */
		@Override
		public void setConverter(Object converter) {
			if (converter != null && converter instanceof Converter) {
				column.setConverter((Converter<?, ?>) converter);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart.
		 * ColumnReference#setRenderer(java.lang.Object, java.lang.Object)
		 */
		@SuppressWarnings({ "unchecked", "rawtypes" })
		@Override
		public void setRenderer(Object renderer, Object converter) {
			if (renderer == null) {
				LOGGER.debug("Null renderer not allowed");
				return;
			}
			if (converter == null) {
				column.setRenderer((Renderer) renderer);
			} else {
				column.setRenderer((Renderer) renderer, (Converter) converter);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart.
		 * ColumnReference#updateProperties()
		 */
		@Override
		public void updateProperties() {
			column.setHeaderCaption(getColumnHeader(cxColumn));
			column.setHidden(cxColumn.isHidden());
			column.setHidable(cxColumn.isHideable());
			column.setEditable(cxColumn.isEditable());
			if (cxColumn.getMinWidthPixels() > -1) {
				column.setMinimumWidth(cxColumn.getMinWidthPixels());
			}
			if (cxColumn.getMaxWidthPixels() > 0) {
				column.setMaximumWidth(cxColumn.getMaxWidthPixels());
			}
			if (cxColumn.getWidth() > -1) {
				column.setWidth(cxColumn.getWidth());
			} else {
				column.setWidthUndefined();
			}
			column.setSortable(cxColumn.isSortable());
			if (cxColumn.getExpandRatio() > -1) {
				column.setExpandRatio(cxColumn.getExpandRatio());
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart.
		 * ColumnReference#updateEditorField()
		 */
		@Override
		public void updateEditorField() {
			if (!cxColumn.isEditable()) {
				column.setEditorField(null);
			} else {
				YField cxField = cxColumn.getEditorField();
				Field<?> field = null;
				if (cxField != null) {
					IFieldEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxField);
					field = (Field<?>) editpart.render(null);
					field.setSizeFull();
				}
				column.setEditorField(field);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.osbp.runtime.common.dispose.AbstractDisposable#
		 * internalDispose()
		 */
		@Override
		protected void internalDispose() {

			// remove this column from the cached columns
			columns.remove(this);

			YField cxField = cxColumn.getEditorField();
			if (cxField != null) {
				IFieldEditpart editpart = ModelUtil.findEditpart(cxField);
				if (editpart != null) {
					editpart.dispose();
				}
			}
		}
	}

	/**
	 * The Class UserChangedHandler.
	 */
	private class UserChangedHandler {

		/**
		 * User changed sort order.
		 *
		 * @param e
		 *            the e
		 */
		private void userChangedSortOrder(SortEvent e) {
			List<CxGridSortable> cxSortOrder = new ArrayList<>();
			for (SortOrder sortOrder : e.getSortOrder()) {
				ColumnWrapper wrapper = findColumnWrapper((String) sortOrder.getPropertyId());

				CxGridSortable cxSortable = CxGridFactory.eINSTANCE.createCxGridSortable();
				cxSortOrder.add(cxSortable);
				if (wrapper != null) {
					cxSortable.setColumn(wrapper.cxColumn);
				}
				cxSortable.setDescending(sortOrder.getDirection() == SortDirection.DESCENDING);
			}

			CxGrid cxGrid = modelAccess.yField;
			try {
				cxGrid.eSetDeliver(false);
				modelAccess.yField.getSortOrder().clear();
				modelAccess.yField.getSortOrder().addAll(cxSortOrder);
			} finally {
				cxGrid.eSetDeliver(true);
			}

		}

		/**
		 * User changed column visibility.
		 *
		 * @param e
		 *            the e
		 */
		private void userChangedColumnVisibility(ColumnVisibilityChangeEvent e) {
			Grid.Column affected = e.getColumn();
			ColumnWrapper wrapper = findColumnWrapper(affected);
			if (wrapper == null) {
				LOGGER.warn("No column available for " + affected.getHeaderCaption());
				return;
			}

			CxGrid cxGrid = modelAccess.yField;
			try {
				cxGrid.eSetDeliver(false);
				// update the column in the model
				CxGridColumn cxColumn = wrapper.cxColumn;
				cxColumn.setHidden(e.isHidden());
			} finally {
				cxGrid.eSetDeliver(true);
			}
		}

		/**
		 * User changed column order.
		 */
		private void userChangedColumnOrder() {
			List<CxGridColumn> cxColumns = new ArrayList<>();
			for (Grid.Column column : grid.getColumns()) {
				ColumnWrapper wrapper = findColumnWrapper(column);
				if (wrapper != null) {
					cxColumns.add(wrapper.cxColumn);
				}
			}

			CxGrid cxGrid = modelAccess.yField;
			try {
				cxGrid.eSetDeliver(false);
				cxGrid.getColumns().clear();
				cxGrid.getColumns().addAll(cxColumns);
			} finally {
				cxGrid.eSetDeliver(true);
			}
		}
	}

	/**
	 * The Class CustomTextField.
	 */
	@SuppressWarnings("serial")
	public class CustomGrid extends Grid {

		// only required to be able to create a binding between
		// org.eclipse.osbp.ecview.extension.grid.CxGrid and com.vaadin.ui.Grid
		// to call this method which refresh the grid.
		public long getRefresh() {
			return 0;
		}

		// only required to be able to create a binding between
		// org.eclipse.osbp.ecview.extension.grid.CxGrid and com.vaadin.ui.Grid
		// to call this method which refresh the grid.
		public void setRefresh(long time) {
			List<SortOrder> sort = getSortOrder();
			clearSortOrder();
			setSortOrder(sort);
		}
	}

	@SuppressWarnings("serial")
	public class CustomSelectionModel extends Grid.SingleSelectionModel {
		@Override
		public boolean isSelected(Object itemId) {
			boolean result = super.isSelected(itemId);
			if (!result) {
				Object selectedItemId = getSelectedRow();
				if (selectedItemId != null && itemId != selectedItemId) {
					Object id1 = DtoUtils.getIdValue(itemId);
					Object id2 = DtoUtils.getIdValue(selectedItemId);
					result = Objects.equals(id1, id2);
					if (result) {
						reset();
						select(itemId);
					}
				}
			}
			return result;
		}
	}
}
