@SuppressWarnings("unchecked")
  public void writePropertyTypeRecord(String name, String value, DataOutput out)
      throws HyracksDataException {
    IARecordBuilder propertyRecordBuilder = new RecordBuilder();
    ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
    propertyRecordBuilder.reset(MetadataRecordTypes.FEED_ADAPTER_CONFIGURATION_RECORDTYPE);
    AMutableString aString = new AMutableString("");
    ISerializerDeserializer<AString> stringSerde =
        AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);

    // write field 0
    fieldValue.reset();
    aString.setValue(name);
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    propertyRecordBuilder.addField(0, fieldValue);

    // write field 1
    fieldValue.reset();
    aString.setValue(value);
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    propertyRecordBuilder.addField(1, fieldValue);

    try {
      propertyRecordBuilder.write(out, true);
    } catch (IOException | AsterixException e) {
      throw new HyracksDataException(e);
    }
  }
 @Override
 protected void setSecondaryRecDescAndComparators(
     CompiledCreateIndexStatement createIndexStmt, AqlMetadataProvider metadata)
     throws AlgebricksException, AsterixException {
   List<String> secondaryKeyFields = createIndexStmt.getKeyFields();
   int numSecondaryKeys = secondaryKeyFields.size();
   if (numSecondaryKeys != 1) {
     throw new AsterixException(
         "Cannot use "
             + numSecondaryKeys
             + " fields as a key for the R-tree index. There can be only one field as a key for the R-tree index.");
   }
   Pair<IAType, Boolean> spatialTypePair =
       Index.getNonNullableKeyFieldType(secondaryKeyFields.get(0), itemType);
   IAType spatialType = spatialTypePair.first;
   anySecondaryKeyIsNullable = spatialTypePair.second;
   if (spatialType == null) {
     throw new AsterixException(
         "Could not find field " + secondaryKeyFields.get(0) + " in the schema.");
   }
   int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
   numNestedSecondaryKeyFields = numDimensions * 2;
   secondaryFieldAccessEvalFactories =
       metadata
           .getFormat()
           .createMBRFactory(itemType, secondaryKeyFields.get(0), numPrimaryKeys, numDimensions);
   secondaryComparatorFactories = new IBinaryComparatorFactory[numNestedSecondaryKeyFields];
   valueProviderFactories = new IPrimitiveValueProviderFactory[numNestedSecondaryKeyFields];
   ISerializerDeserializer[] secondaryRecFields =
       new ISerializerDeserializer[numPrimaryKeys + numNestedSecondaryKeyFields];
   ITypeTraits[] secondaryTypeTraits =
       new ITypeTraits[numNestedSecondaryKeyFields + numPrimaryKeys];
   IAType nestedKeyType = NonTaggedFormatUtil.getNestedSpatialType(spatialType.getTypeTag());
   keyType = nestedKeyType.getTypeTag();
   for (int i = 0; i < numNestedSecondaryKeyFields; i++) {
     ISerializerDeserializer keySerde =
         AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(nestedKeyType);
     secondaryRecFields[i] = keySerde;
     secondaryComparatorFactories[i] =
         AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(
             nestedKeyType, true);
     secondaryTypeTraits[i] = AqlTypeTraitProvider.INSTANCE.getTypeTrait(nestedKeyType);
     valueProviderFactories[i] = AqlPrimitiveValueProviderFactory.INSTANCE;
   }
   // Add serializers and comparators for primary index fields.
   for (int i = 0; i < numPrimaryKeys; i++) {
     secondaryRecFields[numNestedSecondaryKeyFields + i] = primaryRecDesc.getFields()[i];
     secondaryTypeTraits[numNestedSecondaryKeyFields + i] = primaryRecDesc.getTypeTraits()[i];
   }
   secondaryRecDesc = new RecordDescriptor(secondaryRecFields, secondaryTypeTraits);
 }
