public static IndexMetaData readFrom(StreamInput in) throws IOException {
   Builder builder = new Builder(in.readUTF());
   builder.version(in.readLong());
   builder.state(State.fromId(in.readByte()));
   builder.settings(readSettingsFromStream(in));
   int mappingsSize = in.readVInt();
   for (int i = 0; i < mappingsSize; i++) {
     MappingMetaData mappingMd = MappingMetaData.readFrom(in);
     builder.putMapping(mappingMd);
   }
   int aliasesSize = in.readVInt();
   for (int i = 0; i < aliasesSize; i++) {
     AliasMetaData aliasMd = AliasMetaData.Builder.readFrom(in);
     builder.putAlias(aliasMd);
   }
   int customSize = in.readVInt();
   for (int i = 0; i < customSize; i++) {
     String type = in.readUTF();
     Custom customIndexMetaData = lookupFactorySafe(type).readFrom(in);
     builder.putCustom(type, customIndexMetaData);
   }
   return builder.build();
 }
    public static IndexMetaData fromXContent(XContentParser parser) throws IOException {
      if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
        parser.nextToken();
      }
      Builder builder = new Builder(parser.currentName());

      String currentFieldName = null;
      XContentParser.Token token = parser.nextToken();
      while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
        if (token == XContentParser.Token.FIELD_NAME) {
          currentFieldName = parser.currentName();
        } else if (token == XContentParser.Token.START_OBJECT) {
          if ("settings".equals(currentFieldName)) {
            builder.settings(
                ImmutableSettings.settingsBuilder()
                    .put(SettingsLoader.Helper.loadNestedFromMap(parser.mapOrdered())));
          } else if ("mappings".equals(currentFieldName)) {
            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
              if (token == XContentParser.Token.FIELD_NAME) {
                currentFieldName = parser.currentName();
              } else if (token == XContentParser.Token.START_OBJECT) {
                String mappingType = currentFieldName;
                Map<String, Object> mappingSource =
                    MapBuilder.<String, Object>newMapBuilder()
                        .put(mappingType, parser.mapOrdered())
                        .map();
                builder.putMapping(new MappingMetaData(mappingType, mappingSource));
              }
            }
          } else if ("aliases".equals(currentFieldName)) {
            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
              builder.putAlias(AliasMetaData.Builder.fromXContent(parser));
            }
          } else {
            // check if its a custom index metadata
            Custom.Factory<Custom> factory = lookupFactory(currentFieldName);
            if (factory == null) {
              // TODO warn
              parser.skipChildren();
            } else {
              builder.putCustom(factory.type(), factory.fromXContent(parser));
            }
          }
        } else if (token == XContentParser.Token.START_ARRAY) {
          if ("mappings".equals(currentFieldName)) {
            while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
              if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
                builder.putMapping(new MappingMetaData(new CompressedString(parser.binaryValue())));
              } else {
                Map<String, Object> mapping = parser.mapOrdered();
                if (mapping.size() == 1) {
                  String mappingType = mapping.keySet().iterator().next();
                  builder.putMapping(new MappingMetaData(mappingType, mapping));
                }
              }
            }
          }
        } else if (token.isValue()) {
          if ("state".equals(currentFieldName)) {
            builder.state(State.fromString(parser.text()));
          } else if ("version".equals(currentFieldName)) {
            builder.version(parser.longValue());
          }
        }
      }
      return builder.build();
    }