package act.view; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * Licensed 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. * #L% */ import act.app.App; import act.conf.AppConfig; import act.util.ActContext; import act.util.DestroyableBase; import org.osgl.$; import org.osgl.exception.UnexpectedException; import org.osgl.util.C; import org.osgl.util.E; import org.osgl.util.S; import javax.enterprise.context.ApplicationScoped; import java.util.*; import static act.Destroyable.Util.tryDestroyAll; /** * Manage different view solutions */ public class ViewManager extends DestroyableBase { private C.List<View> viewList = C.newList(); private C.List<ActionViewVarDef> implicitActionViewVariables = C.newList(); private C.List<MailerViewVarDef> implicitMailerViewVariables = C.newList(); private Set<VarDef> appDefined = new HashSet<>(); private Map<String, View> preferredViews = new HashMap<String, View>(); private boolean multiViews = false; void register(View view) { E.NPE(view); if (registered(view)) { throw new UnexpectedException("View[%s] already registered", view.name()); } viewList.add(view); } void register(ImplicitVariableProvider implicitVariableProvider) { E.NPE(implicitVariableProvider); List<ActionViewVarDef> l0 = implicitVariableProvider.implicitActionViewVariables(); for (ActionViewVarDef var : l0) { _register(var, implicitActionViewVariables, false); } List<MailerViewVarDef> l1 = implicitVariableProvider.implicitMailerViewVariables(); for (MailerViewVarDef var : l1) { _register(var, implicitMailerViewVariables, false); } } void registerAppDefinedVar(ActionViewVarDef var) { _register(var, implicitActionViewVariables, true); } void registerAppDefinedVar(MailerViewVarDef var) { _register(var, implicitMailerViewVariables, true); } private <T extends VarDef> void _register(T var, List<T> list, boolean fromApp) { if (list.contains(var)) { throw new UnexpectedException("Implicit variable[%s] has already been registered", var.name()); } list.add(var); if (fromApp) { appDefined.add(var); } } public void clearAppDefinedVars() { implicitActionViewVariables.removeAll(appDefined); implicitMailerViewVariables.removeAll(appDefined); appDefined.clear(); } public void onAppStart() { int viewCount = viewList.size(); multiViews = viewCount > 1; } public void reload(App app) { for (View view : viewList) { view.reload(app); } } public View view(String name) { $.Option<View> viewBag = findViewByName(name); return viewBag.isDefined() ? viewBag.get() : null; } public Template load(ActContext context) { AppConfig config = context.config(); Template cached = context.cachedTemplate(); if (null != cached) { return cached; } TemplatePathResolver resolver = config.templatePathResolver(); String path = resolver.resolve(context); Template template = getTemplate(context, config, path); if (null == template) { String amendedPath = resolver.resolveWithContextMethodPath(context); if (S.neq(amendedPath, path)) { template = getTemplate(context, config, amendedPath); if (null != template) { context.templatePath(amendedPath); } } } return template; } private Template getTemplate(ActContext context, AppConfig config, String path) { String templatePath = S.ensureStartsWith(path, '/'); Template template = null; if (multiViews) { View preferred = preferredViews.get(templatePath); if (null != preferred && preferred.appliedTo(context)) { template = preferred.loadTemplate(templatePath, context); if (null != template) { context.cacheTemplate(template); return template; } } } View defView = config.defaultView(); if (null != defView && defView.appliedTo(context)) { template = defView.loadTemplate(templatePath, context); } if (null == template && multiViews) { for (View view : viewList) { if (view == defView || !view.appliedTo(context)) continue; template = view.loadTemplate(templatePath, context); if (null != template) { if (multiViews) { preferredViews.put(templatePath, view); } break; } } } else if (multiViews) { preferredViews.put(templatePath, defView); } if (null != template) { context.cacheTemplate(template); } return template; } public List<ActionViewVarDef> implicitActionViewVariables() { return C.list(implicitActionViewVariables); } public List<MailerViewVarDef> implicitMailerViewVariables() { return C.list(implicitMailerViewVariables); } public void reset() { viewList.clear(); preferredViews.clear(); } @Override protected void releaseResources() { tryDestroyAll(viewList, ApplicationScoped.class); viewList = null; implicitActionViewVariables.clear(); implicitActionViewVariables = null; implicitMailerViewVariables.clear(); implicitMailerViewVariables = null; preferredViews.clear(); preferredViews = null; } private boolean registered(View view) { final String name = view.name().toUpperCase(); return findViewByName(name).isDefined(); } private $.Option<View> findViewByName(final String name) { return viewList.findFirst(new $.Predicate<View>() { @Override public boolean test(View view) { return view.name().toUpperCase().equals(name.toUpperCase()); } }); } }