All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.weborganic.furi.URIResolver Maven / Gradle / Ivy

There is a newer version: 2.4.33
Show newest version
/*
 * 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import org.weborganic.furi.URIResolveResult.Status;


/**
 * A URI pattern resolver identifies the URI pattern and variables values given a specific URI.
 * 
 * This class is typically used as follows:
 * 
 *   // Create a resolver instance 
 *   URIResolver resolver = new URIResolver("http://www.acme.com/test/home");
 * 
 *   // Find the matching pattern amongst a list of precompiled URI patterns
 *   URIPattern pattern = resolver.find(patterns);
 *   
 *   // Resolve the URI for the specified pattern, the result holds all the matching info
 *   URIResolveResult result = resolver.resolve(p);
 * 
* * * @author Christophe Lauret * @version 11 June 2009 */ public class URIResolver { /** * Defines the priority rule for matching patterns. * * @author Christophe Lauret * @version 10 February 2009 */ public enum MatchRule { /** * Indicates that the first matching pattern should be returned when finding a match in a list * of patterns. The ordering of patterns in the list determines the matching pattern. */ FIRST_MATCH, /** * Indicates that the best matching pattern should be returned when finding a match in a list * of patterns. The best matching patterns is determined by the longest common string. */ BEST_MATCH; } /** * The URI to resolve. */ private String _uri; /** * Creates a new resolver for the specified URI. * * @param uri The URI to resolve. */ public URIResolver(String uri) { this._uri = uri; } /** * Returns the URI handled by this resolver. * * @return The URI handled by this resolver. */ public String uri() { return _uri; } /** * Returns the first URI pattern in the list which matches the underlying URI. * * @param patterns The URI patterns available. * * @return The first URI pattern that matches or null. */ public URIPattern find(List patterns) { return findFirst(patterns); } /** * Returns the first URI pattern in the list which matches the underlying URI. * * @param patterns The URI patterns available. * @param rule The rule used to select the matching patterns in case of multiple matches. * * @return The first URI pattern that matches or null. */ public URIPattern find(List patterns, MatchRule rule) { switch (rule) { case FIRST_MATCH: return findFirst(patterns); case BEST_MATCH: return findBest(patterns); } return null; } /** * Returns all the URI patterns in the list which match the underlying URI. * * This methods returns an empty list if there are no matching patterns. * * @param patterns The URI patterns available. * * @return A collection of matching URI patterns. */ public Collection findAll(List patterns) { Collection matches = new ArrayList(); if (patterns == null || patterns.size() == 0) return matches; for (URIPattern p : patterns) { if (p.match(this._uri)) matches.add(p); } return matches; } /** * Resolves the given URI pattern. * * @param pattern The pattern to resolve. * * @return The URI pattern that best matches the given URI. */ public URIResolveResult resolve(URIPattern pattern) { return resolve(pattern, new VariableBinder()); } /** * Resolves the given URI pattern using the specified variable binder. * * @param pattern The pattern to resolve. * @param binder The variable binder. * * @return The URI pattern that best matches the given URI. */ public URIResolveResult resolve(URIPattern pattern, VariableBinder binder) { URIResolveResult result = new URIResolveResult(pattern); Matcher mx = pattern.pattern().matcher(this._uri); boolean match = mx.matches(); // it is an error condition if there is no match // or if the number of capturing groups is not the same as the number of tokens if (!match || mx.groupCount() != pattern.tokens().size()) { result.setStatus(Status.ERROR); return result; } // extracts the variable token List tokens = pattern.tokens(); Map map = new HashMap(); for (int i = 0; i < mx.groupCount(); i++) { Token mt = tokens.get(i); String s = mx.group(i + 1); mt.resolve(s, map); } // lookup variable values lookup(result, map, binder); return result; } // private helpers ---------------------------------------------------------- /** * Lookup the variable values using the variable resolvers specified in the bindings from the * values mapped to the variables. * * Set the status of the result accordingly. * * @param result Where the results go. * @param map Values mapped to the variables. * @param binder The resolvers to use for each variable. */ private void lookup(URIResolveResult result, Map map, VariableBinder binder) { Status status = Status.RESOLVED; // lookup variable values for (Map.Entry entry : map.entrySet()) { Variable var = entry.getKey(); VariableResolver r = binder.getResolver(var.name(), var.type()); Object value = entry.getValue(); // most common case: a string if (value instanceof String) { Object o = r.resolve(value.toString()); result.put(entry.getKey().name(), o); if (o == null) status = Status.UNRESOLVED; // returned an array of values } else if (value instanceof String[]) { // FIXME: handle arrays status = Status.ERROR; // unknown object } else { status = Status.ERROR; } } result.setStatus(status); } /** * Returns the first URI pattern in the list which matches the underlying URI. * * @param patterns The URI patterns available. * * @return The first URI pattern that matches or null. */ private final URIPattern findFirst(List patterns) { if (patterns == null || patterns.size() == 0) return null; for (URIPattern p : patterns) { if (p.match(this._uri)) return p; } return null; } /** * Returns the best URI pattern in the list which matches the underlying URI. * * @param patterns The URI patterns available. * * @return The best URI pattern that matches or null. */ private final URIPattern findBest(List patterns) { if (patterns == null || patterns.size() == 0) return null; URIPattern best = null; for (URIPattern p : patterns) { if (p.match(this._uri)) { if (best == null || p.score() > best.score()) { best = p; } } } return best; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy