Modifier le fichier

Construction des vues en front office

Théorie

La construction des vues repose sur le modèle MVC.
Une vue est définie par trois éléments :

  • un fichier jsp
  • un preparer
  • un modèle

Le preparer doit récupérer les données nécessaires à la construction du modèle, il met en forme ces données telles qu'elles doivent apparaitre à l'écran et les injecte dans le modèle.
Le modèle est ensuite poussé dans la jsp via le controller.

MVC

Une vue peut correspondre à un organisme, une molécule ou un atome. La page finale affichée à l'écran correspond à un ensemble de vue qui sont combinées et imbriquées.

Dans la pratique

Une vue est définie par un ViewPreparer qui étend AbstractViewPreparer, celui-ci déclare les propriétés suivantes :

  • view : chemin de la jsp
  • type : type de la vue
  • order : ordre de priorité d'utilisation de la vue
  • includedSiteTemplate : liste des codes de template de site pouvant utiliser la vue
  • excludedSiteTemplate : liste des codes de template de site ne pouvant pas utiliser la vue
  • expectedViewTypes : liste des types de vue qui compose la vue

Le preparer définit le modèle qu'il utilise :

public class MyViewPreparer<V extends MyViewModel> extends AbstractViewPreparer<V> {
    ...
}

Le preparer doit posséder les méthodes suivantes :

accept : défini le contexte pour lequel la vue répond. La méthode prend en paramètre un FrontContext et retourne un boolean.

public boolean accept(FrontContext context) {
    return true;
}

prepare : construit le modèle associé à la vue. La méthode prend en paramètre un FrontContext et la liste des viewPreparers qui composent la vue.

public V prepare(final FrontContext context, final Map<String, List<IViewPreparer>> preparers) {
    final V viewModel = super.prepare(frontContext, preparers);
    ...
}

Le modèle

Le modèle porte l'ensemble des données affichées dans la vue, le viewPreparer est en charge d'effectuer la transformation des données afin de les injecter dans le modèle. Le modèle défini une méthode getId() qui retourne l'id utilisé pour l'insertion du modèle dans la jsp.

ArticleViewModel :

public class ArticleViewModel extends AbstractContentViewModel {

    @Override
    public String getId() {
        return "articleViewModel";
    }
}

article.jsp :

<jsp:include page="${articleViewModel.view}"/>

Le modèle possède également une liste de viewModels qui correspondent aux types de vue qui composent la vue.

protected Map<String, IViewModel> viewModels = new HashMap<>();

Il est possible de récupérer la grappe complète de viewModels à plat via la méthode getAllViewModels().

Un point d'extension permet d'effectuer un traitement à postériori de la préparation.
Une fois les différents preparers appelés, on récupère la totalité des bean actifs ordonnés de type ViewModelPostProcessor. On applique alors chaque processor accepé sur les viewModels.

Gestion des inclusions/exclusions des vues dans les templates de site

Par défaut, une vue est incluse dans tous les templates de site existants.

Il est possible de définir une liste de templates ne pouvant pas utiliser la vue via la propriété excludedSiteTemplate. Si un ou plusieurs codes de template sont présents dans les excludedSiteTemplate, la vue va être utilisée par tous les templates SAUF ceux présent dans les excludedSiteTemplate.

Le paramètre includedSiteTemplate est restrictif et absolu. Cela veut dire que si une vue définit un ou plusieurs codes dans la liste des includedSiteTemplate, seules ces templates pourront utiliser la vue. Cela veut également dire que si un code de template est présent dans la liste des includedSiteTemplate et également présent dans la liste des excludedSiteTemplate, l'exclusion n'est pas prise en compte.

Exemple :


<bean id="myViewPreparer1" >
    <property name="includedSiteTemplate">
        <list>
        </list>
    </property>
    <property name="excludedSiteTemplate">
        <list>
        </list>
    </property>
</bean>

<bean id="myViewPreparer2" >
    <property name="includedSiteTemplate">
        <list>
            <value>template2</value>
        </list>
    </property>
    <!-- exclus dans aucun templates de site -->
    <property name="excludedSiteTemplate">
        <list>
        </list>
    </property>
</bean>

<bean id="myViewPreparer3" >
    <property name="includedSiteTemplate">
        <list>
            <value>template1</value>
        </list>
    </property>
    <property name="excludedSiteTemplate">
        <list>
            <value>template1</value>
            <value>template3</value>
        </list>
    </property>
