private void init(final GroupType selectedGroupType,
                    final ConverterParent parent, final int index, final GroupType containingGroupType, TypeInfo hiveTypeInfo) {
    if (parent != null) {
      setMetadata(parent.getMetadata());
    }
    final int selectedFieldCount = selectedGroupType.getFieldCount();

    converters = new Converter[selectedFieldCount];
    this.repeatedConverters = new ArrayList<Repeated>();

    if (hiveTypeInfo != null && hiveTypeInfo.getCategory().equals(ObjectInspector.Category.STRUCT)) {
      this.hiveFieldNames = ((StructTypeInfo) hiveTypeInfo).getAllStructFieldNames();
      this.hiveFieldTypeInfos = ((StructTypeInfo) hiveTypeInfo).getAllStructFieldTypeInfos();
    }

    List<Type> selectedFields = selectedGroupType.getFields();
    for (int i = 0; i < selectedFieldCount; i++) {
      Type subtype = selectedFields.get(i);
      if (isSubType(containingGroupType, subtype)) {
        int fieldIndex = containingGroupType.getFieldIndex(subtype.getName());
        TypeInfo _hiveTypeInfo = getFieldTypeIgnoreCase(hiveTypeInfo, subtype.getName(), fieldIndex);
        converters[i] = getFieldConverter(subtype, fieldIndex, _hiveTypeInfo);
      } else {
        throw new IllegalStateException("Group type [" + containingGroupType +
            "] does not contain requested field: " + subtype);
      }
    }
  }
A MapWritableGroupConverter, real converter between hive and parquet types recursively for complex types.
ql/src/java/org/apache/hadoop/hive/ql/io/parquet/convert/HiveStructConverter.java