001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.rest.path; 020 021import java.util.ArrayList; 022import java.util.List; 023import java.util.regex.Matcher; 024import java.util.regex.Pattern; 025 026import lucee.runtime.type.Struct; 027 028 029public class ExpressionPath extends Path { 030 031 private Pattern pattern; 032 private List<String> variables; 033 034 public ExpressionPath(Pattern pattern, List<String> variables) { 035 this.pattern=pattern; 036 this.variables=variables; 037 } 038 039 public static Path getInstance(String path) { 040 /* 041 TODO handle if a pattern already has defined a group 042 */ 043 044 int last=-1,startIndex,endIndex=0,index; 045 String content,variableName,regexPart; 046 StringBuilder regex=new StringBuilder(); 047 List<String> variables=new ArrayList<String>(); 048 while((startIndex=path.indexOf('{',last))!=-1){ 049 if(last+1<startIndex) { 050 delimiter(variables,regex,path.substring(last+1,startIndex)); 051 } 052 053 endIndex=path.indexOf('}',startIndex+1); 054 if(endIndex==-1) return new LiteralPath(path); 055 056 content=path.substring(startIndex+1,endIndex); 057 index=content.indexOf(':'); 058 if(index!=-1) { 059 variableName=content.substring(0,index).trim(); 060 regexPart=content.substring(index+1).trim(); 061 } 062 else { 063 variableName=content.trim(); 064 regexPart=".+"; 065 } 066 regex.append('('); 067 regex.append(regexPart); 068 regex.append(')'); 069 variables.add(variableName); 070 //print.e(variableName); 071 //print.e(regexPart); 072 last=endIndex; 073 } 074 075 if(endIndex+1<path.length()) 076 delimiter(variables,regex,path.substring(endIndex+1)); 077 078 //regex.append("(.*)"); 079 080 Pattern pattern=Pattern.compile(regex.toString()); 081 //print.e(regex); 082 //print.e(variables); 083 return new ExpressionPath(pattern,variables); 084 } 085 086 087 private static void delimiter(List<String> variables, StringBuilder regex, String delimiter) { 088 variables.add(null); 089 regex.append('('); 090 /*print.e(delimiter+":"+Pattern.quote(delimiter)); 091 StringBuilder sb=new StringBuilder(); 092 int len=delimiter.length(); 093 char c; 094 for (int i=0; i<len; i++) { 095 c=delimiter.charAt(i); 096 switch(c){ 097 case '.': sb.append("\\.");break; 098 case '?': sb.append("\\?");break; 099 case '\\': sb.append("\\\\");break; 100 case '^': sb.append("\\^");break; 101 case '$': sb.append("\\$");break; 102 case '+': sb.append("\\+");break; 103 default: sb.append(c); 104 break; 105 } 106 }*/ 107 108 regex.append(Pattern.quote(delimiter)); 109 regex.append(')'); 110 } 111 112 @Override 113 public boolean match(Struct result,String path) { 114 String var; 115 Matcher m = pattern.matcher(path); 116 boolean hasMatches=m.find(); 117 if(!hasMatches) return false; 118 119 if (hasMatches) { 120 // Get all groups for this match 121 int len=m.groupCount(); 122 for (int i=1; i<=len; i++) { 123 String groupStr = m.group(i); 124 var = variables.get(i-1); 125 if(var!=null) result.setEL(var, groupStr.trim()); 126 } 127 } 128 129 return true; 130 } 131 132 /*public static void main(String[] args) { 133 Path path = getInstance("{aaa : \\d+}-{b}"); 134 print.e("+++++++++++"); 135 Map<String,String> res=new HashMap<String, String>(); 136 print.e(path.match(res,"1234-cd")); 137 print.e(res); 138 }*/ 139 140 141 142 public String toString(){ 143 return "expression:"+pattern.pattern(); 144 } 145}