</bean>

<bean id="myViewPreparer4" >
    <!-- inclus par défaut dans tous les templates de site -->
    <property name="includedSiteTemplate">
        <list></list>
    </property>
    <!-- exclus dans aucun templates de site -->
    <property name="excludedSiteTemplate">
        <list>
            <value>template1</value>
            <value>template2</value>
        </list>
    </property>
</bean>

template1template2template3
myViewPreparer1
myViewPreparer2
myViewPreparer3
myViewPreparer4

Récupération des vues pour un template de site

Au démarrage de l'application, le SiteTemplateBeanManager créer une Map contenant la liste des vues regroupées par type pour chaque template de site :

public class SiteTemplateBeanManager extends AbstractBeanManager {

    // Map<codeTemplate, Map<typeVue, List<viewPreparer>>>
    private Map<String, Map<String, List<IViewPreparer>>> viewPreparersByTemplatesSiteAndTypes;
    ...
}

Il est possible de récupérer la liste des viewPreparers pour un template de site comme suit :

final Map<String, List<IViewPreparer>> viewPreparers = SiteTemplateBeanManager.getInstance().getViewPreparersByTemplateSiteCode(context.getInfosSite().getCodeTemplate());

Affichage de la vue

Le controller

L'affichage d'une vue est géré par un controller. Les controllers en charge d'afficher une vue possèdent une liste de handlers typés selon la vue à afficher (fiche, rubrique, search...). La liste de handlers est interrogée afin de récupérer le handler pouvant prendre en charge le contexte courant, puis demande au handler de retourner le ModelAndView correspondant à la vue.

Exemple :

public ModelAndView handleContent(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
    final ContentContext context = initContext(request);
    final Map<String, AbstractContentHandler> handlerList = ApplicationContextManager.getAllActivatedBeansOfType(AbstractContentHandler.class);
    final AbstractContentHandler handler = handlerList.values().stream()
        .filter(h -> h.supports(request, response, context))
        .findFirst()
        .orElse(null);
    return handler.getModelAndView(request, response, context);
}

Les handlers

Les handlers sont en charge de retourner le ModelAndView final au controller.

Un handler doit implémenter com.kosmos.controllers.handlers.ModelAndViewHandler.

public class MyHandler implements ModelAndViewHandler {
    ...
}

Le handler doit posséder une méthode supports qui défini pour quel contexte il répond. Les handlers sont ordonnés afin de pouvoir prioriser plusieurs handlers supportant le même contexte.
Exemple :

@Override
public boolean supports(final HttpServletRequest request, final HttpServletResponse response, final FrontContext frontContext) {
    final ContentContext contentContext = ContentContext.of(frontContext);
    return contentContext.getUrlBean() != null && contentContext.getUrlBean().getIdMetatag() != null;
}

Le handler doit également posséder une méthode getModelAndView en charge de construire le ModelAndView à retourner au controller.
Cette méthode va faire appel ViewModelHelper.prepareViewModel afin de préparer la grappe de viewPreparers qui composent le template que l'on souhaite afficher.

@Override
public ModelAndView getModelAndView(HttpServletRequest request, HttpServletResponse response, final FrontContext frontContext) throws ErreurApplicative {
    final ContentContext contentContext = populateContext(frontContext);
    final AbstractViewModel viewModel = ViewModelHelper.prepareViewModel(DefaultTemplateViewModel.TEMPLATE, contentContext, request, response);
    final ModelAndView modelAndView = new ModelAndView();
    ViewModelHelper.setView(viewModel, modelAndView);
    modelAndView.addAllObjects(viewModel.getAllViewModels());
    return modelAndView;
}

Les templates

Les templates sont des vues globales qui composent la page finale affichée à l'écran, elles sont de type template.
Les templates sont des vues particulières qui représentent le squelette de la page, elles sont utilisées pour regrouper et imbriquer les vues.

<bean id="defaultTemplateViewPreparer" class="com.kosmos.template.DefaultTemplateViewPreparer">
    <property name="type" value="template" />
    <property name="view" value="/WEB-INF/jsp/main.jsp" />
    <property name="expectedViewTypes">
        <list>
            <value>head</value>
            <value>banner</value>
            <value>skiplinks</value>
            <value>header</value>
            <value>breadcrumbs</value>
            <value>body</value>
            <value>footer</value>
            <value>autologin</value>
        </list>
    </property>
</bean>