/** Translates a Function metadata entity to an ITupleReference and vice versa. */
public class FunctionTupleTranslator extends AbstractTupleTranslator<Function> {
  // Field indexes of serialized Function in a tuple.
  // First key field.
  public static final int FUNCTION_DATAVERSENAME_TUPLE_FIELD_INDEX = 0;
  // Second key field.
  public static final int FUNCTION_FUNCTIONNAME_TUPLE_FIELD_INDEX = 1;
  // Third key field.
  public static final int FUNCTION_FUNCTIONARITY_TUPLE_FIELD_INDEX = 2;

  // Payload field containing serialized Function.
  public static final int FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX = 3;

  @SuppressWarnings("unchecked")
  private ISerializerDeserializer<ARecord> recordSerDes =
      AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
          MetadataRecordTypes.FUNCTION_RECORDTYPE);

  public FunctionTupleTranslator(boolean getTuple) {
    super(getTuple, MetadataPrimaryIndexes.FUNCTION_DATASET.getFieldCount());
  }

  @Override
  public Function getMetadataEntityFromTuple(ITupleReference frameTuple) throws IOException {
    byte[] serRecord = frameTuple.getFieldData(FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX);
    int recordStartOffset = frameTuple.getFieldStart(FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX);
    int recordLength = frameTuple.getFieldLength(FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX);
    ByteArrayInputStream stream =
        new ByteArrayInputStream(serRecord, recordStartOffset, recordLength);
    DataInput in = new DataInputStream(stream);
    ARecord functionRecord = (ARecord) recordSerDes.deserialize(in);
    return createFunctionFromARecord(functionRecord);
  }

  private Function createFunctionFromARecord(ARecord functionRecord) {
    String dataverseName =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_DATAVERSENAME_FIELD_INDEX))
            .getStringValue();
    String functionName =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTIONNAME_FIELD_INDEX))
            .getStringValue();
    String arity =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARITY_FIELD_INDEX))
            .getStringValue();

    IACursor cursor =
        ((AOrderedList)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX))
            .getCursor();
    List<String> params = new ArrayList<String>();
    while (cursor.next()) {
      params.add(((AString) cursor.get()).getStringValue());
    }

    String returnType =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX))
            .getStringValue();

    String definition =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEFINITION_FIELD_INDEX))
            .getStringValue();

    String language =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_LANGUAGE_FIELD_INDEX))
            .getStringValue();

    String functionKind =
        ((AString)
                functionRecord.getValueByPos(
                    MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_KIND_FIELD_INDEX))
            .getStringValue();
    return new Function(
        dataverseName,
        functionName,
        Integer.parseInt(arity),
        params,
        returnType,
        definition,
        language,
        functionKind);
  }

  @Override
  public ITupleReference getTupleFromMetadataEntity(Function function)
      throws IOException, MetadataException {
    // write the key in the first 2 fields of the tuple
    tupleBuilder.reset();
    aString.setValue(function.getDataverseName());
    stringSerde.serialize(aString, tupleBuilder.getDataOutput());
    tupleBuilder.addFieldEndOffset();
    aString.setValue(function.getName());
    stringSerde.serialize(aString, tupleBuilder.getDataOutput());
    tupleBuilder.addFieldEndOffset();
    aString.setValue(function.getArity() + "");
    stringSerde.serialize(aString, tupleBuilder.getDataOutput());
    tupleBuilder.addFieldEndOffset();

    // write the pay-load in the fourth field of the tuple

    recordBuilder.reset(MetadataRecordTypes.FUNCTION_RECORDTYPE);

    // write field 0
    fieldValue.reset();
    aString.setValue(function.getDataverseName());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_DATAVERSENAME_FIELD_INDEX, fieldValue);

    // write field 1
    fieldValue.reset();
    aString.setValue(function.getName());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTIONNAME_FIELD_INDEX, fieldValue);

    // write field 2
    fieldValue.reset();
    aString.setValue(function.getArity() + "");
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARITY_FIELD_INDEX, fieldValue);

    // write field 3
    OrderedListBuilder listBuilder = new OrderedListBuilder();
    ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
    listBuilder.reset(
        (AOrderedListType)
            MetadataRecordTypes.FUNCTION_RECORDTYPE
                .getFieldTypes()[
                MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX]);
    for (String param : function.getParams()) {
      itemValue.reset();
      aString.setValue(param);
      stringSerde.serialize(aString, itemValue.getDataOutput());
      listBuilder.addItem(itemValue);
    }
    fieldValue.reset();
    listBuilder.write(fieldValue.getDataOutput(), true);
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX, fieldValue);

    // write field 4
    fieldValue.reset();
    aString.setValue(function.getReturnType());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX, fieldValue);

    // write field 5
    fieldValue.reset();
    aString.setValue(function.getFunctionBody());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEFINITION_FIELD_INDEX, fieldValue);

    // write field 6
    fieldValue.reset();
    aString.setValue(function.getLanguage());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_LANGUAGE_FIELD_INDEX, fieldValue);

    // write field 7
    fieldValue.reset();
    aString.setValue(function.getKind());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(
        MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_KIND_FIELD_INDEX, fieldValue);

    // write record
    try {
      recordBuilder.write(tupleBuilder.getDataOutput(), true);
    } catch (AsterixException e) {
      throw new MetadataException(e);
    }
    tupleBuilder.addFieldEndOffset();

    tuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
    return tuple;
  }
}
/** Translates a Feed metadata entity to an ITupleReference and vice versa. */
public class FeedTupleTranslator extends AbstractTupleTranslator<Feed> {
  // Field indexes of serialized Feed in a tuple.
  // Key field.
  public static final int FEED_DATAVERSE_NAME_FIELD_INDEX = 0;

