All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.cp.BeanCreateMethodFinder Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.cp;

import static org.apache.juneau.common.internal.ArgUtils.*;

import java.util.*;
import java.util.function.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.reflect.*;

/**
 * Utility class for creating beans through creator methods.
 *
 * 

* Used for finding and invoking methods on an object that take in arbitrary parameters and returns bean instances. * *

* This class is instantiated through the following methods: *

    *
  • {@link BeanStore} *
      *
    • {@link BeanStore#createMethodFinder(Class)} *
    • {@link BeanStore#createMethodFinder(Class,Class)} *
    • {@link BeanStore#createMethodFinder(Class,Object)} *
    *
  • *
* *
Example:
*

* // The bean we want to create. * public class A {} * * // The bean that has a creator method for the bean above. * public class B { * * // Creator method. * // Bean store must have a C bean and optionally a D bean. * public A createA(C c, Optional<D> d) { * return new A(c, d.orElse(null)); * } * } * * // Instantiate the bean with the creator method. * B b = new B(); * * // Create a bean store with some mapped beans. * BeanStore beanStore = BeanStore.create().addBean(C.class, new C()); * * // Instantiate the bean using the creator method. * A a = beanStore * .createMethodFinder(A.class, b) // Looking for creator for A on b object. * .find("createA") // Look for method called "createA". * .thenFind("createA2") // Then look for method called "createA2". * .withDefault(()->new A()) // Optionally supply a default value if method not found. * .run(); // Execute. *

* *
See Also:
    *
  • {@link BeanStore} *
* * @param The bean type being created. */ public class BeanCreateMethodFinder { private Class beanType; private final Class resourceClass; private final Object resource; private final BeanStore beanStore; private MethodInfo method; private Object[] args; private Supplier def = ()->null; BeanCreateMethodFinder(Class beanType, Object resource, BeanStore beanStore) { this.beanType = assertArgNotNull("beanType", beanType); this.resource = assertArgNotNull("resource", resource); this.resourceClass = resource.getClass(); this.beanStore = BeanStore.of(beanStore, resource); } BeanCreateMethodFinder(Class beanType, Class resourceClass, BeanStore beanStore) { this.beanType = assertArgNotNull("beanType", beanType); this.resource = null; this.resourceClass = assertArgNotNull("resourceClass", resourceClass); this.beanStore = BeanStore.of(beanStore); } /** * Adds a bean to the lookup for parameters. * * @param The bean type. * @param c The bean type. * @param t The bean. * @return This object. */ public BeanCreateMethodFinder addBean(Class c, T2 t) { beanStore.addBean(c, t); return this; } /** * Find the method matching the specified predicate. * *

* In order for the method to be used, it must adhere to the following restrictions: *

    *
  • The method must be public. *
  • The method can be static. *
  • The method name must match exactly. *
  • The method must not be deprecated or annotated with {@link BeanIgnore}. *
  • The method must have all parameter types specified in requiredParams. *
  • The bean store must contain beans for all parameter types. *
  • The bean store may contain beans for all {@link Optional} parameter types. *
* *

* This method can be called multiple times with different method names or required parameters until a match is found. *
Once a method is found, subsequent calls to this method will be no-ops. * * See {@link BeanStore#createMethodFinder(Class, Object)} for usage. * * @param filter The predicate to apply. * @return This object. */ public BeanCreateMethodFinder find(Predicate filter) { if (method == null) { method = ClassInfo.of(resourceClass).getPublicMethod( x -> x.isNotDeprecated() && x.hasReturnType(beanType) && x.hasNoAnnotation(BeanIgnore.class) && filter.test(x) && beanStore.hasAllParams(x) && (x.isStatic() || resource != null) ); if (method != null) args = beanStore.getParams(method); } return this; } /** * Shortcut for calling find(x -> x.hasName(methodName)). * * @param methodName The method name to match. * @return This object. */ public BeanCreateMethodFinder find(String methodName) { return find(x -> x.hasName(methodName)); } /** * Identical to {@link #find(Predicate)} but named for fluent-style calls. * * @param filter The predicate to apply. * @return This object. */ public BeanCreateMethodFinder thenFind(Predicate filter) { return find(filter); } /** * Identical to {@link #find(Predicate)} but named for fluent-style calls. * * @param methodName The method name to match. * @return This object. */ public BeanCreateMethodFinder thenFind(String methodName) { return find(methodName); } /** * A default value to return if no matching methods were found. * * @param def The default value. Can be null. * @return This object. */ public BeanCreateMethodFinder withDefault(T def) { return withDefault(()->def); } /** * A default value to return if no matching methods were found. * * @param def The default value. * @return This object. */ public BeanCreateMethodFinder withDefault(Supplier def) { assertArgNotNull("def", def); this.def = def; return this; } /** * Executes the matched method and returns the result. * * @return The object returned by the method invocation, or the default value if method was not found. * @throws ExecutableException If method invocation threw an exception. */ @SuppressWarnings("unchecked") public T run() throws ExecutableException { if (method != null) return (T)method.invoke(resource, args); return def.get(); } /** * Same as {@link #run()} but also executes a consumer if the returned value was not null. * * @param consumer The consumer of the response. * @return The object returned by the method invocation, or the default value if method was not found, or {@link Optional#empty()}. * @throws ExecutableException If method invocation threw an exception. */ public T run(Consumer consumer) throws ExecutableException { T t = run(); if (t != null) consumer.accept(t); return t; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy