static MatchFieldPathArgumentExtractor fromFunction()

in hollow/src/main/java/com/netflix/hollow/api/consumer/index/MatchFieldPathArgumentExtractor.java [169:269]


    static <Q, T> MatchFieldPathArgumentExtractor<Q> fromFunction(
            HollowDataset dataset, Class<?> rootType, String fieldPath,
            Class<T> extractorType, Function<Q, T> extractorFunction,
            FieldPathResolver fpResolver) {
        String rootTypeName = HollowObjectTypeMapper.getDefaultTypeName(rootType);
        FieldPaths.FieldPath<? extends FieldPaths.FieldSegment> fp = fpResolver.resolve(dataset, rootTypeName,
                fieldPath);

        // @@@ Method on FieldPath
        FieldPaths.FieldSegment lastSegment = fp.getSegments().get(fp.getSegments().size() - 1);
        HollowObjectSchema.FieldType schemaFieldType;
        if (lastSegment.getEnclosingSchema().getSchemaType() == HollowSchema.SchemaType.OBJECT) {
            FieldPaths.ObjectFieldSegment os = (FieldPaths.ObjectFieldSegment) lastSegment;
            schemaFieldType = os.getType();
        } else {
            schemaFieldType = HollowObjectSchema.FieldType.REFERENCE;
        }

        Function<Q, ?> extractor = extractorFunction;
        switch (schemaFieldType) {
            case BOOLEAN:
                if (extractorType != boolean.class && extractorType != Boolean.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case DOUBLE:
                if (extractorType != double.class && extractorType != Double.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case FLOAT:
                if (extractorType != float.class && extractorType != Float.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case INT:
                if (extractorType == byte.class || extractorType == Byte.class) {
                    @SuppressWarnings("unchecked")
                    Function<Q, Byte> f = (Function<Q, Byte>) extractorFunction;
                    extractor = f.andThen(Byte::intValue);
                    break;
                } else if (extractorType == short.class || extractorType == Short.class) {
                    @SuppressWarnings("unchecked")
                    Function<Q, Short> f = (Function<Q, Short>) extractorFunction;
                    extractor = f.andThen(Short::intValue);
                    break;
                } else if (extractorType == char.class || extractorType == Character.class) {
                    @SuppressWarnings("unchecked")
                    Function<Q, Character> f = (Function<Q, Character>) extractorFunction;
                    extractor = f.andThen(c -> (int) c);
                } else if (extractorType != int.class && extractorType != Integer.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case LONG:
                if (extractorType != long.class && extractorType != Long.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case REFERENCE: {
                // @@@ If extractorType == int.class then consider it an ordinal value
                //   and directly use the extractorFunction

                String typeName = lastSegment.getTypeName();

                // Manage for String and all box types
                if (typeName.equals("String")) {
                    if (!HollowObject.class.isAssignableFrom(extractorType)) {
                        throw incompatibleMatchType(extractorType, fieldPath, typeName);
                    }
                    // @@@ Check that object schema has single value field of String type such as HString
                } else if (!extractorType.getSimpleName().equals(typeName)) {
                    throw incompatibleMatchType(extractorType, fieldPath, typeName);
                } else if (!HollowRecord.class.isAssignableFrom(extractorType)) {
                    throw incompatibleMatchType(extractorType, fieldPath, typeName);
                }

                @SuppressWarnings("unchecked")
                Function<Q, HollowRecord> f = (Function<Q, HollowRecord>) extractorFunction;
                extractor = f.andThen(HollowRecord::getOrdinal);
                break;
            }
            case BYTES:
                if (extractorType != byte[].class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
            case STRING:
                if (extractorType == char[].class) {
                    @SuppressWarnings("unchecked")
                    Function<Q, char[]> f = (Function<Q, char[]>) extractorFunction;
                    extractor = f.andThen(String::valueOf);
                    break;
                } else if (extractorType != String.class) {
                    throw incompatibleMatchType(extractorType, fieldPath, schemaFieldType);
                }
                break;
        }

        return new MatchFieldPathArgumentExtractor<>(fp, extractor);
    }