001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: PathInfoMapping.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.engine;
009:
010: import com.uwyn.rife.engine.exceptions.EngineException;
011: import com.uwyn.rife.engine.exceptions.PathInfoMappingPatternInvalidException;
012: import com.uwyn.rife.tools.StringUtils;
013: import java.util.ArrayList;
014: import java.util.List;
015: import java.util.regex.Matcher;
016: import java.util.regex.Pattern;
017: import java.util.regex.PatternSyntaxException;
018:
019: public class PathInfoMapping {
020: public final static Pattern PATHINFO_SPEC_PATTERN = Pattern
021: .compile("(?<!\\\\)\\$\\{?(\\w+)\\}?(?>\\(([^()]*)\\))?"); // (?<!\\)\$\{?(\w+)\}?(?>\(([^()]*)\))?
022:
023: private String mSpecification = null;
024: private Pattern mRegexp = null;
025: private List<String> mInputs = null;
026: private List<PathInfoMappingSegment> mSegments = null;
027:
028: private PathInfoMapping(String specification) {
029: mSpecification = specification;
030: mInputs = new ArrayList<String>();
031: mSegments = new ArrayList<PathInfoMappingSegment>();
032: }
033:
034: public String getSpecification() {
035: return mSpecification;
036: }
037:
038: public Pattern getRegexp() {
039: return mRegexp;
040: }
041:
042: public List<String> getInputs() {
043: return mInputs;
044: }
045:
046: public List<PathInfoMappingSegment> getSegments() {
047: return mSegments;
048: }
049:
050: static PathInfoMapping create(String specification)
051: throws EngineException {
052: PathInfoMapping mapping = new PathInfoMapping(specification);
053:
054: if (null == specification) {
055: return null;
056: }
057:
058: if (!specification.startsWith("/")) {
059: specification = "/" + specification;
060: }
061:
062: Matcher matcher = PATHINFO_SPEC_PATTERN.matcher(specification);
063: if (!matcher.find()) {
064: mapping.mRegexp = Pattern.compile(StringUtils
065: .encodeRegexp(specification));
066: mapping.mSegments.add(PathInfoMappingSegment
067: .createLiteralSegment(specification));
068: return mapping;
069: }
070:
071: int last_group_end = 0;
072:
073: StringBuilder mapping_regexp = new StringBuilder();
074: while (2 == matcher.groupCount()) {
075: // retrieve the text literal between the previous match and the current one
076: String literal = specification.substring(last_group_end,
077: matcher.start());
078: if (literal.length() > 0) {
079: mapping_regexp
080: .append(StringUtils.encodeRegexp(literal));
081: mapping.mSegments.add(PathInfoMappingSegment
082: .createLiteralSegment(literal));
083: }
084:
085: // obtain the input name
086: String input_name = matcher.group(1);
087: mapping.mInputs.add(input_name);
088:
089: // obtain the input matcher pattern
090: String input_pattern = matcher.group(2);
091:
092: // use the default pattern if none is provided
093: if (null == input_pattern || 0 == input_pattern.length()) {
094: input_pattern = "\\w+";
095: }
096:
097: // check if the pattern syntax is valid
098: Pattern pattern;
099: try {
100: pattern = Pattern.compile(input_pattern);
101: } catch (PatternSyntaxException e) {
102: throw new PathInfoMappingPatternInvalidException(
103: specification, input_name, input_pattern, e);
104: }
105:
106: mapping_regexp.append("(");
107: mapping_regexp.append(input_pattern);
108: mapping_regexp.append(")");
109: mapping.mSegments.add(PathInfoMappingSegment
110: .createRegexpSegment(pattern));
111:
112: // remember the end in this match
113: last_group_end = matcher.end();
114:
115: // check if there are any more matches
116: if (!matcher.find()) {
117: break;
118: }
119: }
120:
121: // retrieve the text literal at the end
122: String literal = specification.substring(last_group_end);
123: if (literal.length() > 0) {
124: mapping_regexp.append(StringUtils.encodeRegexp(literal));
125: mapping.mSegments.add(PathInfoMappingSegment
126: .createLiteralSegment(literal));
127: }
128:
129: mapping.mRegexp = Pattern.compile(mapping_regexp.toString());
130:
131: return mapping;
132: }
133: }
|