  public static final int FEED_NAME_FIELD_INDEX = 1;

  // Payload field containing serialized feed.
  public static final int FEED_PAYLOAD_TUPLE_FIELD_INDEX = 2;

  @SuppressWarnings("unchecked")
  private ISerializerDeserializer<ARecord> recordSerDes =
      AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
          MetadataRecordTypes.FEED_RECORDTYPE);

  public FeedTupleTranslator(boolean getTuple) {
    super(getTuple, MetadataPrimaryIndexes.FEED_DATASET.getFieldCount());
  }

  @Override
  public Feed getMetadataEntityFromTuple(ITupleReference frameTuple) throws IOException {
    byte[] serRecord = frameTuple.getFieldData(FEED_PAYLOAD_TUPLE_FIELD_INDEX);
    int recordStartOffset = frameTuple.getFieldStart(FEED_PAYLOAD_TUPLE_FIELD_INDEX);
    int recordLength = frameTuple.getFieldLength(FEED_PAYLOAD_TUPLE_FIELD_INDEX);
    ByteArrayInputStream stream =
        new ByteArrayInputStream(serRecord, recordStartOffset, recordLength);
    DataInput in = new DataInputStream(stream);
    ARecord feedRecord = (ARecord) recordSerDes.deserialize(in);
    return createFeedFromARecord(feedRecord);
  }

  private Feed createFeedFromARecord(ARecord feedRecord) {
    Feed feed = null;
    String dataverseName =
        ((AString)
                feedRecord.getValueByPos(
                    MetadataRecordTypes.FEED_ARECORD_DATAVERSE_NAME_FIELD_INDEX))
            .getStringValue();
    String feedName =
        ((AString) feedRecord.getValueByPos(MetadataRecordTypes.FEED_ARECORD_FEED_NAME_FIELD_INDEX))
            .getStringValue();

    Object o = feedRecord.getValueByPos(MetadataRecordTypes.FEED_ARECORD_FUNCTION_FIELD_INDEX);
    FunctionSignature signature = null;
    if (!(o instanceof ANull)) {
      String functionName = ((AString) o).getStringValue();
      signature = new FunctionSignature(dataverseName, functionName, 1);
    }

    String feedType =
        ((AString) feedRecord.getValueByPos(MetadataRecordTypes.FEED_ARECORD_FEED_TYPE_FIELD_INDEX))
            .getStringValue();

    FeedType feedTypeEnum = FeedType.valueOf(feedType.toUpperCase());
    switch (feedTypeEnum) {
      case PRIMARY:
        {
          ARecord feedTypeDetailsRecord =
              (ARecord)
                  feedRecord.getValueByPos(
                      MetadataRecordTypes.FEED_ARECORD_PRIMARY_TYPE_DETAILS_FIELD_INDEX);
          String adapterName =
              ((AString)
                      feedTypeDetailsRecord.getValueByPos(
                          MetadataRecordTypes
                              .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_NAME_FIELD_INDEX))
                  .getStringValue();

          IACursor cursor =
              ((AUnorderedList)
                      feedTypeDetailsRecord.getValueByPos(
                          MetadataRecordTypes
                              .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_CONFIGURATION_FIELD_INDEX))
                  .getCursor();
          String key;
          String value;
          Map<String, String> adaptorConfiguration = new HashMap<String, String>();
          while (cursor.next()) {
            ARecord field = (ARecord) cursor.get();
            key =
                ((AString) field.getValueByPos(MetadataRecordTypes.PROPERTIES_NAME_FIELD_INDEX))
                    .getStringValue();
            value =
                ((AString) field.getValueByPos(MetadataRecordTypes.PROPERTIES_VALUE_FIELD_INDEX))
                    .getStringValue();
            adaptorConfiguration.put(key, value);
          }
          feed =
              new PrimaryFeed(
                  dataverseName, feedName, adapterName, adaptorConfiguration, signature);
        }
        break;
      case SECONDARY:
        {
          ARecord feedTypeDetailsRecord =
              (ARecord)
                  feedRecord.getValueByPos(
                      MetadataRecordTypes.FEED_ARECORD_SECONDARY_TYPE_DETAILS_FIELD_INDEX);

          String sourceFeedName =
              ((AString)
                      feedTypeDetailsRecord.getValueByPos(
                          MetadataRecordTypes
                              .FEED_TYPE_SECONDARY_ARECORD_SOURCE_FEED_NAME_FIELD_INDEX))
                  .getStringValue();

          feed = new SecondaryFeed(dataverseName, feedName, sourceFeedName, signature);
        }
        break;
    }

    return feed;
  }

  @Override
  public ITupleReference getTupleFromMetadataEntity(Feed feed)
      throws IOException, MetadataException {
    // write the key in the first two fields of the tuple
    tupleBuilder.reset();
    aString.setValue(feed.getDataverseName());
    stringSerde.serialize(aString, tupleBuilder.getDataOutput());
    tupleBuilder.addFieldEndOffset();

    aString.setValue(feed.getFeedName());
    stringSerde.serialize(aString, tupleBuilder.getDataOutput());
    tupleBuilder.addFieldEndOffset();

    recordBuilder.reset(MetadataRecordTypes.FEED_RECORDTYPE);

    // write field 0
    fieldValue.reset();
    aString.setValue(feed.getDataverseName());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(MetadataRecordTypes.FEED_ARECORD_DATAVERSE_NAME_FIELD_INDEX, fieldValue);

    // write field 1
    fieldValue.reset();
    aString.setValue(feed.getFeedName());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(MetadataRecordTypes.FEED_ARECORD_FEED_NAME_FIELD_INDEX, fieldValue);

    // write field 2
    fieldValue.reset();
    if (feed.getAppliedFunction() != null) {
      aString.setValue(feed.getAppliedFunction().getName());
      stringSerde.serialize(aString, fieldValue.getDataOutput());
      recordBuilder.addField(MetadataRecordTypes.FEED_ARECORD_FUNCTION_FIELD_INDEX, fieldValue);
    }

    // write field 3
    fieldValue.reset();
    aString.setValue(feed.getFeedType().name().toUpperCase());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(MetadataRecordTypes.FEED_ARECORD_FEED_TYPE_FIELD_INDEX, fieldValue);

    // write field 4/5
    fieldValue.reset();
    writeFeedTypeDetailsRecordType(recordBuilder, feed, fieldValue);

    // write field 6
    fieldValue.reset();
    aString.setValue(Calendar.getInstance().getTime().toString());
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    recordBuilder.addField(MetadataRecordTypes.FEED_ARECORD_TIMESTAMP_FIELD_INDEX, fieldValue);

    // write record
    try {
      recordBuilder.write(tupleBuilder.getDataOutput(), true);
    } catch (AsterixException e) {
      throw new MetadataException(e);
    }
    tupleBuilder.addFieldEndOffset();

    tuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
    return tuple;
  }

  @SuppressWarnings("unchecked")
  private void writeFeedTypeDetailsRecordType(
      IARecordBuilder recordBuilder, Feed feed, ArrayBackedValueStorage fieldValue)
      throws HyracksDataException {

    switch (feed.getFeedType()) {
      case PRIMARY:
        {
          PrimaryFeed primaryFeed = (PrimaryFeed) feed;

          IARecordBuilder primaryDetailsRecordBuilder = new RecordBuilder();
          OrderedListBuilder listBuilder = new OrderedListBuilder();
          ArrayBackedValueStorage primaryRecordfieldValue = new ArrayBackedValueStorage();
          ArrayBackedValueStorage primaryRecordItemValue = new ArrayBackedValueStorage();
          primaryDetailsRecordBuilder.reset(MetadataRecordTypes.PRIMARY_FEED_DETAILS_RECORDTYPE);

          AMutableString aString = new AMutableString("");
          ISerializerDeserializer<AString> stringSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ASTRING);

          // write field 0
          fieldValue.reset();
          aString.setValue(primaryFeed.getAdaptorName());
          stringSerde.serialize(aString, primaryRecordfieldValue.getDataOutput());
          primaryDetailsRecordBuilder.addField(
              MetadataRecordTypes.FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_NAME_FIELD_INDEX,
              primaryRecordfieldValue);

          // write field 1
          listBuilder.reset(
              (AUnorderedListType)
                  MetadataRecordTypes.PRIMARY_FEED_DETAILS_RECORDTYPE
                      .getFieldTypes()[
                      MetadataRecordTypes
                          .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_CONFIGURATION_FIELD_INDEX]);
          for (Map.Entry<String, String> property :
              primaryFeed.getAdaptorConfiguration().entrySet()) {
            String name = property.getKey();
            String value = property.getValue();
            primaryRecordItemValue.reset();
            writePropertyTypeRecord(name, value, primaryRecordItemValue.getDataOutput());
            listBuilder.addItem(primaryRecordItemValue);
          }
          primaryRecordfieldValue.reset();
          listBuilder.write(primaryRecordfieldValue.getDataOutput(), true);
          primaryDetailsRecordBuilder.addField(
              MetadataRecordTypes
                  .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_CONFIGURATION_FIELD_INDEX,
              primaryRecordfieldValue);

          try {
            primaryDetailsRecordBuilder.write(fieldValue.getDataOutput(), true);
          } catch (IOException | AsterixException e) {
            throw new HyracksDataException(e);
          }

          recordBuilder.addField(
              MetadataRecordTypes.FEED_ARECORD_PRIMARY_TYPE_DETAILS_FIELD_INDEX, fieldValue);
        }
        break;

      case SECONDARY:
        SecondaryFeed secondaryFeed = (SecondaryFeed) feed;

        IARecordBuilder secondaryDetailsRecordBuilder = new RecordBuilder();
        ArrayBackedValueStorage secondaryFieldValue = new ArrayBackedValueStorage();
        secondaryDetailsRecordBuilder.reset(MetadataRecordTypes.SECONDARY_FEED_DETAILS_RECORDTYPE);

        // write field 0
        fieldValue.reset();
        aString.setValue(secondaryFeed.getSourceFeedName());
        stringSerde.serialize(aString, secondaryFieldValue.getDataOutput());
        secondaryDetailsRecordBuilder.addField(
            MetadataRecordTypes.FEED_ARECORD_SECONDARY_FIELD_DETAILS_SOURCE_FEED_NAME_FIELD_INDEX,
            secondaryFieldValue);

        try {
          secondaryDetailsRecordBuilder.write(fieldValue.getDataOutput(), true);
        } catch (IOException | AsterixException e) {
          throw new HyracksDataException(e);
        }
        recordBuilder.addField(
            MetadataRecordTypes.FEED_ARECORD_SECONDARY_TYPE_DETAILS_FIELD_INDEX, fieldValue);
        break;
    }
  }

  @SuppressWarnings("unchecked")
  public void writePropertyTypeRecord(String name, String value, DataOutput out)
      throws HyracksDataException {
    IARecordBuilder propertyRecordBuilder = new RecordBuilder();
    ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
    propertyRecordBuilder.reset(MetadataRecordTypes.FEED_ADAPTER_CONFIGURATION_RECORDTYPE);
    AMutableString aString = new AMutableString("");
    ISerializerDeserializer<AString> stringSerde =
        AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);

    // write field 0
    fieldValue.reset();
    aString.setValue(name);
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    propertyRecordBuilder.addField(0, fieldValue);

    // write field 1
    fieldValue.reset();
    aString.setValue(value);
    stringSerde.serialize(aString, fieldValue.getDataOutput());
    propertyRecordBuilder.addField(1, fieldValue);

    try {
      propertyRecordBuilder.write(out, true);
    } catch (IOException | AsterixException e) {
      throw new HyracksDataException(e);
    }
  }
}
  @SuppressWarnings("unchecked")
  private void writeFeedTypeDetailsRecordType(
      IARecordBuilder recordBuilder, Feed feed, ArrayBackedValueStorage fieldValue)
      throws HyracksDataException {

    switch (feed.getFeedType()) {
      case PRIMARY:
        {
          PrimaryFeed primaryFeed = (PrimaryFeed) feed;

          IARecordBuilder primaryDetailsRecordBuilder = new RecordBuilder();
          OrderedListBuilder listBuilder = new OrderedListBuilder();
          ArrayBackedValueStorage primaryRecordfieldValue = new ArrayBackedValueStorage();
          ArrayBackedValueStorage primaryRecordItemValue = new ArrayBackedValueStorage();
          primaryDetailsRecordBuilder.reset(MetadataRecordTypes.PRIMARY_FEED_DETAILS_RECORDTYPE);

          AMutableString aString = new AMutableString("");
          ISerializerDeserializer<AString> stringSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ASTRING);

          // write field 0
          fieldValue.reset();
          aString.setValue(primaryFeed.getAdaptorName());
          stringSerde.serialize(aString, primaryRecordfieldValue.getDataOutput());
          primaryDetailsRecordBuilder.addField(
              MetadataRecordTypes.FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_NAME_FIELD_INDEX,
              primaryRecordfieldValue);

          // write field 1
          listBuilder.reset(
              (AUnorderedListType)
                  MetadataRecordTypes.PRIMARY_FEED_DETAILS_RECORDTYPE
                      .getFieldTypes()[
                      MetadataRecordTypes
                          .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_CONFIGURATION_FIELD_INDEX]);
          for (Map.Entry<String, String> property :
              primaryFeed.getAdaptorConfiguration().entrySet()) {
            String name = property.getKey();
            String value = property.getValue();
            primaryRecordItemValue.reset();
            writePropertyTypeRecord(name, value, primaryRecordItemValue.getDataOutput());
            listBuilder.addItem(primaryRecordItemValue);
          }
          primaryRecordfieldValue.reset();
          listBuilder.write(primaryRecordfieldValue.getDataOutput(), true);
          primaryDetailsRecordBuilder.addField(
              MetadataRecordTypes
                  .FEED_ARECORD_PRIMARY_FIELD_DETAILS_ADAPTOR_CONFIGURATION_FIELD_INDEX,
              primaryRecordfieldValue);

          try {
            primaryDetailsRecordBuilder.write(fieldValue.getDataOutput(), true);
          } catch (IOException | AsterixException e) {
            throw new HyracksDataException(e);
          }

          recordBuilder.addField(
              MetadataRecordTypes.FEED_ARECORD_PRIMARY_TYPE_DETAILS_FIELD_INDEX, fieldValue);
        }
        break;

      case SECONDARY:
        SecondaryFeed secondaryFeed = (SecondaryFeed) feed;

        IARecordBuilder secondaryDetailsRecordBuilder = new RecordBuilder();
        ArrayBackedValueStorage secondaryFieldValue = new ArrayBackedValueStorage();
        secondaryDetailsRecordBuilder.reset(MetadataRecordTypes.SECONDARY_FEED_DETAILS_RECORDTYPE);

        // write field 0
        fieldValue.reset();
        aString.setValue(secondaryFeed.getSourceFeedName());
        stringSerde.serialize(aString, secondaryFieldValue.getDataOutput());
        secondaryDetailsRecordBuilder.addField(
            MetadataRecordTypes.FEED_ARECORD_SECONDARY_FIELD_DETAILS_SOURCE_FEED_NAME_FIELD_INDEX,
            secondaryFieldValue);

        try {
          secondaryDetailsRecordBuilder.write(fieldValue.getDataOutput(), true);
        } catch (IOException | AsterixException e) {
          throw new HyracksDataException(e);
        }
        recordBuilder.addField(
            MetadataRecordTypes.FEED_ARECORD_SECONDARY_TYPE_DETAILS_FIELD_INDEX, fieldValue);
        break;
    }
  }
