@Override
    public Optional<FunctionDefinition> getFunctionDefinition(String name) {
        if (BUILT_IN_FUNC_BLACKLIST.contains(name)) {
            return Optional.empty();
        }
        FunctionDefinitionFactory.Context context = () -> classLoader;

        // We override some Hive's function by native implementation to supports hash-agg
        if (isNativeAggFunctionEnabled() && BUILTIN_NATIVE_AGG_FUNC.contains(name.toLowerCase())) {
            return getBuiltInNativeAggFunction(name.toLowerCase());
        }

        // We override Hive's grouping function. Refer to the implementation for more details.
        if (name.equalsIgnoreCase("grouping")) {
            return Optional.of(
                    factory.createFunctionDefinitionFromHiveFunction(
                            name, HiveGenericUDFGrouping.class.getName(), context));
        }

        // this function is used to generate legacy GROUPING__ID value for old hive versions
        if (name.equalsIgnoreCase(GenericUDFLegacyGroupingID.NAME)) {
            return Optional.of(
                    factory.createFunctionDefinitionFromHiveFunction(
                            name, GenericUDFLegacyGroupingID.class.getName(), context));
        }

        // We override Hive's internal_interval. Refer to the implementation for more details
        if (name.equalsIgnoreCase("internal_interval")) {
            return Optional.of(
                    factory.createFunctionDefinitionFromHiveFunction(
                            name, HiveGenericUDFInternalInterval.class.getName(), context));
        }

        // used to access the field of struct in array
        if (name.equalsIgnoreCase(HiveGenericUDFArrayAccessStructField.NAME)) {
            return Optional.of(
                    factory.createFunctionDefinitionFromHiveFunction(
                            name, HiveGenericUDFArrayAccessStructField.class.getName(), context));
        }

        // We add a custom to_decimal function. Refer to the implementation for more details.
        if (name.equalsIgnoreCase(HiveGenericUDFToDecimal.NAME)) {
            return Optional.of(
                    factory.createFunctionDefinitionFromHiveFunction(
                            name, HiveGenericUDFToDecimal.class.getName(), context));
        }

        Optional<FunctionInfo> info = hiveShim.getBuiltInFunctionInfo(name);

        return info.map(
                functionInfo ->
                        factory.createFunctionDefinitionFromHiveFunction(
                                name, functionInfo.getFunctionClass().getName(), context));
    }
@Test
    public void testNonExistFunction() {
        assertThat(new HiveModule().getFunctionDefinition("nonexist")).isNotPresent();
    }