/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: PathInfoMapping.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.engine; import com.uwyn.rife.engine.exceptions.EngineException; import com.uwyn.rife.engine.exceptions.PathInfoMappingPatternInvalidException; import com.uwyn.rife.tools.StringUtils; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; public class PathInfoMapping { public final static Pattern PATHINFO_SPEC_PATTERN = Pattern.compile("(?<!\\\\)\\$\\{?(\\w+)\\}?(?>\\(([^()]*)\\))?"); // (?<!\\)\$\{?(\w+)\}?(?>\(([^()]*)\))? private String mSpecification = null; private Pattern mRegexp = null; private List<String> mInputs = null; private List<PathInfoMappingSegment> mSegments = null; private PathInfoMapping(String specification) { mSpecification = specification; mInputs = new ArrayList<String>(); mSegments = new ArrayList<PathInfoMappingSegment>(); } public String getSpecification() { return mSpecification; } public Pattern getRegexp() { return mRegexp; } public List<String> getInputs() { return mInputs; } public List<PathInfoMappingSegment> getSegments() { return mSegments; } static PathInfoMapping create(String specification) throws EngineException { PathInfoMapping mapping = new PathInfoMapping(specification); if (null == specification) { return null; } if (!specification.startsWith("/")) { specification = "/"+specification; } Matcher matcher = PATHINFO_SPEC_PATTERN.matcher(specification); if (!matcher.find()) { mapping.mRegexp = Pattern.compile(StringUtils.encodeRegexp(specification)); mapping.mSegments.add(PathInfoMappingSegment.createLiteralSegment(specification)); return mapping; } int last_group_end = 0; StringBuilder mapping_regexp = new StringBuilder(); while (2 == matcher.groupCount()) { // retrieve the text literal between the previous match and the current one String literal = specification.substring(last_group_end, matcher.start()); if (literal.length() > 0) { mapping_regexp.append(StringUtils.encodeRegexp(literal)); mapping.mSegments.add(PathInfoMappingSegment.createLiteralSegment(literal)); } // obtain the input name String input_name = matcher.group(1); mapping.mInputs.add(input_name); // obtain the input matcher pattern String input_pattern = matcher.group(2); // use the default pattern if none is provided if (null == input_pattern || 0 == input_pattern.length()) { input_pattern = "\\w+"; } // check if the pattern syntax is valid Pattern pattern; try { pattern = Pattern.compile(input_pattern); } catch (PatternSyntaxException e) { throw new PathInfoMappingPatternInvalidException(specification, input_name, input_pattern, e); } mapping_regexp.append("("); mapping_regexp.append(input_pattern); mapping_regexp.append(")"); mapping.mSegments.add(PathInfoMappingSegment.createRegexpSegment(pattern)); // remember the end in this match last_group_end = matcher.end(); // check if there are any more matches if (!matcher.find()) { break; } } // retrieve the text literal at the end String literal = specification.substring(last_group_end); if (literal.length() > 0) { mapping_regexp.append(StringUtils.encodeRegexp(literal)); mapping.mSegments.add(PathInfoMappingSegment.createLiteralSegment(literal)); } mapping.mRegexp = Pattern.compile(mapping_regexp.toString()); return mapping; } }