org.fenixedu.bennu.spring.portal.PortalHandlerMapping.java Source code

Java tutorial

Introduction

Here is the source code for org.fenixedu.bennu.spring.portal.PortalHandlerMapping.java

Source

/**
 * Copyright  2014 Instituto Superior Tcnico
 *
 * This file is part of Bennu Spring.
 *
 * Bennu Spring is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Bennu Spring is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Bennu Spring.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fenixedu.bennu.spring.portal;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.fenixedu.bennu.core.util.CoreConfiguration;
import org.fenixedu.bennu.portal.model.Application;
import org.fenixedu.bennu.portal.model.ApplicationRegistry;
import org.fenixedu.bennu.portal.model.Functionality;
import org.fenixedu.commons.i18n.LocalizedString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

public class PortalHandlerMapping extends RequestMappingHandlerMapping {

    private static final Logger logger = LoggerFactory.getLogger(PortalHandlerMapping.class);

    private static final String[] EMPTY_ARRAY = new String[0];
    public static final String DELEGATE = "$DELEGATE_TO_PARENT$";

    @Autowired
    private MessageSource messageSource;

    private final Map<Class<?>, Functionality> functionalities = new HashMap<>();
    private final Map<Class<?>, Application> applicationClasses = new HashMap<>();

    @Override
    protected void initHandlerMethods() {
        registerApplications(getApplicationContext().getBeansWithAnnotation(SpringApplication.class).values());
        registerFunctionalities(getApplicationContext().getBeansWithAnnotation(SpringFunctionality.class).values());
        registerLonelyControllers(
                getApplicationContext().getBeansWithAnnotation(BennuSpringController.class).values());
        super.initHandlerMethods();
    }

    private void registerLonelyControllers(Collection<Object> values) {
        for (Object bean : values) {
            Class<?> type = bean.getClass();
            Class<?> functionalityType = AnnotationUtils.findAnnotation(type, BennuSpringController.class).value();
            Functionality functionality = functionalities.get(functionalityType);
            if (functionality == null) {
                throw new Error("Controller " + type.getName() + " declares " + functionalityType.getName()
                        + " as a functionality, but it is not one...");
            }
            functionalities.put(type, functionality);
        }
    }

    private void registerApplications(Collection<Object> values) {
        for (Object bean : values) {
            Class<?> type = bean.getClass();
            SpringApplication app = AnnotationUtils.findAnnotation(type, SpringApplication.class);
            LocalizedString title = getLocalized(app.title());
            Application application = new Application(type.getName(), app.path(), app.group(), title,
                    app.description().equals(DELEGATE) ? title : getLocalized(app.description()), app.hint());
            applicationClasses.put(type, application);
            ApplicationRegistry.registerApplication(application);
            logger.debug("Registered application for type {}", type);
        }
    }

    private void registerFunctionalities(Collection<Object> values) {
        for (Object bean : values) {
            Class<?> type = bean.getClass();
            SpringFunctionality model = AnnotationUtils.findAnnotation(type, SpringFunctionality.class);
            RequestMapping mapping = AnnotationUtils.findAnnotation(type, RequestMapping.class);
            if (mapping == null) {
                throw new Error("Functionality type " + type.getName() + " does not declare a @RequestMapping!");
            }
            Application app = applicationClasses.get(model.app());
            String path = extractPath(mapping, type);
            LocalizedString title = getLocalized(model.title());
            Functionality functionality = new Functionality(SpringPortalBackend.BACKEND_KEY, "/" + path,
                    path.replace('/', '-'),
                    model.accessGroup().equals(DELEGATE) ? app.getAccessGroup() : model.accessGroup(), title,
                    model.description().equals(DELEGATE) ? title : getLocalized(model.description()));
            app.addFunctionality(functionality);
            functionalities.put(type, functionality);
        }
    }

    private String extractPath(RequestMapping mapping, Class<?> type) {
        if (ObjectUtils.isEmpty(mapping.value())) {
            throw new Error(
                    "Functionality type " + type.getName() + " does not declare any @RequestMapping mappings!");
        }
        String path = mapping.value()[0];
        return path.startsWith("/") ? path.substring(1) : path;
    }

    @Override
    protected HandlerMethod createHandlerMethod(Object handler, Method method) {
        HandlerMethod handlerMethod = super.createHandlerMethod(handler, method).createWithResolvedBean();
        Functionality functionality = functionalities.get(handlerMethod.getBeanType());
        return new PortalHandlerMethod(handlerMethod, functionality);
    }

    private LocalizedString getLocalized(String key) {
        LocalizedString.Builder builder = new LocalizedString.Builder();
        for (Locale locale : CoreConfiguration.supportedLocales()) {
            builder.with(locale, messageSource.getMessage(key, EMPTY_ARRAY, "!!" + key + "!!", locale));
        }
        return builder.build();
    }

}