Skip to content

Commit 2ec372e

Browse files
committed
started to implement advanced search expressions (#153, #135)
1 parent d39d4dc commit 2ec372e

File tree

4 files changed

+219
-0
lines changed

4 files changed

+219
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package net.bootsfaces.expressions;
2+
3+
import java.util.List;
4+
5+
import javax.faces.component.UIComponent;
6+
7+
public interface AbstractExpressionResolver {
8+
public List<UIComponent> resolve(UIComponent component, String parentId, String currentId, String originalExpression);
9+
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* Copyright 2014 Riccardo Massera (TheCoder4.Eu)
3+
*
4+
* This file is part of BootsFaces.
5+
*
6+
* BootsFaces is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* BootsFaces is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with BootsFaces. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package net.bootsfaces.expressions;
20+
21+
import java.util.ArrayList;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
import javax.faces.FacesException;
27+
import javax.faces.component.UIComponent;
28+
import javax.faces.component.UINamingContainer;
29+
import javax.faces.context.FacesContext;
30+
31+
/**
32+
* The ExpressionResolver converts search expressions to component ids.
33+
*
34+
* @author Stephan Rauh, http://www.beyondjava.net
35+
*
36+
*/
37+
public class ExpressionResolver {
38+
39+
private static IDExpressionResolver idExpressionResolver = new IDExpressionResolver();
40+
private static Map<String, AbstractExpressionResolver> resolvers = new HashMap<String, AbstractExpressionResolver>();
41+
42+
public static String getComponentIDs(FacesContext context, UIComponent component, String update) {
43+
List<String> expressions = getExpressions(update);
44+
String result = "";
45+
for (String exp : expressions) {
46+
result += " " + getComponentId(context, component, exp);
47+
}
48+
return result.trim();
49+
}
50+
51+
private static String getComponentId(FacesContext context, UIComponent component, String originalExpression) {
52+
char separatorChar = UINamingContainer.getSeparatorChar(context);
53+
String separator = "" + separatorChar;
54+
String parentId = "";
55+
if (originalExpression.startsWith(":")) {
56+
originalExpression = originalExpression.substring(1);
57+
parentId = ":";
58+
}
59+
String[] subexpressions = originalExpression.split(separator);
60+
for (int i = 0; i < subexpressions.length; i++) {
61+
String currentId = subexpressions[i];
62+
if (currentId != null && currentId.length() > 0) {
63+
parentId = translateSearchExpressionToId(component, parentId, currentId, originalExpression);
64+
} else
65+
throw new FacesException("Invalid search expression: " + originalExpression);
66+
}
67+
68+
UIComponent c = component.findComponent(parentId);
69+
return c.getClientId();
70+
}
71+
72+
private static String translateSearchExpressionToId(UIComponent component, String parentId, String currentId,
73+
String originalExpression) {
74+
try {
75+
List<UIComponent> c;
76+
if (currentId.startsWith("@")) {
77+
AbstractExpressionResolver resolver;
78+
if (resolvers.containsKey(currentId)) {
79+
resolver = resolvers.get(currentId);
80+
} else {
81+
String className = currentId.substring(1, 2).toUpperCase();
82+
if (currentId.length()>2) className += currentId.substring(2);
83+
Class<?> rc = Class.forName("net.bootsfaces.expressions." + className + "ExpressionResolver");
84+
resolver = (AbstractExpressionResolver) rc.newInstance();
85+
synchronized (resolvers) {
86+
if (!resolvers.containsKey(currentId)) resolvers.put(currentId, resolver);
87+
}
88+
}
89+
c = resolver.resolve(component, parentId, currentId, originalExpression);
90+
} else
91+
c = idExpressionResolver.resolve(component, parentId, currentId, originalExpression);
92+
if (null != c && c.size() == 1) {
93+
parentId += ":" + c.get(0).getId();
94+
} else
95+
throw new FacesException("Invalid search expression: " + originalExpression + " resolved to " + parentId
96+
+ ":" + currentId);
97+
return parentId;
98+
} catch (ReflectiveOperationException e) {
99+
throw new FacesException(
100+
"Invalid search expression: " + originalExpression + " The subexpression " + currentId + " doesn't exist");
101+
}
102+
}
103+
104+
public static List<String> getExpressions(String commaSeparatedList) {
105+
List<String> expressions = new ArrayList<String>();
106+
int pos = 0;
107+
int start = 0;
108+
while (pos < commaSeparatedList.length()) {
109+
char c = commaSeparatedList.charAt(pos);
110+
if (c == ' ' | c == ',') {
111+
if (pos - start > 0) {
112+
expressions.add(commaSeparatedList.substring(start, pos));
113+
}
114+
pos++;
115+
start = pos;
116+
continue;
117+
}
118+
if (c == '(') {
119+
pos = readUntilNextParenthesis(commaSeparatedList, pos + 1);
120+
}
121+
pos++;
122+
}
123+
if (pos - start > 0) {
124+
expressions.add(commaSeparatedList.substring(start, pos));
125+
}
126+
return expressions;
127+
}
128+
129+
private static int readUntilNextParenthesis(String commaSeparatedList, int start) {
130+
int pos = start;
131+
while (pos < commaSeparatedList.length()) {
132+
char c = commaSeparatedList.charAt(pos);
133+
if (c == '\'')
134+
readUntilEndOfString(commaSeparatedList, pos + 1);
135+
if (c == ')')
136+
return pos;
137+
pos++;
138+
}
139+
throw new FacesException("invalid search expression - closing parenthesis expected: " + commaSeparatedList
140+
+ " starting at position " + start);
141+
}
142+
143+
private static int readUntilEndOfString(String commaSeparatedList, int start) {
144+
int pos = start;
145+
while (pos < commaSeparatedList.length()) {
146+
char c = commaSeparatedList.charAt(pos);
147+
if (c == '\\')
148+
pos++;
149+
if (c == '\'')
150+
return pos;
151+
pos++;
152+
}
153+
throw new FacesException("invalid search expression - end of string expected: " + commaSeparatedList
154+
+ " starting at position " + start);
155+
}
156+
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package net.bootsfaces.expressions;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import javax.faces.FacesException;
7+
import javax.faces.component.UIComponent;
8+
import javax.faces.component.UIForm;
9+
import javax.faces.component.UIViewRoot;
10+
11+
public class FormExpressionResolver implements AbstractExpressionResolver {
12+
public List<UIComponent> resolve(UIComponent component, String parentId, String currentId, String originalExpression) {
13+
14+
UIComponent c = component;
15+
16+
while (c != null && c.getClass() != UIViewRoot.class) {
17+
System.out.println(c.getClass().getName());
18+
if (UIForm.class.isAssignableFrom(c.getClass())) {
19+
List<UIComponent> result = new ArrayList<UIComponent>();
20+
result.add(c);
21+
return result;
22+
}
23+
c = c.getParent();
24+
}
25+
throw new FacesException("Invalid search expression - the component isn't inside a form " + originalExpression);
26+
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net.bootsfaces.expressions;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import javax.faces.component.UIComponent;
7+
8+
public class IDExpressionResolver implements AbstractExpressionResolver {
9+
public List<UIComponent> resolve(UIComponent component, String parentId, String currentId, String originalExpression) {
10+
String childId;
11+
if (parentId.endsWith(":"))
12+
childId = parentId + ":" + currentId;
13+
else if (parentId.length() > 0)
14+
childId = parentId + ":" + currentId;
15+
else
16+
childId = currentId;
17+
UIComponent c = component.findComponent(childId);
18+
List<UIComponent> result = new ArrayList<UIComponent>();
19+
result.add(c);
20+
return result;
21+
}
22+
23+
}

0 commit comments

Comments
 (0)