/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the "License"). You may not use this file except * in compliance with the License. * * You can obtain a copy of the license at * http://www.opensource.org/licenses/cddl1.php * See the License for the specific language governing * permissions and limitations under the License. */ /* * PathSegment.java * * Created on August 7, 2006, 1:24 PM * */ package org.jvnet.ws.wadl2java.ast; import java.net.URI; import org.jvnet.ws.wadl.Param; import org.jvnet.ws.wadl.ParamStyle; import org.jvnet.ws.wadl.Resource; import org.jvnet.ws.wadl.ResourceType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import java.util.regex.Matcher; import org.jvnet.ws.wadl2java.ElementResolver; /** * Represents a segment of a URI with zero or more embedded parameters as found * in the path attribute of a WADL resource element. Embedded parameters are * represented as {name} where name is the name of the parameter. This class also * maintains the list of matrix parameters, query parameters and any addition * parameter information supplied using a child WADL param element. */ public class PathSegment { private String template; private List<Param> templateParameters; private List<Param> matrixParameters; private List<Param> queryParameters; private List<Param> headerParameters; /** * Construct a PathSegment instance using a string representation. All parameters * will be treated as string types and no matrix parameters will be specified. * @param template the string version of the template */ public PathSegment(String template) { this(template, null); } /** * Construct a PathSegment instance using a string representation and a list of * matrix parameter names. All parameters will be treated as string types. * @param template the string version of the template * @param matrixParameters a list of matrix parameter names */ public PathSegment(String template, List<String> matrixParameters) { this.template = template; this.templateParameters = new ArrayList<Param>(); this.matrixParameters = new ArrayList<Param>(); this.queryParameters = new ArrayList<Param>(); this.headerParameters = new ArrayList<Param>(); // parse template for embedded parameters Pattern embeddedParamPattern = Pattern.compile("\\{.*?\\}"); Matcher matcher = embeddedParamPattern.matcher(template); while (matcher.find()) { String paramName = matcher.group(); paramName = paramName.substring(1,paramName.length()-1); Param embeddedParam = new Param(); embeddedParam.setName(paramName); templateParameters.add(embeddedParam); } if (matrixParameters != null) { for (String matrixParam: matrixParameters) { Param p = new Param(); p.setName(matrixParam); p.setStyle(ParamStyle.MATRIX); this.matrixParameters.add(p); } } } /** * Creates a new instance of PathSegment from a WADL resource element * @param resource the WADL resource element * @param file the URI of the WADL file that contains the resource element * @param idMap a map of URI reference to WADL definition element */ public PathSegment(Resource resource, URI file, ElementResolver idMap) { template = resource.getPath() == null ? "" : resource.getPath(); this.templateParameters = new ArrayList<Param>(); this.matrixParameters = new ArrayList<Param>(); this.queryParameters = new ArrayList<Param>(); this.headerParameters = new ArrayList<Param>(); // iterate through child param elements to extract params Map<String, Param> pathParameters = new HashMap<String, Param>(); for (Param p: resource.getParam()) { p = derefIfRequired(p, file, idMap); if (p==null) continue; else if (p.getStyle() == null || p.getStyle() == ParamStyle.TEMPLATE) pathParameters.put(p.getName(), p); else if (p.getStyle() == ParamStyle.MATRIX) matrixParameters.add(p); else if (p.getStyle() == ParamStyle.QUERY) queryParameters.add(p); else if (p.getStyle() == ParamStyle.HEADER) headerParameters.add(p); } // parse template for embedded parameters Pattern embeddedParamPattern = Pattern.compile("\\{.*?\\}"); Matcher matcher = embeddedParamPattern.matcher(template); while (matcher.find()) { String paramName = matcher.group(); paramName = paramName.substring(1,paramName.length()-1); // if embedded parameter is annotated by child param then use that // otherwise create a new empty param for it if (pathParameters.containsKey(paramName)) templateParameters.add(pathParameters.get(paramName)); else { Param embeddedParam = new Param(); embeddedParam.setName(paramName); templateParameters.add(embeddedParam); } } } /** * Creates a new instance of PathSegment from a WADL resource type element * @param resource the WADL resource type element * @param file the URI of the WADL file that contains the resource type element * @param idMap a map of URI reference to WADL definition element */ public PathSegment(ResourceType resource, URI file, ElementResolver idMap) { template = null; templateParameters = new ArrayList<Param>(); matrixParameters = new ArrayList<Param>(); queryParameters = new ArrayList<Param>(); headerParameters = new ArrayList<Param>(); // iterate through child param elements to extract params Map<String, Param> pathParameters = new HashMap<String, Param>(); for (Param p: resource.getParam()) { p = derefIfRequired(p, file, idMap); if (p==null) continue; else if (p.getStyle() == ParamStyle.QUERY) queryParameters.add(p); else if (p.getStyle() == ParamStyle.MATRIX) matrixParameters.add(p); else if (p.getStyle() == ParamStyle.HEADER) headerParameters.add(p); } } /** * Dereference a param reference element if required. * @param p the param reference or definition * @param file the URI of the WADL file containing the param reference or definition * @param idMap a map of URI reference to WADL definition element * @return the param definition element */ protected static Param derefIfRequired(Param p, URI file, ElementResolver idMap) { String href = p.getHref(); if (href!=null && href.length()>0) return idMap.resolve(file, href, Param.class); else return p; } /** * Get the underlying path segment template string * @return the path segment template string */ public String getTemplate() { return template; } /** * Get a list of parameters embedded within the underlying path segment template. * E.g. if the template string is {p1}/xyzzy/{p2} this will return a list of two * parameters: p1 and p2. * @return the names of the parameters embedded within the template */ public List<Param> getTemplateParameters() { return templateParameters; } /** * Get list of matrix parameters attached to the path segment * @return a list of matrix parameter names */ public List<Param> getMatrixParameters() { return matrixParameters; } /** * Get list of query parameters attached to the path segment * @return a list of query parameter names */ public List<Param> getQueryParameters() { return queryParameters; } /** * Get list of header parameters attached to the path segment * @return a list of header parameter names */ public List<Param> getHeaderParameters() { return headerParameters; } /** * Merges the supplied parameter values into the path segment template and returns * the resulting path segment. E.g. if the template is "{p1}/{p2}" with a matrix * parameter p3 and the values of p1, p2 and p3 are "v1", "v2" and "v3" * respectively the returned path segment would be "v1/v2;p3=v3". * Query parameters are ignored. * @param parameterValues a map of parameter names to values. Values can be of any class, evaluate uses * the object's toString method to obtain the stringified value. * @return the path segment resulting from inserting the parameter values into the template */ public String evaluate(Map<String, Object> parameterValues) { String retVal = template; if (parameterValues==null) parameterValues = new HashMap<String, Object>(); for (Param param: templateParameters) { String paramName = param.getName(); String paramValue = ""; if (parameterValues.containsKey(paramName)) paramValue = parameterValues.get(paramName).toString(); else if (param.isRequired()) throw new IllegalArgumentException( AstMessages.TEMPLATE_VALUE_MISSING(paramName)); retVal = retVal.replaceAll("\\{"+paramName+"\\}", paramValue); } StringBuffer buf = new StringBuffer(retVal); for (Param param: matrixParameters) { String paramName = param.getName(); Object paramObject = null; if (parameterValues.containsKey(paramName)) { paramObject = parameterValues.get(paramName); } else if (param.isRequired()) throw new IllegalArgumentException( AstMessages.MATRIX_VALUE_MISSING(paramName)); if (paramObject==null) continue; if (paramObject instanceof Boolean) { Boolean b = (Boolean)paramObject; if (b.booleanValue()) { buf.append(';'); buf.append(paramName); } } else { buf.append(';'); buf.append(paramName); buf.append('='); buf.append(String.valueOf(paramObject)); } } return buf.toString(); } }