public class APointSerializerDeserializer implements ISerializerDeserializer<APoint> {

  private static final long serialVersionUID = 1L;

  public static final APointSerializerDeserializer INSTANCE = new APointSerializerDeserializer();

  @SuppressWarnings("unchecked")
  private static final ISerializerDeserializer<APoint> pointSerde =
      AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.APOINT);

  private static final AMutablePoint aPoint = new AMutablePoint(0, 0);

  private APointSerializerDeserializer() {}

  @Override
  public APoint deserialize(DataInput in) throws HyracksDataException {
    try {
      return new APoint(in.readDouble(), in.readDouble());
    } catch (IOException e) {
      throw new HyracksDataException(e);
    }
  }

  @Override
  public void serialize(APoint instance, DataOutput out) throws HyracksDataException {
    try {
      out.writeDouble(instance.getX());
      out.writeDouble(instance.getY());
    } catch (IOException e) {
      throw new HyracksDataException(e);
    }
  }

  public static void serialize(double x, double y, DataOutput out) throws HyracksDataException {
    try {
      out.writeDouble(x);
      out.writeDouble(y);
    } catch (IOException e) {
      throw new HyracksDataException(e);
    }
  }

  public static final int getCoordinateOffset(Coordinate coordinate) throws HyracksDataException {

    switch (coordinate) {
      case X:
        return 1;
      case Y:
        return 9;
      default:
        throw new HyracksDataException("Wrong coordinate");
    }
  }

  public static void parse(String point, DataOutput out) throws HyracksDataException {
    try {
      aPoint.setValue(
          Double.parseDouble(point.substring(0, point.indexOf(','))),
          Double.parseDouble(point.substring(point.indexOf(',') + 1, point.length())));
      pointSerde.serialize(aPoint, out);
    } catch (HyracksDataException e) {
      throw new HyracksDataException(point + " can not be an instance of point");
    }
  }
}