private void checkGeomInstance(Instance geomInstance) {
   assertTrue(geomInstance.getValue() instanceof Collection<?>);
   for (Object instance : ((Collection<?>) geomInstance.getValue())) {
     assertTrue(instance instanceof GeometryProperty<?>);
     @SuppressWarnings("unchecked")
     MultiPolygon multipolygon = ((GeometryProperty<MultiPolygon>) instance).getGeometry();
     assertTrue(
         "Read geometry does not match the reference geometry",
         multipolygon.equalsExact(reference));
   }
 }
  private void checkPolygonPropertyInstance(Instance instance) {
    Object[] geomVals = instance.getProperty(new QName(NS_TEST, "geometry"));
    assertNotNull(geomVals);
    assertEquals(1, geomVals.length);

    Object geom = geomVals[0];
    assertTrue(geom instanceof Instance);

    Instance geomInstance = (Instance) geom;
    checkGeomInstance(geomInstance);
  }
  /**
   * Iterates over properties of the instance and creates a map of the given properties
   *
   * @param instance the Instance to check
   * @param headerRow the current header row of the table
   * @param solveNestedProperties <code>true</code> if nested properties should be solved, otherwise
   *     <code>false</code>
   * @return a map of properties with string of localpart of the QName of the property as key
   */
  protected Map<String, Object> getPropertyMap(
      Instance instance, List<String> headerRow, boolean solveNestedProperties) {
    // properties of current instance
    Iterable<QName> allProperties = instance.getPropertyNames();

    // write properties to map; currently only the first property of nested
    // properties is selected
    Map<String, Object> row = new HashMap<String, Object>();
    for (QName qname : allProperties) {

      // get properties of the current instance
      Object[] properties = instance.getProperty(qname);
      if (properties != null && properties.length != 0) {
        String cellValue = "";
        // only the first property is evaluated
        Object property = properties[0];
        if (shouldBeDisplayed(property)) {
          cellValue = qname.getLocalPart();
        }

        // if property is an OInstance or OGroup, it's a nested property
        if (solveNestedProperties && property instanceof Group) {
          Group nextInstance = (Group) property;
          iterateBuild(nextInstance, qname, headerRow, row, cellValue);
          //					Group inst = (Group) property;
          //					// check if property has a value and add it
          //					checkValue(inst, headerRow, row, cellValue);
          //					// go through nested properties to get other properties
          //					Iterator<QName> propertyIt = inst.getPropertyNames().iterator();
          //					if (propertyIt.hasNext()) {
          //						QName value = propertyIt.next();
          //						Object nextProp = inst.getProperty(value)[0];
          //						// check if current property should be displayed in map
          //						if (shouldBeDisplayed(nextProp)) {
          //							cellValue += ".";
          //							cellValue += value.getLocalPart();
          //						}
          //
          //						// iterate over all nested properties
          //						while (nextProp instanceof Group) {
          //							Group oinst = (Group) nextProp;
          //							checkValue(oinst, headerRow, row, cellValue);
          //
          //							// get localparts of all nested properties
          //							Iterator<QName> qnames = oinst.getPropertyNames().iterator();
          //							if (qnames.hasNext()) {
          //								value = qnames.next();
          //								nextProp = oinst.getProperty(value)[0];
          //								if (shouldBeDisplayed(nextProp)) {
          //									cellValue += ".";
          //									cellValue += value.getLocalPart();
          //								}
          //								else
          //									continue;
          //							}
          //							else
          //								break;
          //						}
          //						// add property with corresponding cellValue (localpart)
          //						// to map
          //						// no resolving of nested properties
          //						addProperty(headerRow, row, nextProp, cellValue);
          //					}
        } else {
          // add property with corresponding cellValue (localpart) to
          // map
          if (property instanceof Group && shouldBeDisplayed(property)) {
            checkValue((Group) property, headerRow, row, cellValue);
          } else {
            addProperty(headerRow, row, property, cellValue);
          }
        }
      }
    }
    return row;
  }
    /** Update the selection */
    protected void updateSelection() {
      if (!typeDefinitions.getSelection().isEmpty()) {
        TypeDefinition type =
            (TypeDefinition)
                ((IStructuredSelection) typeDefinitions.getSelection()).getFirstElement();

        filterField.setType(type);

        SchemaSpaceID space = getSchemaSpace();

        Integer max = (Integer) ((IStructuredSelection) count.getSelection()).getFirstElement();

        InstanceService is = PlatformUI.getWorkbench().getService(InstanceService.class);

        List<Instance> instanceList = new ArrayList<Instance>();
        DataSet dataset =
            (space == SchemaSpaceID.SOURCE) ? (DataSet.SOURCE) : (DataSet.TRANSFORMED);

        Filter filter = null;
        String filterExpression = filterField.getFilterExpression();
        /*
         * Custom filter handling.
         *
         * FIXME Ultimately this should be done by the filter field
         * instead, which should be able to handle all kinds of
         * registered filters (e.g. also Groovy).
         */
        if (filterExpression.startsWith("id:")) {
          // XXX meta ID "hack"
          String metaFilter = filterExpression.substring("id:".length());
          String[] values = metaFilter.split(",");

          filter =
              new MetaFilter(
                  type, InstanceMetadata.METADATA_ID, new HashSet<>(Arrays.asList(values)));
        } else if (filterExpression.startsWith("source:")) {
          // XXX meta source ID "hack"
          String metaFilter = filterExpression.substring("source:".length());
          String[] values = metaFilter.split(",");

          filter =
              new MetaFilter(
                  type, InstanceMetadata.METADATA_SOURCEID, new HashSet<>(Arrays.asList(values)));
        } else {
          filter = filterField.getFilter();
        }

        InstanceCollection instances = is.getInstances(dataset);
        if (filter != null) {
          instances = instances.select(filter);
        }

        ResourceIterator<Instance> it = instances.iterator();
        try {
          int num = 0;
          while (it.hasNext() && num < max) {
            Instance instance = it.next();
            if (instance.getDefinition().equals(type)) {
              instanceList.add(instance);
              num++;
            }
          }
        } finally {
          it.close();
        }

        selection = instanceList;
        selectedType = type;
      } else {
        selection = null;
        selectedType = null;

        filterField.setType(null);
      }

      for (InstanceSelectionListener listener : listeners) {
        listener.selectionChanged(selectedType, selection);
      }
    }
  /** @see InstanceViewer#setInput(TypeDefinition, Iterable) */
  @Override
  public void setInput(TypeDefinition type, Iterable<Instance> instances) {
    // remove old columns
    TreeColumn[] columns = treeViewer.getTree().getColumns();
    if (columns != null) {
      for (TreeColumn column : columns) {
        column.dispose();
      }
      labelProviders.clear();
    }

    // create row defs for metadata
    //			if (features != null) {
    //				boolean displayLineage = false;
    //				int lineageLength = 0;
    //				int featuresSize = 0;
    //				for (Feature f : features) {
    //					featuresSize++;
    //					Lineage l = (Lineage) f.getUserData().get("METADATA_LINEAGE"); //$NON-NLS-1$
    //					if (l != null && l.getProcessSteps().size() > 0) {
    //						displayLineage = true;
    //						if (lineageLength < l.getProcessSteps().size()) {
    //							lineageLength = l.getProcessSteps().size();
    //						}
    //					}
    //				}
    //
    //				if (displayLineage) {
    //					Object[][] processStepsText = new Object[lineageLength][featuresSize + 1];
    //					int featureIndex = 0;
    //					for (Feature f : features) {
    //						Lineage l = (Lineage) f.getUserData().get("METADATA_LINEAGE"); //$NON-NLS-1$
    //						if (l != null && l.getProcessSteps().size() > 0) {
    //							int psIndex = 0;
    //							for (ProcessStep ps : l.getProcessSteps()) {
    //								processStepsText[psIndex][featureIndex + 1] = ps.getDescription().toString();
    //								psIndex++;
    //							}
    //						}
    //						featureIndex++;
    //					}
    //
    //					DefaultTreeNode lineage = new DefaultTreeNode(Messages.DefinitionFeatureTreeViewer_5);
    // //$NON-NLS-1$
    //					metadata.addChild(lineage);
    //					for (int i = 0; i < lineageLength; i++) {
    //						processStepsText[i][0] = Messages.DefinitionFeatureTreeViewer_6 + (i + 1); //$NON-NLS-1$
    //						DefaultTreeNode processStep = new DefaultTreeNode(processStepsText[i]);
    //						lineage.addChild(processStep);
    //					}
    //				}
    // set input
    if (type != null) {
      // pass metadatas to the treeviewer, if instances contain metadatas
      Set<String> completeMetaNames = new HashSet<String>();
      for (Instance inst : instances) {
        for (String name : inst.getMetaDataNames()) {
          completeMetaNames.add(name);
        }
      }

      Pair<TypeDefinition, Set<String>> pair =
          new Pair<TypeDefinition, Set<String>>(type, completeMetaNames);

      treeViewer.setInput(pair);
    } else treeViewer.setInput(Collections.emptySet());

    Layout layout = treeViewer.getTree().getParent().getLayout();

    // add type column
    if (type != null) {
      TreeViewerColumn column = new TreeViewerColumn(treeViewer, SWT.LEFT);
      column.getColumn().setText(type.getDisplayName());
      column.setLabelProvider(
          new TreeColumnViewerLabelProvider(new DefinitionMetaCompareLabelProvider(treeViewer)));
      if (layout instanceof TreeColumnLayout) {
        ((TreeColumnLayout) layout).setColumnData(column.getColumn(), new ColumnWeightData(1));
      }
    }

    // add columns for features
    int index = 1;
    if (instances != null) {
      //			// sort features
      //			List<Feature> sortedFeatures = new ArrayList<Feature>();
      //			for (Feature f : features) {
      //				sortedFeatures.add(f);
      //			}
      //			Collections.sort(sortedFeatures, new Comparator<Feature>() {
      //
      //				@Override
      //				public int compare(Feature o1, Feature o2) {
      //					FeatureId id1 = FeatureBuilder.getSourceID(o1);
      //					if (id1 == null) {
      //						id1 = o1.getIdentifier();
      //					}
      //
      //					FeatureId id2 = FeatureBuilder.getSourceID(o2);
      //					if (id2 == null) {
      //						id2 = o2.getIdentifier();
      //					}
      //
      //					return id1.getID().compareTo(id2.getID());
      //				}
      //
      //			});
      List<Instance> insts = new ArrayList<Instance>();
      for (Instance instance : instances) { // sortedFeatures) {
        final TreeViewerColumn column = new TreeViewerColumn(treeViewer, SWT.LEFT);
        //				FeatureId id = FeatureBuilder.getSourceID(feature);
        //				if (id == null) {
        //					id = feature.getIdentifier();
        //				}
        //				column.getColumn().setText(id.toString());
        column.getColumn().setText(String.valueOf(index)); // XXX
        // identifier?
        DefinitionInstanceLabelProvider labelProvider =
            new DefinitionInstanceLabelProvider(instance);
        labelProviders.put(index, labelProvider);
        column.setLabelProvider(labelProvider);
        if (layout instanceof TreeColumnLayout) {
          ((TreeColumnLayout) layout).setColumnData(column.getColumn(), new ColumnWeightData(1));
        }

        // add tool tip
        //				new ColumnBrowserTip(treeViewer, 400, 300, true, index, null);
        insts.add(instance);
        index++;
      }
      ((MetadataCompareActionProvider) maep).setInput(insts, labelProviders);
    }

    treeViewer.refresh();
    treeViewer.getTree().getParent().layout(true, true);

    selectionProvider.updateSelection(instances);

    // auto-expand attributes/metadata
    treeViewer.expandToLevel(2);
  }