catch up with branch development

Signed-off-by: Ralf Mollik <ramollik@compex-commerce.com>
diff --git a/org.eclipse.osbp.infogrid.api/META-INF/MANIFEST.MF b/org.eclipse.osbp.infogrid.api/META-INF/MANIFEST.MF
index ffaa86f..d40a72d 100644
--- a/org.eclipse.osbp.infogrid.api/META-INF/MANIFEST.MF
+++ b/org.eclipse.osbp.infogrid.api/META-INF/MANIFEST.MF
@@ -10,9 +10,11 @@
  org.eclipse.osbp.ecview.extension.grid.model;bundle-version="[0.9.0,0.10.0)",
  org.eclipse.osbp.ecview.extension.model;bundle-version="[0.9.0,0.10.0)",
  org.eclipse.core.databinding.beans;bundle-version="[1.3.100,1.4.0)",
- org.eclipse.core.databinding.property;bundle-version="[1.6.0,1.7.0)"
+ org.eclipse.core.databinding.property;bundle-version="[1.6.0,1.7.0)",
+ org.eclipse.osbp.dsl.datatype.lib;bundle-version="0.9.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.eclipse.osbp.infogrid.api;version="0.9.0"
-Import-Package: org.osgi.service.component.annotations,
+Import-Package: org.apache.commons.lang3;version="3.4.0",
+ org.osgi.service.component.annotations,
  org.slf4j;version="1.7.2"
 Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/ECViewGridEditorFieldFactory.java b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/ECViewGridEditorFieldFactory.java
index 01f7e99..24d5d69 100644
--- a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/ECViewGridEditorFieldFactory.java
+++ b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/ECViewGridEditorFieldFactory.java
@@ -10,25 +10,49 @@
  * Contributors:   
  * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
  */
- package org.eclipse.osbp.infogrid.api;
+package org.eclipse.osbp.infogrid.api;
 
+import java.lang.reflect.Field;
 import java.util.Date;
 
+import org.eclipse.osbp.dsl.common.datatypes.IDto;
 import org.eclipse.osbp.ecview.core.common.model.core.YField;
 import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelFactory;
+import org.eclipse.osbp.ecview.core.extension.model.extension.YComboBox;
 import org.eclipse.osbp.infogrid.model.gridsource.CxGridProperty;
+import org.eclipse.osbp.runtime.common.annotations.DtoUtils;
 
