001// Generated by delombok at Sun Jul 30 17:21:56 UTC 2023
002package de.cuioss.test.jsf.config.decorator;
003
004import static de.cuioss.tools.string.MoreStrings.emptyToNull;
005import static de.cuioss.tools.string.MoreStrings.isEmpty;
006import static java.util.Objects.requireNonNull;
007import java.util.Optional;
008import javax.faces.context.FacesContext;
009import javax.inject.Named;
010import de.cuioss.tools.reflect.MoreReflection;
011import lombok.NonNull;
012
013/**
014 * @author Oliver Wolff
015 */
016public class BeanConfigDecorator {
017    private static final String NAME_MUST_NOT_BE_NULL = "Name must not be null";
018    private static final String BEAN_MUST_NOT_BE_NULL = "Bean must not be null";
019    /**
020     * Wraps textual names to EL-expressions.
021     */
022    @SuppressWarnings("el-syntax")
023    public static final String EL_WRAPPER = "#{%s}";
024    /**
025     * String constant used for checking if given String is EL-Expression.
026     */
027    @SuppressWarnings("el-syntax")
028    public static final String EL_START = "#{";
029    @NonNull
030    private final FacesContext facesContext;
031
032    /**
033     * Registers a given Object as jsf-managed bean for the given key
034     *
035     * @param managedBean to be registered, must not be null
036     * @param name        to be registered to. May be a correct value-expression or
037     *                    not (actual name only). Must not be null nor empty.
038     * @return the {@link BeanConfigDecorator} itself in order to enable a
039     *         fluent-api style usage
040     */
041    public BeanConfigDecorator register(final Object managedBean, final String name) {
042        requireNonNull(emptyToNull(name), NAME_MUST_NOT_BE_NULL);
043        requireNonNull(managedBean, BEAN_MUST_NOT_BE_NULL);
044        final var expressionFactory = facesContext.getApplication().getExpressionFactory();
045        final var ve = expressionFactory.createValueExpression(facesContext.getELContext(), checkManagedBeanKey(name), managedBean.getClass());
046        ve.setValue(facesContext.getELContext(), managedBean);
047        return this;
048    }
049
050    /**
051     * Registers a given Object as jsf-managed bean. It checks the given bean for
052     * the annotation {@link Named} in oder to extract the corresponding value
053     * attribute. If none could be found it uses the {@link Class#getSimpleName()}
054     * with the first letter being lower-cased
055     *
056     * @param managedBean to be registered, must not be null
057     * @return the {@link BeanConfigDecorator} itself in order to enable a
058     *         fluent-api style usage
059     */
060    public BeanConfigDecorator register(final Object managedBean) {
061        requireNonNull(managedBean, BEAN_MUST_NOT_BE_NULL);
062        final Class<?> type = managedBean.getClass();
063        String name = null;
064        final Optional<Named> named = MoreReflection.extractAnnotation(type, Named.class);
065        if (named.isPresent() && !isEmpty(named.get().value())) {
066            name = named.get().value();
067        }
068        if (null == name) {
069            final var builder = new StringBuilder();
070            builder.append(Character.toLowerCase(type.getSimpleName().charAt(0)));
071            builder.append(type.getSimpleName().substring(1));
072            name = builder.toString();
073        }
074        return register(managedBean, name);
075    }
076
077    /**
078     * In case the beanKey is not an el expression (starting not with '#{') this
079     * method wraps the expression accordingly.
080     *
081     * @param managedBeanKey must not be null or empty
082     * @return the key wrapped as an EL-Expression if needed, otherwise the given
083     *         key.
084     */
085    public static String checkManagedBeanKey(final String managedBeanKey) {
086        requireNonNull(emptyToNull(managedBeanKey), NAME_MUST_NOT_BE_NULL);
087        var elKey = managedBeanKey;
088        if (!elKey.startsWith(EL_START)) {
089            elKey = String.format(EL_WRAPPER, elKey);
090        }
091        return elKey;
092    }
093
094    /**
095     * Utility method for accessing a concrete bean
096     *
097     * @param name         May be a correct value-expression or not (actual name
098     *                     only). Must not be null nor empty.
099     * @param facesContext to be used for accessing the bean
100     * @param expectedType identifying the type to be checked
101     * @return the registered bean for a given type or null, if none could be found
102     */
103    public static <T> T getBean(final String name, final FacesContext facesContext, final Class<T> expectedType) {
104        requireNonNull(facesContext);
105        requireNonNull(name);
106        requireNonNull(expectedType);
107        return facesContext.getApplication().evaluateExpressionGet(facesContext, checkManagedBeanKey(name), expectedType);
108    }
109
110    @java.lang.SuppressWarnings("all")
111    @lombok.Generated
112    public BeanConfigDecorator(@NonNull final FacesContext facesContext) {
113        if (facesContext == null) {
114            throw new java.lang.NullPointerException("facesContext is marked non-null but is null");
115        }
116        this.facesContext = facesContext;
117    }
118}