Search in sources :

Example 16 with CallableUserAggregationFunction

use of org.neo4j.kernel.api.procedure.CallableUserAggregationFunction in project neo4j by neo4j.

the class UserAggregationFunctionTest method shouldAllowOverridingProcedureName.

@Test
void shouldAllowOverridingProcedureName() throws Throwable {
    // When
    CallableUserAggregationFunction method = compile(FunctionWithOverriddenName.class).get(0);
    // Then
    assertEquals("org.mystuff.thisisActuallyTheName", method.signature().name().toString());
}
Also used : CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) Test(org.junit.jupiter.api.Test)

Example 17 with CallableUserAggregationFunction

use of org.neo4j.kernel.api.procedure.CallableUserAggregationFunction in project neo4j by neo4j.

the class UserAggregationFunctionTest method shouldNotLoadAnyFunctionIfConfigIsEmpty.

@Test
void shouldNotLoadAnyFunctionIfConfigIsEmpty() throws Throwable {
    // Given
    Log log = spy(Log.class);
    procedureCompiler = new ProcedureCompiler(new TypeCheckers(), components, new ComponentRegistry(), log, new ProcedureConfig(Config.defaults(GraphDatabaseSettings.procedure_allowlist, List.of(""))));
    List<CallableUserAggregationFunction> method = compile(SingleAggregationFunction.class);
    verify(log).warn("The function 'org.neo4j.procedure.impl.collectCool' is not on the allowlist and won't be loaded.");
    assertThat(method.size()).isEqualTo(0);
}
Also used : CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) Log(org.neo4j.logging.Log) NullLog(org.neo4j.logging.NullLog) Test(org.junit.jupiter.api.Test)

Example 18 with CallableUserAggregationFunction

use of org.neo4j.kernel.api.procedure.CallableUserAggregationFunction in project neo4j by neo4j.

the class UserAggregationFunctionTest method shouldLoadWhiteListedFunction.

@Test
void shouldLoadWhiteListedFunction() throws Throwable {
    // Given
    procedureCompiler = new ProcedureCompiler(new TypeCheckers(), components, new ComponentRegistry(), NullLog.getInstance(), new ProcedureConfig(Config.defaults(GraphDatabaseSettings.procedure_allowlist, List.of("org.neo4j.procedure.impl.collectCool"))));
    CallableUserAggregationFunction method = compile(SingleAggregationFunction.class).get(0);
    // Expect
    UserAggregator created = method.create(prepareContext());
    created.update(new AnyValue[] { stringValue("Bonnie") });
    assertThat(created.result()).isEqualTo(VirtualValues.list(stringValue("Bonnie")));
}
Also used : CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) UserAggregator(org.neo4j.internal.kernel.api.procs.UserAggregator) Test(org.junit.jupiter.api.Test)

Example 19 with CallableUserAggregationFunction

use of org.neo4j.kernel.api.procedure.CallableUserAggregationFunction in project neo4j by neo4j.

the class UserAggregationFunctionTest method shouldRunClassWithMultipleFunctionsDeclared.

@Test
void shouldRunClassWithMultipleFunctionsDeclared() throws Throwable {
    // Given
    List<CallableUserAggregationFunction> compiled = compile(MultiFunction.class);
    CallableUserAggregationFunction f1 = compiled.get(0);
    CallableUserAggregationFunction f2 = compiled.get(1);
    // When
    UserAggregator f1Aggregator = f1.create(prepareContext());
    f1Aggregator.update(new AnyValue[] { stringValue("Bonnie") });
    f1Aggregator.update(new AnyValue[] { stringValue("Clyde") });
    UserAggregator f2Aggregator = f2.create(prepareContext());
    f2Aggregator.update(new AnyValue[] { stringValue("Bonnie"), longValue(1337L) });
    f2Aggregator.update(new AnyValue[] { stringValue("Bonnie"), longValue(42L) });
    // Then
    assertThat(f1Aggregator.result()).isEqualTo(VirtualValues.list(stringValue("Bonnie"), stringValue("Clyde")));
    assertThat(((MapValue) f2Aggregator.result()).get("Bonnie")).isEqualTo(longValue(1337L));
}
Also used : CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) UserAggregator(org.neo4j.internal.kernel.api.procs.UserAggregator) MapValue(org.neo4j.values.virtual.MapValue) Test(org.junit.jupiter.api.Test)

Example 20 with CallableUserAggregationFunction

use of org.neo4j.kernel.api.procedure.CallableUserAggregationFunction in project neo4j by neo4j.

the class ProcedureCompiler method compileAggregationFunction.