-public class ECViewGridEditorFieldFactory implements
-		IECViewGridEditorFieldFactory {
+public class ECViewGridEditorFieldFactory implements IECViewGridEditorFieldFactory {
 
 	private ExtensionModelFactory factory = ExtensionModelFactory.eINSTANCE;
 
 	@Override
-	public YField createEditorField(CxGridProperty prop, Class<?> propertyType) {
+	public YField createEditorField(CxGridProperty prop, Class<?> propertyType, Class<?> rootType) {
+
+		if (GridUtil.isNestedAndBindsDto(rootType, prop)) {
+			// nested field
+			Class<?> nestedType = GridUtil.getDtoType(rootType, prop);
+			// if the first type in the dot path is a dto, we use a combo for
+			// editing
+			if (IDto.class.isAssignableFrom(nestedType)) {
+				YComboBox combo = factory.createYComboBox();
+				combo.setType(nestedType);
+				combo.setTypeQualifiedName(nestedType.getName());
+				combo.setUseBeanService(true);
+
+				Field dkField = DtoUtils.getDomainKeyField(nestedType);
+				if (dkField != null) {
+					combo.setCaptionProperty(dkField.getName());
+					return combo;
+				}
+				// combo will be there, but toString is shown as caption
+				return combo;
+			}
+		}
+
 		if (propertyType == String.class) {
 			return factory.createYTextField();
-		} else if (propertyType == Integer.class
-				|| propertyType == Integer.TYPE) {
+		} else if (propertyType == Integer.class || propertyType == Integer.TYPE) {
 			return factory.createYNumericField();
 		} else if (propertyType == Short.class || propertyType == Short.TYPE) {
 			return factory.createYNumericField();
@@ -40,11 +64,9 @@
 			return factory.createYDecimalField();
 		} else if (propertyType == Long.class || propertyType == Long.TYPE) {
 			return factory.createYNumericField();
-		} else if (propertyType == Character.class
-				|| propertyType == Character.TYPE) {
+		} else if (propertyType == Character.class || propertyType == Character.TYPE) {
 			return factory.createYTextField();
-		} else if (propertyType == Boolean.class
-				|| propertyType == Boolean.TYPE) {
+		} else if (propertyType == Boolean.class || propertyType == Boolean.TYPE) {
 			return factory.createYCheckBox();
 		} else if (propertyType == Date.class) {
 			return factory.createYDateTime();
diff --git a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/GridUtil.java b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/GridUtil.java
new file mode 100644
index 0000000..9bcb179
--- /dev/null
+++ b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/GridUtil.java
@@ -0,0 +1,194 @@
+package org.eclipse.osbp.infogrid.api;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.osbp.dsl.common.datatypes.IDto;
+import org.eclipse.osbp.infogrid.model.gridsource.CxGridProperty;
+import org.eclipse.osbp.runtime.common.annotations.DtoUtils;
+import org.eclipse.osbp.runtime.common.util.BeanUtils;
+
+public class GridUtil {
+
+	public static boolean isNested(Class<?> rootType, CxGridProperty prop) {
+		return prop.getDotPath() != null && prop.getDotPath().contains(".") || isBindsRawDto(rootType, prop);
+	}
+
+	public static boolean isNestedAndBindsDto(Class<?> rootType, CxGridProperty prop) {
+		if (!isNested(rootType, prop)) {
+			return false;
+		}
+
+		if (prop.getDotPath().contains(".")) {
+			// nested field
+			String[] tokens = prop.getDotPath().split("\\.");
+			Class<?> nestedType = BeanProperties.value(rootType, tokens[0]).getPropertyDescriptor().getPropertyType();
+
+			// if the first type in the dot path is a dto, we use a combo for
+			// editing
+			if (IDto.class.isAssignableFrom(nestedType)) {
+				return true;
+			}
+		} else {
+			return isBindsRawDto(rootType, prop);
+		}
+		return false;
+	}
+
+	/**
+	 * Is used to create groups in the grid. A group is defined by the first dto
+	 * in the binding path.<br>
+	 * Eg: <br>
+	 * <ul>
+	 * <li>person.<b>country</b> --> "country"</li>
+	 * <li>person.<b>country</b>.isoCode --> "country"</li>
+	 * <li>person.<b>country</b>.continent --> "country"</li>
+	 * <li>person.<b>country</b>.continent.name --> "country"</li>
+	 * </ul>
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static String getGroup(Class<?> rootType, CxGridProperty prop) {
+		if (!isNested(rootType, prop)) {
+			return "Main";
+		}
+
+		Class<?> dtoType = getDtoType(rootType, prop);
+		return dtoType.getSimpleName() ;
+	}
+
+	/**
+	 * Returns true, if the path or dot path points to a dto.<br>
+	 * Eg: person.country<br>
+	 * In this case the domainKey property will be attached to the dto path
+	 * later. <code>person.country --> person.country.isoCode</code>
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static boolean isBindsRawDto(Class<?> rootType, CxGridProperty prop) {
+
+		Class<?> type = BeanUtils.getNestedFieldType(rootType, prop.getDotPath());
+		// if the first type in the dot path is a dto, we use a combo for
+		// editing
+		if (IDto.class.isAssignableFrom(type)) {
+			return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Returns the dto type, if the path or dot path points to a dto.<br>
+	 * Eg: person.country.continent -> continent is returned<br>
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static Class<?> getBindsRawDtoType(Class<?> rootType, CxGridProperty prop) {
+		if (!isBindsRawDto(rootType, prop)) {
+			throw new IllegalArgumentException("Not a valid call");
+		}
+		Class<?> type = BeanUtils.getNestedFieldType(rootType, prop.getDotPath());
+		return type;
+	}
+
+	/**
+	 * Returns true, if the path or dot path points to a dto.<br>
+	 * Eg: person.country<br>
+	 * In this case the domainKey property will be attached to the dto path
+	 * later. <code>person.country --> person.country.isoCode</code>
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static boolean isBindsDomainKey(Class<?> rootType, CxGridProperty prop) {
+		if (isBindsRawDto(rootType, prop)) {
+			return false;
+		}
+		Field field = BeanUtils.getNestedField(rootType, prop.getDotPath());
+		String propName = field.getName();
+
+		Class<?> type = field.getDeclaringClass();
+		return DtoUtils.isDomainkeyField(type, propName);
+	}
+
+	/**
+	 * Returns the path which binds the dto. It is used to create a column for
+	 * the dto in the grid.<br>
+	 * Eg:<br>
+	 * Full path: country.continent.name<br>
+	 * Dto path: country --> Since country binds the country dto. The tail path
+	 * will be continent.name and is used to point the nested converter to the
+	 * target property inside the country. country will be added as a column to
+	 * the grid.
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static String getDtoBindingPath(Class<?> rootType, CxGridProperty prop) {
+		if (!isNestedAndBindsDto(rootType, prop)) {
+			return prop.getDotPath();
+		}
+
+		String[] tokens = prop.getDotPath().split("\\.");
+		return tokens[0];
+	}
+
+	/**
+	 * Returns the tail dot path used to point the NestedConverter to its
+	 * property inside the dto.<br>
+	 * Eg:<br>
+	 * Full path: country.continent.name<br>
+	 * Tail path: continent.name --> Since country binds the country dto. So
+	 * country will be added as a column to the grid.
+	 * 
+	 * @param rootType
+	 * @param prop
+	 * @return
+	 */
+	public static String getNestedConverterTailDotPath(Class<?> rootType, CxGridProperty prop) {
+		if (!isNestedAndBindsDto(rootType, prop)) {
+			return prop.getDotPath();
+		}
+
+		String[] tokens = prop.getDotPath().split("\\.");
+		if (tokens.length == 1) {
+			return "";
+		}
+		StringBuilder b = new StringBuilder();
+		for (int i = 1; i < tokens.length; i++) {
+			if (b.length() != 0) {
+				b.append(".");
+			}
+			b.append(tokens[i]);
+		}
+		return b.toString();
+	}
+
+	public static Class<?> getDtoType(Class<?> rootType, CxGridProperty prop) {
+		return BeanProperties.value(rootType, getDtoBindingPath(rootType, prop)).getPropertyDescriptor()
+				.getPropertyType();
+	}
+	
+	public static Class<?> getPropertyType(Class<?> rootType, CxGridProperty prop) {
+		return BeanProperties.value(rootType, prop.getDotPath()).getPropertyDescriptor()
+				.getPropertyType();
+	}
+
+	public static String getDomainKeyName(Class<?> rootType, CxGridProperty prop) {
+		if (!isBindsRawDto(rootType, prop)) {
+			throw new IllegalStateException("Only dtos have domainkeys");
+		}
+		
+		Class<?> type = getBindsRawDtoType(rootType, prop);
+		return DtoUtils.getDomainKeyField(type).getName();
+	}
+
+}
diff --git a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/IECViewGridEditorFieldFactory.java b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/IECViewGridEditorFieldFactory.java
index 0266703..f9b8edd 100644
--- a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/IECViewGridEditorFieldFactory.java
+++ b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/IECViewGridEditorFieldFactory.java
@@ -31,8 +31,9 @@
 	 * 
 	 * @param prop
 	 * @param propertyType
+	 * @param rootType 
 	 * @return
 	 */
-	YField createEditorField(CxGridProperty prop, Class<?> propertyType);
+	YField createEditorField(CxGridProperty prop, Class<?> propertyType, Class<?> rootType);
 
 }
diff --git a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/SingleECViewGridFactory.java b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/SingleECViewGridFactory.java
index 52ce909..33d4981 100644
--- a/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/SingleECViewGridFactory.java
+++ b/org.eclipse.osbp.infogrid.api/src/org/eclipse/osbp/infogrid/api/SingleECViewGridFactory.java
@@ -10,11 +10,17 @@
  * Contributors:   
  * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
  */
- package org.eclipse.osbp.infogrid.api;
+package org.eclipse.osbp.infogrid.api;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.ClassUtils;
 import org.eclipse.core.databinding.beans.BeanProperties;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EClass;
@@ -24,10 +30,13 @@
 import org.eclipse.osbp.ecview.extension.grid.CxGrid;
 import org.eclipse.osbp.ecview.extension.grid.CxGridColumn;
 import org.eclipse.osbp.ecview.extension.grid.CxGridFactory;
+import org.eclipse.osbp.ecview.extension.grid.CxGridGroupedCell;
+import org.eclipse.osbp.ecview.extension.grid.CxGridHeaderRow;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridButtonRenderer;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridDateRenderer;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridImageRenderer;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridIndicatorRenderer;
+import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNestedConverter;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNumberRenderer;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridPriceRenderer;
 import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridProgressBarRenderer;
@@ -65,8 +74,7 @@
 
 public class SingleECViewGridFactory implements IECViewGridFactory {
 
-	private static final Logger LOGGER = LoggerFactory
-			.getLogger(SingleECViewGridFactory.class);
+	private static final Logger LOGGER = LoggerFactory.getLogger(SingleECViewGridFactory.class);
 
 	private CxGridFactory gridFactory = CxGridFactory.eINSTANCE;
 
@@ -80,10 +88,8 @@
 	@Override
 	public CxGrid createGrid(Class<?> inputType, CxGridSource gridSource) {
 
-		BundleContext bc = FrameworkUtil.getBundle(getClass())
-				.getBundleContext();
-		ServiceReference<IBundleSpace> bsRef = bc
-				.getServiceReference(IBundleSpace.class);
+		BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+		ServiceReference<IBundleSpace> bsRef = bc.getServiceReference(IBundleSpace.class);
 		if (bsRef == null) {
 			LOGGER.error("No BundleSpace available.");
 			return gridFactory.createCxGrid();
@@ -94,10 +100,8 @@
 		try {
 			rootType = bundleSpace.forName(gridSource.getRootTypeFQN());
 		} catch (ClassNotFoundException e) {
-			e.printStackTrace();
+			LOGGER.error("{}", e);
 		}
-		// TODO: check the case "rootType == null". Maybe use a default rootType
-		// to continue ...
 
 		bc.ungetService(bsRef);
 
@@ -115,21 +119,157 @@
 			grid.setType(rootType);
 			grid.setTypeQualifiedName(rootType.getName());
 
-			for (CxGridProperty prop : gridSource.getProperties()) {
-				CxGridColumn column = gridFactory.createCxGridColumn();
-				column.setPropertyPath(prop.getDotPath());
-				column.setPropertyId(prop.getDotPath());
+			List<Info> temp = new ArrayList<>(gridSource.getProperties().size());
 
-				Class<?> propertyType = BeanProperties
-						.value(rootType, prop.getDotPath())
-						.getPropertyDescriptor().getPropertyType();
+			// create the basic infos. In further steps we will group them and
+			// calculate editable states.
+			//
+			for (CxGridProperty prop : gridSource.getProperties()) {
+
+				Info info = new Info();
+				info.prop = prop;
+				temp.add(info);
+
+				if (GridUtil.isNested(rootType, prop)) {
+					info.group = GridUtil.getGroup(rootType, prop);
+					info.firstNestedDtoType = GridUtil.getDtoType(rootType, prop);
+					info.nested = true;
+					boolean bindsRawDto = GridUtil.isBindsRawDto(rootType, prop);
+					info.rawDtoRef = bindsRawDto;
+					if (bindsRawDto) {
+						info.fullDotPath = prop.getDotPath() + "." + GridUtil.getDomainKeyName(rootType, prop);
+						info.prop.setDotPath(info.fullDotPath);
+						info.domainkey = true;
+						// ATTENTION: Here we need to use the dto type, since
+						// this type is bound to the grid column
+						info.type = GridUtil.getPropertyType(rootType, prop);
+					} else {
+						info.fullDotPath = prop.getDotPath();
+						info.domainkey = GridUtil.isBindsDomainKey(rootType, prop);
+
+						info.type = GridUtil.getPropertyType(rootType, prop);
+					}
+				} else {
+					info.group = "";
+					info.fullDotPath = prop.getDotPath();
+					info.type = GridUtil.getPropertyType(rootType, prop);
+				}
+			}
+
+			// filter double entries and create a map for groupings
+			//
+			Map<String, List<Info>> infoGroup = new HashMap<>();
+			List<Info> infos = new ArrayList<>(gridSource.getProperties().size());
+			Set<String> dotPath = new HashSet<>();
+			for (Info info : temp) {
+				if (dotPath.contains(info.fullDotPath)) {
+					continue;
+				}
+
+				if (!infoGroup.containsKey(info.group)) {
+					infoGroup.put(info.group, new ArrayList<>());
+				}
+
+				List<Info> list = infoGroup.get(info.group);
+				list.add(info);
+
+				dotPath.add(info.fullDotPath);
+				infos.add(info);
+			}
+
+			// check which info is editable. Only one per group is editable.
+			// Preferred the domainkey property
+			for (Map.Entry<String, List<Info>> entry : infoGroup.entrySet()) {
+				boolean domainkeyFound = false;
+				for (Info info : entry.getValue()) {
+
+					if (info.group.equals("")) {
+						// the root group is always editable according its
+						// property
+						info.editable = info.prop.isEditable();
+						continue;
+					}
+
+					if (info.domainkey) {
+						info.editable = true;
+						domainkeyFound = true;
+						break;
+					}
+				}
+				if (!domainkeyFound) {
+					entry.getValue().get(0).editable = true;
+				}
+			}
+
+			// create a header row for the grouped columns
+			//
+			temp = new ArrayList<>(infos);
+			infos.clear();
+			CxGridHeaderRow groupingRow = CxGridFactory.eINSTANCE.createCxGridHeaderRow();
+			grid.getHeaders().add(groupingRow);
+
+			for (String group : infoGroup.keySet()) {
+				CxGridGroupedCell groupedCell = CxGridFactory.eINSTANCE.createCxGridGroupedCell();
+				groupedCell.setId(group + "Group");
+				groupedCell.setName(group + "Group");
+				groupedCell.setLabelI18nKey(group);
+				groupingRow.getGroupings().add(groupedCell);
+
+				// find grouped infos
+				List<Info> groupedCells = temp.stream().filter(info -> info.group.equals(group))
+						.collect(Collectors.toList());
+
+				// and apply the cxGridGroup
+				groupedCells.stream().forEach(info -> info.cxGridGroup = groupedCell);
+
+				infos.addAll(groupedCells);
+			}
+
+			for (Info info : infos) {
+				CxGridProperty prop = info.prop;
+				CxGridColumn column = gridFactory.createCxGridColumn();
+				column.setType(info.type);
+				column.setTypeQualifiedName(info.type.getName());
+
+				if (info.cxGridGroup != null) {
+					info.cxGridGroup.getGroupables().add(column);
+				}
+
+				if (info.editable) {
+					// we create the column based on the dto and use the
+					// converter to convert to the target property inside the
+					// dto
+					column.setPropertyPath(GridUtil.getDtoBindingPath(rootType, prop));
+				} else {
+					// otherwise we create the column with the fully dto path
+					column.setPropertyPath(prop.getDotPath());
+				}
+				column.setPropertyId(column.getPropertyPath());
+
+				column.setLabelI18nKey(prop.getDotPath());
+
+				Class<?> propertyType = BeanProperties.value(rootType, prop.getDotPath()).getPropertyDescriptor()
+						.getPropertyType();
 
 				// editable
-				YField yEditorField = getEditorField(prop, propertyType);
-				column.setEditable(yEditorField != null);
-				column.setEditorField(yEditorField);
+				if (info.editable) {
+					YField yEditorField = getEditorField(prop, propertyType, rootType);
+					column.setEditable(yEditorField != null);
+					column.setEditorField(yEditorField);
 
-				Pair pair = createRendererPair(prop, propertyType);
+					if (info.nested) {
+						// only one nested property is editable. So it needs to
+						// edit the dto by combobox and requires a different
+						// filterPropertyPath.
+						// The bindings property path points directly to the dto
+						column.setEditsDto(true);
+						column.setFilterPropertyPathForEditsDto(info.fullDotPath);
+					}
+				} else {
+					column.setEditable(false);
+				}
+
+				Pair pair = createRendererPair(rootType, prop, propertyType, info);
 				column.setRenderer(pair.renderer);
 				column.setConverter(pair.converter);
 				// column.setMaxWidthPixels(50);
@@ -154,10 +294,11 @@
 	 * 
 	 * @param prop
 	 * @param propertyType
+	 * @param rootType
 	 * @return
 	 */
-	protected YField getEditorField(CxGridProperty prop, Class<?> propertyType) {
-		return editorFieldFactory.createEditorField(prop, propertyType);
+	protected YField getEditorField(CxGridProperty prop, Class<?> propertyType, Class<?> rootType) {
+		return editorFieldFactory.createEditorField(prop, propertyType, rootType);
 	}
 
 	protected boolean isEditable(CxGridSource gridSource) {
@@ -174,12 +315,12 @@
 	 * 
 	 * @param prop
 	 * @param propertyType
+	 * @param editable
 	 * @return
 	 */
-	protected Pair createRendererPair(CxGridProperty prop, Class<?> propertyType) {
+	protected Pair createRendererPair(Class<?> rootType, CxGridProperty prop, Class<?> propertyType, Info info) {
 
 		Pair pair = new Pair();
-
 		CxGridRendererFactory factory = CxGridRendererFactory.eINSTANCE;
 		if (prop.getStyle() == null) {
 			return createBadRenderer();
@@ -201,19 +342,15 @@
 			if (!isNumeric(propertyType)) {
 				return createBadRenderer();
 			}
-			CxGridPropNumberStyle style = (CxGridPropNumberStyle) prop
-					.getStyle();
-			CxGridNumberRenderer renderer = factory
-					.createCxGridNumberRenderer();
+			CxGridPropNumberStyle style = (CxGridPropNumberStyle) prop.getStyle();
+			CxGridNumberRenderer renderer = factory.createCxGridNumberRenderer();
 			renderer.setNumberFormat(style.getNumberFormat());
 			pair.renderer = renderer;
 		}
 			break;
 		case CxGridStylePackage.CX_GRID_PROP_BUTTON_STYLE: {
-			CxGridPropButtonStyle style = (CxGridPropButtonStyle) prop
-					.getStyle();
-			CxGridButtonRenderer renderer = factory
-					.createCxGridButtonRenderer();
+			CxGridPropButtonStyle style = (CxGridPropButtonStyle) prop.getStyle();
+			CxGridButtonRenderer renderer = factory.createCxGridButtonRenderer();
 			renderer.setEventTopic(style.getEventTopic());
 			pair.renderer = renderer;
 		}
@@ -231,19 +368,15 @@
 			pair.renderer = factory.createCxGridHtmlRenderer();
 			break;
 		case CxGridStylePackage.CX_GRID_PROP_PROGRESSBAR_STYLE: {
-			CxGridPropProgressbarStyle style = (CxGridPropProgressbarStyle) prop
-					.getStyle();
-			CxGridProgressBarRenderer renderer = factory
-					.createCxGridProgressBarRenderer();
+			CxGridPropProgressbarStyle style = (CxGridPropProgressbarStyle) prop.getStyle();
+			CxGridProgressBarRenderer renderer = factory.createCxGridProgressBarRenderer();
 			renderer.setMaxValue(style.getMaxValue());
 			pair.renderer = renderer;
 		}
 			break;
 		case CxGridStylePackage.CX_GRID_PROP_INDICATOR_STYLE: {
-			CxGridPropIndicatorStyle style = (CxGridPropIndicatorStyle) prop
-					.getStyle();
-			CxGridIndicatorRenderer renderer = factory
-					.createCxGridIndicatorRenderer();
+			CxGridPropIndicatorStyle style = (CxGridPropIndicatorStyle) prop.getStyle();
+			CxGridIndicatorRenderer renderer = factory.createCxGridIndicatorRenderer();
 			renderer.setGreenStarts(style.getGreenStarts());
 			renderer.setRedEnds(style.getRedEnds());
 			pair.renderer = renderer;
@@ -256,10 +389,8 @@
 			pair.renderer = factory.createCxGridHtmlRenderer();
 			break;
 		case CxGridStylePackage.CX_GRID_PROP_QUANTITY_STYLE: {
-			CxGridPropQuantityStyle style = (CxGridPropQuantityStyle) prop
-					.getStyle();
-			CxGridQuantityRenderer renderer = factory
-					.createCxGridQuantityRenderer();
+			CxGridPropQuantityStyle style = (CxGridPropQuantityStyle) prop.getStyle();
+			CxGridQuantityRenderer renderer = factory.createCxGridQuantityRenderer();
 			renderer.setHtmlPattern(style.getHtmlPattern());
 			renderer.setNullRepresentation("");
 			renderer.setNumberFormat(style.getValueNumberFormat());
@@ -281,14 +412,38 @@
 			break;
 		}
 
+		if (info.nested && info.editable) {
+			CxGridNestedConverter nestedConverter = CxGridRendererFactory.eINSTANCE.createCxGridNestedConverter();
+			Class<?> dtoType = GridUtil.getDtoType(rootType, prop);
+			nestedConverter.setBaseType(dtoType);
+			nestedConverter.setBaseTypeQualifiedName(dtoType.getName());
+
+			if (propertyType.isPrimitive()) {
+				propertyType = ClassUtils.primitiveToWrapper(propertyType);
+			}
+			nestedConverter.setNestedType(propertyType);
+			nestedConverter.setNestedTypeQualifiedName(propertyType.getName());
+
+			// we create the column based on the dto and use the
+			// converter to point to the target property inside the dto
+			String nestedConverterTailPath = GridUtil.getNestedConverterTailDotPath(rootType, prop);
+			nestedConverter.setNestedDotPath(nestedConverterTailPath);
+
+			// the nestedConverter needs to use the nested type converter to
+			// convert to the presentation. Eg, the nestedConverter extracts
+			// birthdate from Person and the nestedTypeConverter does pretty
+			// formatting of date
+			nestedConverter.setNestedTypeConverter(pair.converter);
+			pair.converter = nestedConverter;
+		}
+
 		return pair;
 	}
 
 	protected boolean isNumeric(Class<?> propertyType) {
 		boolean result = Number.class.isAssignableFrom(propertyType);
 		if (!result) {
-			if (propertyType.isPrimitive() && propertyType != Boolean.TYPE
-					&& propertyType != Void.TYPE) {
+			if (propertyType.isPrimitive() && propertyType != Boolean.TYPE && propertyType != Void.TYPE) {
 				result = true;
 			}
 		}
@@ -303,14 +458,12 @@
 		CxGridStyleConfig cxConfig = configs.get(0);
 		if (cxConfig instanceof CxGridStyleConfigStringToResource) {
 			List<YStringToResourceConfig> newConfigs = toStringToResourceConfig(configs);
-			YStringToResourceConverter converter = YConverterFactory.eINSTANCE
-					.createYStringToResourceConverter();
+			YStringToResourceConverter converter = YConverterFactory.eINSTANCE.createYStringToResourceConverter();
 			converter.getConfigs().addAll(newConfigs);
 			return converter;
 		} else if (cxConfig instanceof CxGridStyleConfigNumericToResource) {
 			List<YNumericToResourceConfig> newConfigs = toNumberToResourceConfig(configs);
-			YNumericToResourceConverter converter = YConverterFactory.eINSTANCE
-					.createYNumericToResourceConverter();
+			YNumericToResourceConverter converter = YConverterFactory.eINSTANCE.createYNumericToResourceConverter();
 			converter.getConfigs().addAll(newConfigs);
 			return converter;
 		}
@@ -318,8 +471,7 @@
 		return null;
 	}
 
-	private List<YNumericToResourceConfig> toNumberToResourceConfig(
-			EList<CxGridStyleConfig> configs) {
+	private List<YNumericToResourceConfig> toNumberToResourceConfig(EList<CxGridStyleConfig> configs) {
 		List<YNumericToResourceConfig> result = new ArrayList<>(configs.size());
 		for (CxGridStyleConfig config : configs) {
 			if (!(config instanceof CxGridStyleConfigNumericToResource)) {
@@ -328,8 +480,7 @@
 			}
 
 			CxGridStyleConfigNumericToResource givenConfig = (CxGridStyleConfigNumericToResource) config;
-			YNumericToResourceConfig newConfig = YConverterFactory.eINSTANCE
-					.createYNumericToResourceConfig();
+			YNumericToResourceConfig newConfig = YConverterFactory.eINSTANCE.createYNumericToResourceConfig();
 			newConfig.setResourceThemePath(givenConfig.getResourceThemePath());
 			newConfig.setValue(givenConfig.getValue());
 			newConfig.setCompare(toGridCompare(givenConfig.getCompare()));
@@ -357,8 +508,7 @@
 		return null;
 	}
 
-	private List<YStringToResourceConfig> toStringToResourceConfig(
-			EList<CxGridStyleConfig> configs) {
+	private List<YStringToResourceConfig> toStringToResourceConfig(EList<CxGridStyleConfig> configs) {
 		List<YStringToResourceConfig> result = new ArrayList<>(configs.size());
 		for (CxGridStyleConfig config : configs) {
 			if (!(config instanceof CxGridStyleConfigStringToResource)) {
@@ -367,8 +517,7 @@
 			}
 
 			CxGridStyleConfigStringToResource givenConfig = (CxGridStyleConfigStringToResource) config;
-			YStringToResourceConfig newConfig = YConverterFactory.eINSTANCE
-					.createYStringToResourceConfig();
+			YStringToResourceConfig newConfig = YConverterFactory.eINSTANCE.createYStringToResourceConfig();
 			newConfig.setResourceThemePath(givenConfig.getResourceThemePath());
 			newConfig.setValue(givenConfig.getValue());
 			newConfig.setCompare(toGridCompare(givenConfig.getCompare()));
@@ -380,8 +529,7 @@
 
 	protected Pair createBadRenderer() {
 		Pair pair = new Pair();
-		pair.renderer = CxGridRendererFactory.eINSTANCE
-				.createCxGridTextRenderer();
+		pair.renderer = CxGridRendererFactory.eINSTANCE.createCxGridTextRenderer();
 		return pair;
 	}
 
@@ -389,4 +537,36 @@
 		public CxGridRenderer renderer;
 		public YConverter converter;
 	}
+
+	protected static class Info {
+		public CxGridGroupedCell cxGridGroup;
+
+		CxGridProperty prop;
+
+		// true, if the column is editable
+		boolean editable;
+
+		// the name of the first bound dto
+		String group;
+
+		// the dot path extended by the domainkey if rawDtoRef is true
+		String fullDotPath;
+
+		// true if nested or rawDtoRef
+		boolean nested;
+
+		// if true, then the prop binds to the domain key
+		boolean domainkey;
+
+		// if true, we need to add the domainkey since the property points to a
+		// raw dto. Eg. person.country -> so we make it to
+		// person.country.isoCode
+		boolean rawDtoRef;
+
+		// the first dtoType in the binding path used for groupings
+		Class<?> firstNestedDtoType;
+
+		// the type of the bound property
+		Class<?> type;
+	}
 }
diff --git a/org.eclipse.osbp.infogrid.model.edit/.classpath b/org.eclipse.osbp.infogrid.model.edit/.classpath
index cf36b56..22f3064 100644
--- a/org.eclipse.osbp.infogrid.model.edit/.classpath
+++ b/org.eclipse.osbp.infogrid.model.edit/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="src" path="src/"/>
-	<classpathentry kind="output" path="target/classes"/>
+	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.osbp.infogrid.model.edit/.project b/org.eclipse.osbp.infogrid.model.edit/.project
index 7174e52..3157b0a 100644
--- a/org.eclipse.osbp.infogrid.model.edit/.project
+++ b/org.eclipse.osbp.infogrid.model.edit/.project
@@ -6,11 +6,6 @@
 	</projects>
 	<buildSpec>
 		<buildCommand>
-			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
@@ -30,20 +25,8 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
-		<buildCommand>
-			<name>org.sonarlint.eclipse.core.sonarlintBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.m2e.core.maven2Builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
 	</buildSpec>
 	<natures>
-		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
-		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.babel.editor.rbeNature</nature>
diff --git a/org.eclipse.osbp.infogrid.model.edit/META-INF/MANIFEST.MF b/org.eclipse.osbp.infogrid.model.edit/META-INF/MANIFEST.MF
index 766a1a2..8e79c03 100644
--- a/org.eclipse.osbp.infogrid.model.edit/META-INF/MANIFEST.MF
+++ b/org.eclipse.osbp.infogrid.model.edit/META-INF/MANIFEST.MF
@@ -4,15 +4,16 @@
 Bundle-SymbolicName: org.eclipse.osbp.infogrid.model.edit;singleton:=true
 Bundle-Version: 0.9.0.qualifier
 Bundle-ClassPath: .
-Bundle-Activator: org.eclipse.osbp.infogrid.model.gridsource.provider.CxGridSourceEditPlugin$Implementation
+Bundle-Activator: org.eclipse.osbp.infogrid.model.gridsource.provider.CxGridSourceEditPlugin$Implementation$Activator
 Bundle-Vendor: Eclipse OSBP
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.eclipse.osbp.infogrid.model.gridsource.provider;version="0.9.0",
  org.eclipse.osbp.infogrid.model.gridsource.style.provider;version="0.9.0"
-Require-Bundle: org.eclipse.core.runtime,
+Require-Bundle: org.eclipse.core.runtime;resolution:=optional;x-installation:=greedy,
  org.eclipse.osbp.infogrid.model;bundle-version="[0.9.0,0.10.0)";visibility:=reexport,
  org.eclipse.emf.edit;visibility:=reexport,
  org.eclipse.xtext.common.types;bundle-version="[2.11.0,2.12.0)";visibility:=reexport,
  org.eclipse.xtext.common.types.edit;bundle-version="[2.11.0,2.12.0)";visibility:=reexport
+Import-Package: org.osgi.framework
 Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.osbp.infogrid.model.edit/plugin.properties b/org.eclipse.osbp.infogrid.model.edit/plugin.properties
index 265967c..3dc5b33 100644
--- a/org.eclipse.osbp.infogrid.model.edit/plugin.properties
+++ b/org.eclipse.osbp.infogrid.model.edit/plugin.properties
@@ -100,3 +100,4 @@
 _UI_CxGridSource_tags_feature = Tags
 _UI_CxGridSource_selectionEventTopic_feature = Selection Event Topic
 _UI_CxGridProperty_editable_feature = Editable
+_UI_CxGridSource_groupNestedTypes_feature = Group Nested Types
diff --git a/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceEditPlugin.java b/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceEditPlugin.java
index bc15b53..55cd06b 100644
--- a/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceEditPlugin.java
+++ b/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceEditPlugin.java
@@ -17,6 +17,7 @@
 import org.eclipse.emf.common.util.ResourceLocator;
 
 import org.eclipse.xtext.common.types.provider.TypesEditPlugin;
+import org.osgi.framework.BundleActivator;
 
 /**
  * This is the central singleton for the CxGridSource edit plugin.
@@ -97,6 +98,19 @@
 			//
 			plugin = this;
 		}
+
+		/**
+		 * The actual implementation of the purely OSGi-compatible <b>Bundle Activator</b>.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		public static final class Activator extends EMFPlugin.OSGiDelegatingBundleActivator {
+			@Override
+			protected BundleActivator createBundle() {
+				return new Implementation();
+			}
+		}
 	}
 
 }
diff --git a/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceItemProvider.java b/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceItemProvider.java
index 3e53db1..a903ffb 100644
--- a/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceItemProvider.java
+++ b/org.eclipse.osbp.infogrid.model.edit/src/org/eclipse/osbp/infogrid/model/gridsource/provider/CxGridSourceItemProvider.java
@@ -81,6 +81,7 @@
 			addKindPropertyDescriptor(object);
 			addRootTypeFQNPropertyDescriptor(object);
 			addSelectionEventTopicPropertyDescriptor(object);
+			addGroupNestedTypesPropertyDescriptor(object);
 		}
 		return itemPropertyDescriptors;
 	}
@@ -196,6 +197,28 @@
 	}
 
 	/**
+	 * This adds a property descriptor for the Group Nested Types feature.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected void addGroupNestedTypesPropertyDescriptor(Object object) {
+		itemPropertyDescriptors.add
+			(createItemPropertyDescriptor
+				(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(),
+				 getResourceLocator(),
+				 getString("_UI_CxGridSource_groupNestedTypes_feature"),
+				 getString("_UI_PropertyDescriptor_description", "_UI_CxGridSource_groupNestedTypes_feature", "_UI_CxGridSource_type"),
+				 CxGridSourcePackage.Literals.CX_GRID_SOURCE__GROUP_NESTED_TYPES,
+				 true,
+				 false,
+				 false,
+				 ItemPropertyDescriptor.BOOLEAN_VALUE_IMAGE,
+				 null,
+				 null));
+	}
+
+	/**
 	 * This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
 	 * {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
 	 * {@link org.eclipse.emf.edit.command.MoveCommand} in {@link #createCommand}.
@@ -270,6 +293,7 @@
 			case CxGridSourcePackage.CX_GRID_SOURCE__KIND:
 			case CxGridSourcePackage.CX_GRID_SOURCE__ROOT_TYPE_FQN:
 			case CxGridSourcePackage.CX_GRID_SOURCE__SELECTION_EVENT_TOPIC:
+			case CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES:
 				fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true));
 				return;
 			case CxGridSourcePackage.CX_GRID_SOURCE__ROOT_TYPE:
diff --git a/org.eclipse.osbp.infogrid.model/model/gridsource.aird b/org.eclipse.osbp.infogrid.model/model/gridsource.aird
new file mode 100644
index 0000000..7185cdd
--- /dev/null
+++ b/org.eclipse.osbp.infogrid.model/model/gridsource.aird
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<viewpoint:DAnalysis xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:viewpoint="http://www.eclipse.org/sirius/1.1.0" xmi:id="_yr1HMCmJEeel844VWZXc6w" version="11.1.0.201608251200"/>
diff --git a/org.eclipse.osbp.infogrid.model/model/gridsource.ecore b/org.eclipse.osbp.infogrid.model/model/gridsource.ecore
index cb02d21..f50a7e6 100644
--- a/org.eclipse.osbp.infogrid.model/model/gridsource.ecore
+++ b/org.eclipse.osbp.infogrid.model/model/gridsource.ecore
@@ -15,6 +15,8 @@
     <eStructuralFeatures xsi:type="ecore:EReference" name="inputs" upperBound="-1"
         eType="#//CxGridSourceInput" containment="true"/>
     <eStructuralFeatures xsi:type="ecore:EAttribute" name="selectionEventTopic" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="groupNestedTypes" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"
+        defaultValueLiteral="false"/>
   </eClassifiers>
   <eClassifiers xsi:type="ecore:EClass" name="CxGridSourceInput">
     <eStructuralFeatures xsi:type="ecore:EReference" name="inputType" eType="ecore:EClass ../../org.eclipse.xtext.common.types/model/JavaVMTypes.ecore#//JvmTypeReference"
diff --git a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSource.java b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSource.java
index 0547e46..f6e600b 100644
--- a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSource.java
+++ b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSource.java
@@ -35,6 +35,7 @@
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#getProperties <em>Properties</em>}</li>
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#getInputs <em>Inputs</em>}</li>
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#getSelectionEventTopic <em>Selection Event Topic</em>}</li>
+ *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#isGroupNestedTypes <em>Group Nested Types</em>}</li>
  * </ul>
  *
  * @see org.eclipse.osbp.infogrid.model.gridsource.CxGridSourcePackage#getCxGridSource()
@@ -221,4 +222,31 @@
 	 */
 	void setSelectionEventTopic(String value);
 
+	/**
+	 * Returns the value of the '<em><b>Group Nested Types</b></em>' attribute.
+	 * The default value is <code>"false"</code>.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Group Nested Types</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Group Nested Types</em>' attribute.
+	 * @see #setGroupNestedTypes(boolean)
+	 * @see org.eclipse.osbp.infogrid.model.gridsource.CxGridSourcePackage#getCxGridSource_GroupNestedTypes()
+	 * @model default="false"
+	 * @generated
+	 */
+	boolean isGroupNestedTypes();
+
+	/**
+	 * Sets the value of the '{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#isGroupNestedTypes <em>Group Nested Types</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Group Nested Types</em>' attribute.
+	 * @see #isGroupNestedTypes()
+	 * @generated
+	 */
+	void setGroupNestedTypes(boolean value);
+
 } // CxGridSource
diff --git a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSourcePackage.java b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSourcePackage.java
index afc12cf..f4af7a2 100644
--- a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSourcePackage.java
+++ b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/CxGridSourcePackage.java
@@ -148,13 +148,22 @@
 	int CX_GRID_SOURCE__SELECTION_EVENT_TOPIC = 7;
 
 	/**
+	 * The feature id for the '<em><b>Group Nested Types</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int CX_GRID_SOURCE__GROUP_NESTED_TYPES = 8;
+
+	/**
 	 * The number of structural features of the '<em>Cx Grid Source</em>' class.
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
 	 * @generated
 	 * @ordered
 	 */
-	int CX_GRID_SOURCE_FEATURE_COUNT = 8;
+	int CX_GRID_SOURCE_FEATURE_COUNT = 9;
 
 	/**
 	 * The meta object id for the '{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceInputImpl <em>Input</em>}' class.
@@ -486,6 +495,17 @@
 	EAttribute getCxGridSource_SelectionEventTopic();
 
 	/**
+	 * Returns the meta object for the attribute '{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#isGroupNestedTypes <em>Group Nested Types</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Group Nested Types</em>'.
+	 * @see org.eclipse.osbp.infogrid.model.gridsource.CxGridSource#isGroupNestedTypes()
+	 * @see #getCxGridSource()
+	 * @generated
+	 */
+	EAttribute getCxGridSource_GroupNestedTypes();
+
+	/**
 	 * Returns the meta object for class '{@link org.eclipse.osbp.infogrid.model.gridsource.CxGridSourceInput <em>Input</em>}'.
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -797,6 +817,14 @@
 		EAttribute CX_GRID_SOURCE__SELECTION_EVENT_TOPIC = eINSTANCE.getCxGridSource_SelectionEventTopic();
 
 		/**
+		 * The meta object literal for the '<em><b>Group Nested Types</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute CX_GRID_SOURCE__GROUP_NESTED_TYPES = eINSTANCE.getCxGridSource_GroupNestedTypes();
+
+		/**
 		 * The meta object literal for the '{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceInputImpl <em>Input</em>}' class.
 		 * <!-- begin-user-doc -->
 		 * <!-- end-user-doc -->
diff --git a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourceImpl.java b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourceImpl.java
index f084c53..1ea8703 100644
--- a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourceImpl.java
+++ b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourceImpl.java
@@ -45,6 +45,7 @@
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceImpl#getProperties <em>Properties</em>}</li>
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceImpl#getInputs <em>Inputs</em>}</li>
  *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceImpl#getSelectionEventTopic <em>Selection Event Topic</em>}</li>
+ *   <li>{@link org.eclipse.osbp.infogrid.model.gridsource.impl.CxGridSourceImpl#isGroupNestedTypes <em>Group Nested Types</em>}</li>
  * </ul>
  *
  * @generated
@@ -171,6 +172,26 @@
 	protected String selectionEventTopic = SELECTION_EVENT_TOPIC_EDEFAULT;
 
 	/**
+	 * The default value of the '{@link #isGroupNestedTypes() <em>Group Nested Types</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isGroupNestedTypes()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final boolean GROUP_NESTED_TYPES_EDEFAULT = false;
+
+	/**
+	 * The cached value of the '{@link #isGroupNestedTypes() <em>Group Nested Types</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isGroupNestedTypes()
+	 * @generated
+	 * @ordered
+	 */
+	protected boolean groupNestedTypes = GROUP_NESTED_TYPES_EDEFAULT;
+
+	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
 	 * @generated
@@ -357,6 +378,27 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
+	public boolean isGroupNestedTypes() {
+		return groupNestedTypes;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setGroupNestedTypes(boolean newGroupNestedTypes) {
+		boolean oldGroupNestedTypes = groupNestedTypes;
+		groupNestedTypes = newGroupNestedTypes;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES, oldGroupNestedTypes, groupNestedTypes));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
 	@Override
 	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
 		switch (featureID) {
@@ -394,6 +436,8 @@
 				return getInputs();
 			case CxGridSourcePackage.CX_GRID_SOURCE__SELECTION_EVENT_TOPIC:
 				return getSelectionEventTopic();
+			case CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES:
+				return isGroupNestedTypes();
 		}
 		return super.eGet(featureID, resolve, coreType);
 	}
@@ -434,6 +478,9 @@
 			case CxGridSourcePackage.CX_GRID_SOURCE__SELECTION_EVENT_TOPIC:
 				setSelectionEventTopic((String)newValue);
 				return;
+			case CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES:
+				setGroupNestedTypes((Boolean)newValue);
+				return;
 		}
 		super.eSet(featureID, newValue);
 	}
@@ -470,6 +517,9 @@
 			case CxGridSourcePackage.CX_GRID_SOURCE__SELECTION_EVENT_TOPIC:
 				setSelectionEventTopic(SELECTION_EVENT_TOPIC_EDEFAULT);
 				return;
+			case CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES:
+				setGroupNestedTypes(GROUP_NESTED_TYPES_EDEFAULT);
+				return;
 		}
 		super.eUnset(featureID);
 	}
@@ -498,6 +548,8 @@
 				return inputs != null && !inputs.isEmpty();
 			case CxGridSourcePackage.CX_GRID_SOURCE__SELECTION_EVENT_TOPIC:
 				return SELECTION_EVENT_TOPIC_EDEFAULT == null ? selectionEventTopic != null : !SELECTION_EVENT_TOPIC_EDEFAULT.equals(selectionEventTopic);
+			case CxGridSourcePackage.CX_GRID_SOURCE__GROUP_NESTED_TYPES:
+				return groupNestedTypes != GROUP_NESTED_TYPES_EDEFAULT;
 		}
 		return super.eIsSet(featureID);
 	}
@@ -522,6 +574,8 @@
 		result.append(rootTypeFQN);
 		result.append(", selectionEventTopic: ");
 		result.append(selectionEventTopic);
+		result.append(", groupNestedTypes: ");
+		result.append(groupNestedTypes);
 		result.append(')');
 		return result.toString();
 	}
diff --git a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourcePackageImpl.java b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourcePackageImpl.java
index 586ca18..c22af3c 100644
--- a/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourcePackageImpl.java
+++ b/org.eclipse.osbp.infogrid.model/src/org/eclipse/osbp/infogrid/model/gridsource/impl/CxGridSourcePackageImpl.java
@@ -233,6 +233,15 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
+	public EAttribute getCxGridSource_GroupNestedTypes() {
+		return (EAttribute)cxGridSourceEClass.getEStructuralFeatures().get(8);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
 	public EClass getCxGridSourceInput() {
 		return cxGridSourceInputEClass;
 	}
@@ -445,6 +454,7 @@
 		createEReference(cxGridSourceEClass, CX_GRID_SOURCE__PROPERTIES);
 		createEReference(cxGridSourceEClass, CX_GRID_SOURCE__INPUTS);
 		createEAttribute(cxGridSourceEClass, CX_GRID_SOURCE__SELECTION_EVENT_TOPIC);
+		createEAttribute(cxGridSourceEClass, CX_GRID_SOURCE__GROUP_NESTED_TYPES);
 
 		cxGridSourceInputEClass = createEClass(CX_GRID_SOURCE_INPUT);
 		createEReference(cxGridSourceInputEClass, CX_GRID_SOURCE_INPUT__INPUT_TYPE);
@@ -518,6 +528,7 @@
 		initEReference(getCxGridSource_Properties(), this.getCxGridProperty(), null, "properties", null, 0, -1, CxGridSource.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 		initEReference(getCxGridSource_Inputs(), this.getCxGridSourceInput(), null, "inputs", null, 0, -1, CxGridSource.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 		initEAttribute(getCxGridSource_SelectionEventTopic(), ecorePackage.getEString(), "selectionEventTopic", null, 0, 1, CxGridSource.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getCxGridSource_GroupNestedTypes(), ecorePackage.getEBoolean(), "groupNestedTypes", "false", 0, 1, CxGridSource.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 
 		initEClass(cxGridSourceInputEClass, CxGridSourceInput.class, "CxGridSourceInput", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEReference(getCxGridSourceInput_InputType(), theTypesPackage.getJvmTypeReference(), null, "inputType", null, 0, 1, CxGridSourceInput.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
diff --git a/stuff b/stuff
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stuff