@Override
    public List<DataRecord> visit(StagingBlockKey stagingBlockKey) {
      FieldMetadata blockField =
          new SimpleTypeFieldMetadata(
              explicitProjection,
              false,
              false,
              false,
              "blockKey", //$NON-NLS-1$
              new SimpleTypeMetadata(XMLConstants.W3C_XML_SCHEMA_NS_URI, Types.STRING),
              Collections.<String>emptyList(),
              Collections.<String>emptyList(),
              Collections.<String>emptyList(),
              StringUtils.EMPTY);
      lastField = blockField;
      recordProjection.put(
          blockField,
          new ValueBuilder() {

            @Override
            public Object getValue(DataRecord record) {
              return record
                  .getRecordMetadata()
                  .getRecordProperties()
                  .get(StagingStorage.METADATA_STAGING_BLOCK_KEY);
            }
          });
      return records;
    }
    @Override
    public List<DataRecord> visit(Field field) {
      lastField = field.getFieldMetadata();
      recordProjection.put(
          lastField,
          new ValueBuilder() {

            @Override
            public Object getValue(DataRecord record) {
              return record.get(lastField);
            }
          });
      return records;
    }
 @Override
 public List<DataRecord> visit(Alias alias) {
   alias.getTypedExpression().accept(this);
   FieldMetadata aliasField =
       new SimpleTypeFieldMetadata(
           explicitProjection,
           false,
           lastField.isMany(),
           lastField.isMandatory(),
           alias.getAliasName(),
           lastField.getType(),
           Collections.<String>emptyList(),
           Collections.<String>emptyList(),
           Collections.<String>emptyList(),
           StringUtils.EMPTY);
   ValueBuilder previousValueBuilder = recordProjection.remove(lastField);
   if (previousValueBuilder == null) {
     AggregateValueBuilder previous = aggregateProjection.remove(lastField);
     aggregateProjection.put(aliasField, previous);
   } else {
     recordProjection.put(aliasField, previousValueBuilder);
   }
   return records;
 }
    @Override
    public List<DataRecord> visit(final Distinct distinct) {
      distinct.getExpression().accept(this);
      final ValueBuilder builder = recordProjection.remove(lastField);
      aggregateProjection.put(
          lastField,
          new AggregateValueBuilder() {

            @Override
            public Collection<Object> getValues(List<DataRecord> records) {
              Set<Object> distinctObjects = new HashSet<Object>();
              for (DataRecord record : records) {
                distinctObjects.add(builder.getValue(record));
              }
              return distinctObjects;
            }
          });
      return records;
    }