/* * This file is part of the URI Template library. * * For licensing information please see the file license.txt included in the release. * A copy of this licence can also be found at * http://www.opensource.org/licenses/artistic-license-2.0.php */ package org.weborganic.furi; import java.util.Hashtable; import java.util.Map; import org.weborganic.furi.Variable.Reserved; /** * A factory for URI tokens. * * <p>Tokens can be instantiated from an expression which is specific to each token. * * @see TokenLiteral * @see TokenVariable * @see TokenOperatorD3 * @see TokenOperatorPS * * @author Christophe Lauret * @version 6 November 2009 */ public class TokenFactory { /** * A syntax to use for creating tokens. * * @author Christophe Lauret * @version 6 November 2009 */ public enum Syntax { /** * Use the syntax defined in Draft 3 of the URI templates. */ DRAFT3 { @Override protected Token newExpansion(String exp) { // an operator as defined in Draft 3 if (exp.indexOf('|') >= 0) { return TokenOperatorD3.parse(exp); // assume a variable } else { return new TokenVariable(Variable.parse(exp)); } } }, /** * Use a syntax currently used in PageSeeder and based on what was suggested * by Roy T Fielding on the W3C URI listing in October 2008. */ PAGESEEDER { @Override protected Token newExpansion(String exp) { // possibly Roy Fielding's operators if (!Character.isLetter(exp.charAt(0)) && !Character.isDigit(exp.charAt(0))) { return TokenOperatorPS.parse(exp); // assume a variable } else { return new TokenVariable(Variable.parse(exp)); } } }, /** * Use a syntax based on the draft as of 29 October 2009. */ DRAFTX { @Override protected Token newExpansion(String exp) { // possibly Roy Fielding's operators if (!Character.isLetter(exp.charAt(0)) && !Character.isDigit(exp.charAt(0))) { return TokenOperatorDX.parse(exp); // maybe a collection } else if (exp.indexOf(',') >= 0) { return TokenOperatorDX.parse(exp); // assume a variable } else { return new TokenVariable(Variable.parse(exp)); } } }; /** * Generates a template expansion token corresponding to the specified expression. * * @param exp The expression within the curly brackets {}. * * @return The corresponding token instance. * * @throws URITemplateSyntaxException If the expression could not be parsed as a valid token. */ protected abstract Token newExpansion(String exp); } /** * Factories for reuse. */ private static final Map<Syntax, TokenFactory> FACTORIES = new Hashtable<Syntax, TokenFactory>(); static { for (Syntax syntax : Syntax.values()) { FACTORIES.put(syntax, new TokenFactory(syntax)); } } /** * The URI template syntax to use for generating tokens. */ private Syntax _syntax; /** * Prevents creation of instances. * * @param syntax The URI template syntax to use for generating tokens. */ private TokenFactory(Syntax syntax) { this._syntax = syntax; } /** * Generates the token corresponding to the specified expression. * * @param exp The expression. * * @return The corresponding token instance. * * @throws URITemplateSyntaxException If the expression could not be parsed as a valid token. */ public Token newToken(String exp) { // no expression: no token! if (exp == null || exp.length() == 0) return null; // intercept the wild card if ("*".equals(exp)) return newWildcard(); // too short to be anything but a literal int len = exp.length(); if (len < 2) return new TokenLiteral(exp); // a template expansion token if (exp.charAt(0) == '{' && exp.charAt(len - 1) == '}') { // defer to the underlying syntax return this._syntax.newExpansion(exp.substring(1, len - 1)); } // a literal text token return new TokenLiteral(exp); } /** * Generates the token corresponding to the specified expression. * * @param exp The expression. * * @return The corresponding token instance. * * @throws URITemplateSyntaxException If the expression could not be parsed as a valid token. */ public static Token newToken(String exp, Syntax syntax) { TokenFactory factory = getInstance(syntax); return factory.newToken(exp); } /** * Creates a new 'wildcard' token for legacy purposes. * * <p>This is used for conventional URI patterns which have been implemented using "*". * * @return A new 'wildcard' token. */ private static final Token newWildcard() { return new TokenOperatorPS(TokenOperatorPS.Operator.URI_INSERT, new Variable(Reserved.WILDCARD)); } /** * Returns a token factory instance using the default syntax (DRAFTX). * * @return a token factory instance using the default syntax (DRAFTX). */ public static TokenFactory getInstance() { return FACTORIES.get(Syntax.DRAFTX); } /** * Returns a token factory instance. * * @return a token factory instance. */ public static TokenFactory getInstance(Syntax syntax) { return new TokenFactory(syntax); } }