001// Generated by delombok at Sun Jul 30 17:21:56 UTC 2023
002package de.cuioss.test.jsf.config.decorator;
003
004import java.util.Collection;
005import java.util.Locale;
006import java.util.ResourceBundle;
007import javax.faces.application.Application;
008import javax.faces.application.ApplicationWrapper;
009import javax.faces.application.NavigationCase;
010import javax.faces.application.NavigationHandler;
011import javax.faces.application.ProjectStage;
012import javax.faces.context.ExternalContext;
013import javax.faces.context.FacesContext;
014import javax.servlet.http.HttpServletRequest;
015import org.apache.myfaces.test.config.ResourceBundleVarNames;
016import org.apache.myfaces.test.mock.MockApplication20;
017import org.apache.myfaces.test.mock.MockHttpServletRequest;
018import org.apache.myfaces.test.mock.MockServletContext;
019import de.cuioss.test.jsf.mocks.CuiMockConfigurableNavigationHandler;
020import de.cuioss.tools.reflect.FieldWrapper;
021
022/**
023 * Helper class acting as runtime-registry for {@link ResourceBundle},
024 * {@link NavigationHandler},
025 *
026 * @author Oliver Wolff
027 */
028public class ApplicationConfigDecorator {
029    private final Application application;
030    private final FacesContext facesContext;
031
032    /**
033     * Registers a {@link ResourceBundle} to a given name
034     *
035     * @param bundleName the name of the bundle to be registered to
036     * @param bundlePath the path to the {@link ResourceBundle}
037     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
038     *         fluent-api style usage
039     */
040    public ApplicationConfigDecorator registerResourceBundle(final String bundleName, final String bundlePath) {
041        ResourceBundleVarNames.addVarName(bundleName, bundlePath);
042        return this;
043    }
044
045    /**
046     * Registers the supported {@link Locale}s, see
047     * {@link Application#setSupportedLocales(Collection)}
048     *
049     * @param locales to be registered
050     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
051     *         fluent-api style usage
052     */
053    public ApplicationConfigDecorator registerSupportedLocales(final Collection<Locale> locales) {
054        application.setSupportedLocales(locales);
055        return this;
056    }
057
058    /**
059     * Registers the default {@link Locale}, see
060     * {@link Application#setDefaultLocale(Locale)}
061     *
062     * @param locale to be registered
063     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
064     *         fluent-api style usage
065     */
066    public ApplicationConfigDecorator registerDefaultLocale(final Locale locale) {
067        application.setDefaultLocale(locale);
068        return this;
069    }
070
071    /**
072     * Register a navigation case in a simple way, with two parameter only
073     *
074     * @param outcome  to be registered
075     * @param toViewId to be registered
076     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
077     *         fluent-api style usage
078     */
079    public ApplicationConfigDecorator registerNavigationCase(final String outcome, final String toViewId) {
080        getMockNavigationHandler().addNavigationCase(outcome, new NavigationCase(null, null, outcome, null, toViewId, null, null, true, true));
081        return this;
082    }
083
084    /**
085     * @return an instance of {@link CuiMockConfigurableNavigationHandler} If not
086     *         already configured this method will implicitly register a new
087     *         instance
088     */
089    public CuiMockConfigurableNavigationHandler getMockNavigationHandler() {
090        if (!(application.getNavigationHandler() instanceof CuiMockConfigurableNavigationHandler)) {
091            application.setNavigationHandler(new CuiMockConfigurableNavigationHandler());
092        }
093        return (CuiMockConfigurableNavigationHandler) application.getNavigationHandler();
094    }
095
096    /**
097     * Sets the {@link ProjectStage}. Caution: this method uses hardcore reflection
098     * to access the field with the name "_projectStage", may therefore be fragile.
099     *
100     * @param projectStage to be set
101     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
102     *         fluent-api style usage
103     */
104    public ApplicationConfigDecorator setProjectStage(final ProjectStage projectStage) {
105        var projectStageField = FieldWrapper.from(MockApplication20.class, "_projectStage");
106        if (projectStageField.isEmpty()) {
107            throw new IllegalStateException("Unable to set projectStage, due to underlying Exception");
108        }
109        projectStageField.get().writeValue(getMockApplicationInstance(application), projectStage);
110        return this;
111    }
112
113    private static Object getMockApplicationInstance(final Application application) {
114        if (application instanceof MockApplication20) {
115            return application;
116        }
117        if (application instanceof ApplicationWrapper) {
118            return getMockApplicationInstance(((ApplicationWrapper) application).getWrapped());
119        }
120        return application;
121    }
122
123    /**
124     * Sets the contextPath in {@link HttpServletRequest}
125     *
126     * @param contextPath to be set
127     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
128     *         fluent-api style usage
129     */
130    public ApplicationConfigDecorator setContextPath(final String contextPath) {
131        ((MockHttpServletRequest) facesContext.getExternalContext().getRequest()).setContextPath(contextPath);
132        return this;
133    }
134
135    /**
136     * Registers a concrete InitParameter to
137     * {@link ExternalContext#getInitParameterMap()}
138     *
139     * @param key   used as the key for the
140     *              {@link ExternalContext#getInitParameterMap()}
141     * @param value used as the value for the
142     *              {@link ExternalContext#getInitParameterMap()}
143     * @return the {@link ApplicationConfigDecorator} itself in order to enable a
144     *         fluent-api style usage
145     */
146    public ApplicationConfigDecorator addInitParameter(final String key, final String value) {
147        var context = (MockServletContext) facesContext.getExternalContext().getContext();
148        context.addInitParameter(key, value);
149        return this;
150    }
151
152    @java.lang.SuppressWarnings("all")
153    @lombok.Generated
154    public ApplicationConfigDecorator(final Application application, final FacesContext facesContext) {
155        this.application = application;
156        this.facesContext = facesContext;
157    }
158}