com.braffdev.server.core.module.mapping.MappingModule.java Source code

Java tutorial

Introduction

Here is the source code for com.braffdev.server.core.module.mapping.MappingModule.java

Source

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                         *
 *  Copyright (C) 2015, Markus Staudt <info@braffdev.com>                  *
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program 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 General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

package com.braffdev.server.core.module.mapping;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.braffdev.server.core.Constants;
import com.braffdev.server.core.http.method.HttpMethod;
import com.braffdev.server.core.module.Module;
import com.braffdev.server.core.module.mapping.exception.MappingAlreadyExistsException;
import com.braffdev.server.core.module.mapping.pattern.PatternConverter;
import com.braffdev.server.core.module.mapping.pattern.PatternInfo;
import com.braffdev.server.core.module.mapping.requesthandler.RequestHandler;
import com.braffdev.server.core.module.mapping.requesthandler.RequestHandlerInfo;

/**
 *
 */
public class MappingModule extends Module {

    private List<Mapping> mappings;

    /**
     *
     */
    public MappingModule() {
        this.mappings = new ArrayList<Mapping>();
    }

    /**
     *
     */
    @Override
    public String getName() {
        return Constants.Module.NAME_MAPPING;
    }

    /**
     * @param m
     * @throws MappingAlreadyExistsException
     */
    public void add(String uri, HttpMethod method, RequestHandler handler) throws MappingAlreadyExistsException {
        this.add(new PatternConverter().convert(uri), method, handler);
    }

    /**
     * @param pattern
     * @param method
     * @param handler
     * @throws MappingAlreadyExistsException
     */
    public void add(PatternInfo patternInfo, HttpMethod method, RequestHandler handler)
            throws MappingAlreadyExistsException {

        int index = this.indexOf(patternInfo);
        if (index == -1) {
            // there is no such mapping yet
            // create a new one!
            this.createMapping(patternInfo, method, handler);

        } else {
            // mapping already exists
            Mapping mapping = this.mappings.get(index);
            // check if the method we want to map is already mapped
            if (!mapping.getHandlerMapping().containsKey(method)) {
                mapping.getHandlerMapping().put(method, handler);

            } else {
                throw new MappingAlreadyExistsException(
                        "There is already a mapping for " + patternInfo.getPattern() + " on the method " + method);

            }
        }

        Collections.sort(this.mappings);
    }

    /**
     * @param pattern
     * @param method
     * @param handler
     */
    public void remove(PatternInfo patternInfo, HttpMethod method, RequestHandler handler) {
        int index = this.indexOf(patternInfo);
        if (index != -1) {
            Mapping mapping = this.mappings.get(index);
            mapping.getHandlerMapping().remove(method);

            if (mapping.getHandlerMapping().isEmpty()) {
                this.mappings.remove(index);// empty - remove whole mapping
            }
        }
    }

    /**
     * @param pattern
     * @return
     */
    private int indexOf(PatternInfo patternInfo) {
        synchronized (this.mappings) {
            for (int i = 0; i < this.mappings.size(); i++) {
                Mapping mapping = this.mappings.get(i);

                if (mapping.getPatternInfo().getPattern().pattern().equals(patternInfo.getPattern().pattern())) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * @param pattern
     * @param method
     * @param handler
     */
    private void createMapping(PatternInfo patternInfo, HttpMethod method, RequestHandler handler) {
        String pattern = patternInfo.getPattern().pattern();

        Mapping mapping = new Mapping();
        mapping.setPatternInfo(patternInfo);
        mapping.setLevels(StringUtils.countMatches(pattern, "/"));
        mapping.getHandlerMapping().put(method, handler);
        mapping.setType(MappingType.get(pattern));

        this.mappings.add(mapping);

    }

    /**
     * @return
     */
    public RequestHandlerInfo lookup(String uri, HttpMethod method) {
        Mapping mapping = this.lookupInternalMapping(uri);

        if (mapping != null) {
            return this.mappingLookup(mapping, method);
        }
        return null;

    }

    /**
     * @param uri
     * @return
     */
    public Mapping lookupInternalMapping(String uri) {
        // check all direct mappings first
        for (Mapping mapping : this.mappings) {
            if (mapping.getType() != MappingType.DIRECT) {
                continue;
            }

            Pattern pattern = mapping.getPatternInfo().getPattern();
            if (pattern.matcher(uri).matches()) {
                return mapping;
            }
        }

        // check wildcard mappings
        for (Mapping mapping : this.mappings) {
            if (mapping.getType() != MappingType.WILDCARD) {
                continue;
            }

            Pattern pattern = mapping.getPatternInfo().getPattern();
            if (pattern.matcher(uri).matches()) {
                return mapping;
            }
        }

        return null;
    }

    /**
     * @param mapping
     * @param method
     * @return
     */
    private RequestHandlerInfo mappingLookup(Mapping mapping, HttpMethod method) {
        Map<HttpMethod, RequestHandler> handlerMapping = mapping.getHandlerMapping();

        RequestHandler requestHandler = handlerMapping.get(method);
        if ((requestHandler == null) && (method != HttpMethod.ALL)) {
            // fallback
            requestHandler = handlerMapping.get(HttpMethod.ALL);
        }

        RequestHandlerInfo info = null;
        if (requestHandler != null) {
            info = new RequestHandlerInfo();
            info.setRequestHandler(requestHandler);
            info.setPatternInfo(mapping.getPatternInfo());
        }

        return info;
    }

    /**
     *
     */
    public List<Mapping> getMappings() {
        return this.mappings;
    }
}