/*
* Copyright (C) 2014 Civilian Framework.
*
* Licensed under the Civilian License (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.civilian-framework.org/license.txt
*
* 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.
*/
package org.civilian.resource;
import org.civilian.response.UriEncoder;
import org.civilian.util.Check;
/**
* PathParam defines how one or more path segments of a request path
* map to a path parameter value.
* To use path parameters in your application you need to perform these steps:
* <ol>
* <li>Create a PathParam object for every path parameter in your application URLs
* and store it into a variable (since a PathParam doesn't have any runtime dependency it is fine
* to store it into a static final constant).
* <li>Add each PathParam object to a {@link PathParamMap}. Again the PathParamMap can be stored
* as a constant.
* <li>In the constructor of your application class pass the PathParamMap to the application base class.
* <li>When a request is dispatched to a controller, path params are automatically recognized.
* and stored in the {@link org.civilian.Request#getPathParam(PathParam) request}.
* </ol>
* @param <T> the type of the path parameter values
*/
public abstract class PathParam<T>
{
/**
* Creates a new PathParam.
* @param name the name of the path parameter
*/
public PathParam(String name)
{
name_ = Check.notNull(name, "name");
}
/**
* Returns the name of the path parameter.
*/
public String getName()
{
return name_;
}
/**
* Returns the type of path parameter values.
*/
public abstract Class<T> getType();
/**
* Parses a path parameter value from a path.
* If a valid path parameter is recognized, the method should
* position the scanner after the matching segments and return
* the value. If no valid path parameter is recognized
* the method should return null and leave the scanner position
* unchanged.
* @param scanner a PathScanner object which provides access to the
* path segments.
*/
public abstract T parse(PathScanner scanner);
/**
* Converts a path parameter value into a path string.
* The returned path should be a valid path string according to the rules
* of {@link Path}.
* @param value path parameter value
* @param encoder a UriEncoder which can be used to encode reserved characters.
*/
public String buildPath(T value, UriEncoder encoder)
{
StringBuilder s = new StringBuilder();
buildPath(value, encoder, s);
return s.toString();
}
/**
* Converts a path parameter value into a path string.
* The returned path should be a valid path string according to the rules
* of {@link Path}.
* @param value path parameter value
* @param encoder a UriEncoder which can be used to encode reserved characters
* @param path the path of the pattern is appended to the StringBuilder
*/
public abstract void buildPath(T value, UriEncoder encoder, StringBuilder path);
/**
* Helper method foe buildPath. Appends a single segment to the path.
*/
protected void buildPathSegment(String segment, UriEncoder encoder, StringBuilder path)
{
Check.notEmpty(segment, "segment");
path.append('/');
encoder.encode(segment, path);
}
/**
* Returns a String containing the match pattern of the PathParam.
* Used by {@link #toDetailedString()}
*/
protected abstract String getPatternString();
/**
* Returns a detailed string representation of the path parameter for debug purposes.
*/
public String toDetailedString()
{
String p = getPatternString();
return "/{" + name_ + " : " + getType().getSimpleName() + (p == null ? "" : "=" + p ) + '}';
}
/**
* Returns a string representation of the path parameter for debug purposes.
*/
@Override public String toString()
{
return "/{" + name_ + '}';
}
private String name_;
}