@Override
  protected Object defaultTypeDataFromBinary(final byte[] bytes) {
    final ByteBuffer buf = ByteBuffer.wrap(bytes);
    final int initialBytes = buf.getInt();
    // temporary hack for backward compatibility
    final boolean skipConfig = (initialBytes > 0);
    final byte[] typeNameBytes = skipConfig ? new byte[initialBytes] : new byte[buf.getInt()];
    final byte[] visibilityManagementClassNameBytes = new byte[buf.getInt()];
    final byte[] attrBytes = skipConfig ? new byte[0] : new byte[buf.getInt()];
    final byte[] encodedTypeBytes = new byte[buf.getInt()];
    final byte[] adapterIdBytes = new byte[buf.getInt()];
    buf.get(typeNameBytes);
    buf.get(visibilityManagementClassNameBytes); // ignore...old release
    buf.get(attrBytes);
    buf.get(encodedTypeBytes);
    buf.get(adapterIdBytes);
    adapterId = new ByteArrayId(adapterIdBytes);

    final String typeName = StringUtils.stringFromBinary(typeNameBytes);

    final String encodedType = StringUtils.stringFromBinary(encodedTypeBytes);
    try {
      final SimpleFeatureType myType = DataUtilities.createType(typeName, encodedType);

      featureType = myType;
      return featureType;
    } catch (final SchemaException e) {
      LOGGER.error("Unable to deserialized feature type", e);
    }

    final SimpleFeatureUserDataConfigurationSet userDataConfiguration =
        new SimpleFeatureUserDataConfigurationSet();
    userDataConfiguration.addConfigurations(typeName, new TimeDescriptorConfiguration(featureType));
    userDataConfiguration.addConfigurations(
        typeName, new SimpleFeatureStatsConfigurationCollection(featureType));
    userDataConfiguration.addConfigurations(
        typeName, new SimpleFeaturePrimaryIndexConfiguration(featureType));
    try {
      userDataConfiguration.fromJsonString(StringUtils.stringFromBinary(attrBytes), featureType);

    } catch (final IOException e) {
      LOGGER.error("Failure to decode simple feature user data configuration", e);
    }

    return null;
  }
  @Override
  protected byte[] defaultTypeDataToBinary() {
    final String encodedType = DataUtilities.encodeType(featureType);
    final String typeName = featureType.getTypeName();
    final byte[] typeNameBytes = StringUtils.stringToBinary(typeName);
    final byte[] encodedTypeBytes = StringUtils.stringToBinary(encodedType);

    byte[] attrBytes = new byte[0];

    final SimpleFeatureUserDataConfigurationSet userDataConfiguration =
        new SimpleFeatureUserDataConfigurationSet();
    userDataConfiguration.addConfigurations(typeName, new TimeDescriptorConfiguration());
    userDataConfiguration.addConfigurations(
        typeName, new SimpleFeatureStatsConfigurationCollection());
    userDataConfiguration.addConfigurations(typeName, new SimpleFeaturePrimaryIndexConfiguration());
    userDataConfiguration.configureFromType(featureType);

    try {
      attrBytes = StringUtils.stringToBinary(userDataConfiguration.asJsonString());
    } catch (final IOException e) {
      LOGGER.error("Failure to encode simple feature user data configuration", e);
    }

    final ByteBuffer buf =
        ByteBuffer.allocate(
            encodedTypeBytes.length
                + typeNameBytes.length
                + adapterId.getBytes().length
                + attrBytes.length
                + 24);

    buf.putInt(0); // a signal for the new version
    buf.putInt(typeNameBytes.length);
    buf.putInt(0); // old visibility (backward compatibility)
    buf.putInt(attrBytes.length);
    buf.putInt(encodedTypeBytes.length);
    buf.putInt(adapterId.getBytes().length);
    buf.put(typeNameBytes);
    buf.put(attrBytes);
    buf.put(encodedTypeBytes);
    buf.put(adapterId.getBytes());
    return buf.array();
  }