private ProtoToHiveConvertor createConvertor(Descriptor descriptor,
      Map<Descriptor, ProtoToHiveConvertor> cache) throws SerDeException {
    if (cache.containsKey(descriptor)) {
      return cache.get(descriptor);
    }
    List<FieldDescriptor> fields = descriptor.getFields();
    StructConvertor scConvertor = new StructConvertor(fields.size());
    int i = 0;
    for (FieldDescriptor field : descriptor.getFields()) {
      ProtoToHiveConvertor fc;
      if (field.getJavaType() == JavaType.MESSAGE) {
        fc = createConvertor(field.getMessageType(), cache);
      } else if (field.getJavaType() == JavaType.BYTE_STRING) {
        fc = ByteStringConvertor.INSTANCE;
      } else if (field.getJavaType() == JavaType.ENUM) {
        fc = EnumConvertor.INSTANCE;
      } else {
        fc = IdentityConvertor.INSTANCE;
      }
      if (field.isRepeated()) {
        if (field.getJavaType() == JavaType.MESSAGE &&
            mapTypes.contains(field.getMessageType().getFullName())) {
          if (field.getMessageType().getFields().size() != 2) {
            throw new SerDeException("Expected exactly 2 fields for: " +
                field.getMessageType().getFullName());
          }
          fc = new MapConvertor(fc);
        } else {
          fc = new ListConvertor(fc);
        }
      }
      scConvertor.add(i++, field, fc);
    }
    cache.put(descriptor, scConvertor);
    return scConvertor;
  }
Convert the given writable to a message.
@param writable The writable object containing the message.
@return The converted message object.
@throws SerDeException
ql/src/java/org/apache/hadoop/hive/ql/io/protobuf/ProtobufSerDe.java