private CallableUserAggregationFunction compileAggregationFunction(Class<?> definition, Method create, QualifiedName funcName) throws ProcedureException {
    restrictions.verify(funcName);
    // find update and result method
    Method update = null;
    Method result = null;
    Class<?> aggregator = create.getReturnType();
    for (Method m : aggregator.getDeclaredMethods()) {
        if (m.isAnnotationPresent(UserAggregationUpdate.class)) {
            if (update != null) {
                throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Class '%s' contains multiple methods annotated with '@%s'.", aggregator.getSimpleName(), UserAggregationUpdate.class.getSimpleName());
            }
            update = m;
        }
        if (m.isAnnotationPresent(UserAggregationResult.class)) {
            if (result != null) {
                throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Class '%s' contains multiple methods annotated with '@%s'.", aggregator.getSimpleName(), UserAggregationResult.class.getSimpleName());
            }
            result = m;
        }
    }
    if (result == null || update == null) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Class '%s' must contain methods annotated with both '@%s' as well as '@%s'.", aggregator.getSimpleName(), UserAggregationResult.class.getSimpleName(), UserAggregationUpdate.class.getSimpleName());
    }
    if (update.getReturnType() != void.class) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Update method '%s' in %s has type '%s' but must have return type 'void'.", update.getName(), aggregator.getSimpleName(), update.getReturnType().getSimpleName());
    }
    if (!isPublic(create.getModifiers())) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Aggregation method '%s' in %s must be public.", create.getName(), definition.getSimpleName());
    }
    if (!isPublic(aggregator.getModifiers())) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Aggregation class '%s' must be public.", aggregator.getSimpleName());
    }
    if (!isPublic(update.getModifiers())) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Aggregation update method '%s' in %s must be public.", update.getName(), aggregator.getSimpleName());
    }
    if (!isPublic(result.getModifiers())) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Aggregation result method '%s' in %s must be public.", result.getName(), aggregator.getSimpleName());
    }
    List<FieldSignature> inputSignature = inputSignatureDeterminer.signatureFor(update);
    Class<?> returnType = result.getReturnType();
    TypeCheckers.TypeChecker valueConverter = typeCheckers.checkerFor(returnType);
    String description = description(create);
    UserAggregationFunction function = create.getAnnotation(UserAggregationFunction.class);
    String deprecated = deprecated(create, function::deprecatedBy, "Use of @UserAggregationFunction(deprecatedBy) without @Deprecated in " + funcName);
    List<FieldSetter> setters = allFieldInjections.setters(definition);
    if (!config.fullAccessFor(funcName.toString())) {
        try {
            setters = safeFieldInjections.setters(definition);
        } catch (ComponentInjectionException e) {
            description = describeAndLogLoadFailure(funcName);
            UserFunctionSignature signature = new UserFunctionSignature(funcName, inputSignature, valueConverter.type(), deprecated, config.rolesFor(funcName.toString()), description, null, false);
            return new FailedLoadAggregatedFunction(signature);
        }
    }
    UserFunctionSignature signature = new UserFunctionSignature(funcName, inputSignature, valueConverter.type(), deprecated, config.rolesFor(funcName.toString()), description, null, false);
    return ProcedureCompilation.compileAggregation(signature, setters, create, update, result);
}
Also used : UserAggregationResult(org.neo4j.procedure.UserAggregationResult) UserAggregationUpdate(org.neo4j.procedure.UserAggregationUpdate) FieldSignature(org.neo4j.internal.kernel.api.procs.FieldSignature) Method(java.lang.reflect.Method) UserFunctionSignature(org.neo4j.internal.kernel.api.procs.UserFunctionSignature) CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) UserAggregationFunction(org.neo4j.procedure.UserAggregationFunction) FailedLoadAggregatedFunction(org.neo4j.kernel.api.procedure.FailedLoadAggregatedFunction) ProcedureException(org.neo4j.internal.kernel.api.exceptions.ProcedureException) ComponentInjectionException(org.neo4j.kernel.api.exceptions.ComponentInjectionException)

Aggregations

CallableUserAggregationFunction (org.neo4j.kernel.api.procedure.CallableUserAggregationFunction)20 Test (org.junit.jupiter.api.Test)15 UserAggregator (org.neo4j.internal.kernel.api.procs.UserAggregator)7 UserFunctionSignature (org.neo4j.internal.kernel.api.procs.UserFunctionSignature)7 ProcedureException (org.neo4j.internal.kernel.api.exceptions.ProcedureException)6 Log (org.neo4j.logging.Log)5 NullLog (org.neo4j.logging.NullLog)4 Method (java.lang.reflect.Method)2 FieldSignature (org.neo4j.internal.kernel.api.procs.FieldSignature)2 QualifiedName (org.neo4j.internal.kernel.api.procs.QualifiedName)2 ComponentInjectionException (org.neo4j.kernel.api.exceptions.ComponentInjectionException)2 CallableProcedure (org.neo4j.kernel.api.procedure.CallableProcedure)2 CallableUserFunction (org.neo4j.kernel.api.procedure.CallableUserFunction)2 FailedLoadAggregatedFunction (org.neo4j.kernel.api.procedure.FailedLoadAggregatedFunction)2 UserAggregationFunction (org.neo4j.procedure.UserAggregationFunction)2 UserAggregationResult (org.neo4j.procedure.UserAggregationResult)2 UserAggregationUpdate (org.neo4j.procedure.UserAggregationUpdate)2 AnyValue (org.neo4j.values.AnyValue)2 Constructor (java.lang.reflect.Constructor)1 Modifier.isPublic (java.lang.reflect.Modifier.isPublic)1