com.quartercode.femtoweb.impl.DefaultContext.java Source code

Java tutorial

Introduction

Here is the source code for com.quartercode.femtoweb.impl.DefaultContext.java

Source

/*
 * This file is part of FemtoWeb.
 * Copyright (c) 2015 QuarterCode <http://quartercode.com/>
 *
 * FemtoWeb 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.
 *
 * FemtoWeb 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FemtoWeb. If not, see <http://www.gnu.org/licenses/>.
 */

package com.quartercode.femtoweb.impl;

import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import com.quartercode.femtoweb.api.Action;
import com.quartercode.femtoweb.api.ActionNotFoundException;
import com.quartercode.femtoweb.api.Context;

/**
 * The default implementation of the {@link Context} interface.
 * This class is used by the {@link FemtoWebFilter}.
 */
public class DefaultContext implements Context {

    private static final String DEFAULT_STATIC_ASSET_PATH = "/static";
    private static final String DEFAULT_DYNAMIC_ASSET_PATH = "/WEB-INF/dynamic";
    private static final String DEFAULT_INDEX_URI = "/index";

    private final String actionBasePackage;
    private final String staticAssetPath;
    private final String dynamicAssetPath;
    private final String indexUri;

    private final Map<Class<? extends Action>, String> actionsToUris = new HashMap<>();
    private final Map<String, Class<? extends Action>> urisToActions = new HashMap<>();

    /**
     * Creates a new default context implementation with the given framework settings.
     *
     * @param actionBasePackage The package which contains all {@link Action}s and action subpackages.
     *        Note that this also functions as a package prefix which is removed from all action packages before they are mapped to URIs.
     *        Thereby, package names like {@code com.quartercode.femtowebtest.actions} are not included in URIs.
     * @param staticAssetPath The {@link #getStaticAssetPath() static asset path}.
     *        If this is blank, a default value is used.
     * @param dynamicAssetPath The {@link #getDynamicAssetPath() dynamic asset path}.
     *        If this is blank, a default value is used.
     * @param indexUri The {@link #getIndexUri() index URI}.
     *        If this is blank, a default value is used.
     */
    public DefaultContext(String actionBasePackage, String staticAssetPath, String dynamicAssetPath,
            String indexUri) {

        Validate.notBlank(actionBasePackage, "Action base package cannot be blank");
        Validate.isTrue(!isClassExistent(actionBasePackage),
                "Provided action base package name ('%s') is a class and not a package", actionBasePackage);

        this.actionBasePackage = actionBasePackage;
        this.staticAssetPath = !StringUtils.isBlank(staticAssetPath) ? preparePath(staticAssetPath)
                : DEFAULT_STATIC_ASSET_PATH;
        this.dynamicAssetPath = !StringUtils.isBlank(dynamicAssetPath) ? preparePath(dynamicAssetPath)
                : DEFAULT_DYNAMIC_ASSET_PATH;
        this.indexUri = !StringUtils.isBlank(indexUri) ? preparePath(indexUri) : DEFAULT_INDEX_URI;
    }

    private boolean isClassExistent(String className) {

        try {
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    private String preparePath(String path) {

        return "/" + StringUtils.strip(path, "/");
    }

    @Override
    public String getStaticAssetPath() {

        return staticAssetPath;
    }

    @Override
    public String getDynamicAssetPath() {

        return dynamicAssetPath;
    }

    @Override
    public String getIndexUri() {

        return indexUri;
    }

    @Override
    public String getUri(Class<? extends Action> action) {

        if (!actionsToUris.containsKey(action)) {
            insertActionUriPair(action, ActionUriResolver.getUri(actionBasePackage, action));
        }

        return actionsToUris.get(action);
    }

    @Override
    public Class<? extends Action> getAction(String uri) throws ActionNotFoundException {

        // By doing this, you are no longer able to flood the cache by requesting the same action with different amounts of repeated "/" at the end
        String effectiveUri = "/" + StringUtils.strip(uri, "/");

        if (!urisToActions.containsKey(effectiveUri)) {
            insertActionUriPair(ActionUriResolver.getAction(actionBasePackage, effectiveUri), effectiveUri);
        }

        return urisToActions.get(effectiveUri);
    }

    private void insertActionUriPair(Class<? extends Action> action, String uri) {

        actionsToUris.put(action, uri);
        urisToActions.put(uri, action);
    }

}