1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html.util;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import javax.faces.FacesException;
30 import javax.faces.application.ConfigurableNavigationHandler;
31 import javax.faces.application.NavigationCase;
32 import javax.faces.application.NavigationHandler;
33 import javax.faces.application.ProjectStage;
34 import javax.faces.application.ViewHandler;
35 import javax.faces.component.UIComponent;
36 import javax.faces.component.UIOutcomeTarget;
37 import javax.faces.component.UIParameter;
38 import javax.faces.context.FacesContext;
39 import javax.faces.flow.FlowHandler;
40 import javax.faces.lifecycle.ClientWindow;
41 import org.apache.myfaces.shared.application.NavigationUtils;
42 import org.apache.myfaces.shared.renderkit.JSFAttr;
43 import org.apache.myfaces.shared.renderkit.RendererUtils;
44 import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
45
46
47
48
49 public class OutcomeTargetUtils
50 {
51
52 private static final Logger log = Logger.getLogger(OutcomeTargetUtils.class
53 .getName());
54
55 public static String getOutcomeTargetHref(FacesContext facesContext,
56 UIOutcomeTarget component) throws IOException
57 {
58 String outcome = component.getOutcome();
59 outcome = (outcome == null) ? facesContext.getViewRoot().getViewId()
60 : outcome;
61 outcome = ((outcome == null) ? HtmlRendererUtils.STR_EMPTY : outcome.trim());
62
63 NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
64 if (!(nh instanceof ConfigurableNavigationHandler))
65 {
66 throw new FacesException(
67 "Navigation handler must be an instance of "
68 + "ConfigurableNavigationHandler for using h:link or h:button");
69 }
70 ConfigurableNavigationHandler navigationHandler = (ConfigurableNavigationHandler) nh;
71
72
73
74 String toFlowDocumentId = (String) component.getAttributes().get(
75 JSFAttr.TO_FLOW_DOCUMENT_ID_ATTR);
76
77
78 NavigationCase navigationCase = null;
79 if (toFlowDocumentId == null)
80 {
81 navigationCase = navigationHandler.getNavigationCase(
82 facesContext, null, outcome);
83 }
84 else
85 {
86 navigationCase = navigationHandler.getNavigationCase(
87 facesContext, null, outcome, toFlowDocumentId);
88 }
89
90
91 if (navigationCase == null)
92 {
93
94 log.warning("Could not determine NavigationCase for UIOutcomeTarget component "
95 + RendererUtils.getPathToComponent(component) + " with outcome " + outcome);
96
97 return null;
98 }
99 Map<String, List<String>> parameters = null;
100
101 if (component.getChildCount() > 0)
102 {
103 List<UIParameter> validParams = getValidUIParameterChildren(
104 facesContext, component.getChildren(), true, false);
105 if (validParams.size() > 0)
106 {
107 parameters = new HashMap<String, List<String>>();
108 }
109 for (int i = 0, size = validParams.size(); i < size; i++)
110 {
111 UIParameter param = validParams.get(i);
112 String name = param.getName();
113 Object value = param.getValue();
114 if (parameters.containsKey(name))
115 {
116 parameters.get(name).add(value.toString());
117 }
118 else
119 {
120 List<String> list = new ArrayList<String>(1);
121 list.add(value.toString());
122 parameters.put(name, list);
123 }
124 }
125 }
126
127
128
129 if (navigationCase.getToFlowDocumentId() != null)
130 {
131 if (parameters == null)
132 {
133 parameters = new HashMap<String, List<String>>();
134 }
135 if (!parameters.containsKey(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME))
136 {
137 List<String> list = new ArrayList<String>(1);
138 list.add(navigationCase.getToFlowDocumentId());
139 parameters.put(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, list);
140 }
141 if (!parameters.containsKey(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME))
142 {
143 List<String> list2 = new ArrayList<String>(1);
144 list2.add(navigationCase.getFromOutcome());
145 parameters.put(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, list2);
146 }
147 }
148
149
150 Map<String, List<String>> navigationCaseParams =
151 NavigationUtils.getEvaluatedNavigationParameters(facesContext,
152 navigationCase.getParameters());
153 if (navigationCaseParams != null)
154 {
155 if (parameters == null)
156 {
157 parameters = new HashMap<String, List<String>>();
158 }
159
160 for (Map.Entry<String, List<String>> entry : navigationCaseParams
161 .entrySet())
162 {
163 if (!parameters.containsKey(entry.getKey()))
164 {
165 parameters.put(entry.getKey(), entry.getValue());
166 }
167 }
168 }
169 if (parameters == null)
170 {
171 parameters = Collections.emptyMap();
172 }
173 boolean disableClientWindow = component.isDisableClientWindow();
174 ClientWindow clientWindow = facesContext.getExternalContext().getClientWindow();
175 String href;
176 try
177 {
178 if (clientWindow != null && disableClientWindow)
179 {
180 clientWindow.disableClientWindowRenderMode(facesContext);
181 }
182
183
184
185 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
186 href = viewHandler.getBookmarkableURL(facesContext,
187 navigationCase.getToViewId(facesContext),
188 parameters, navigationCase.isIncludeViewParams() || component.isIncludeViewParams());
189 }
190 finally
191 {
192 if (clientWindow != null && disableClientWindow)
193 {
194 clientWindow.enableClientWindowRenderMode(facesContext);
195 }
196 }
197
198 String fragment = (String) component.getAttributes().get("fragment");
199 if (fragment != null)
200 {
201 fragment = fragment.trim();
202
203 if (fragment.length() > 0)
204 {
205 href += "#" + fragment;
206 }
207 }
208 return href;
209 }
210
211
212
213
214
215
216
217
218
219
220 public static List<UIParameter> getValidUIParameterChildren(
221 FacesContext facesContext, List<UIComponent> children,
222 boolean skipNullValue, boolean skipUnrendered)
223 {
224 return getValidUIParameterChildren(facesContext, children,
225 skipNullValue, skipUnrendered, true);
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246 public static List<UIParameter> getValidUIParameterChildren(
247 FacesContext facesContext, List<UIComponent> children,
248 boolean skipNullValue, boolean skipUnrendered, boolean skipNullName)
249 {
250 List<UIParameter> params = null;
251 for (int i = 0, size = children.size(); i < size; i++)
252 {
253 UIComponent child = children.get(i);
254 if (child instanceof UIParameter)
255 {
256 UIParameter param = (UIParameter) child;
257
258
259 if (param.isDisable() || (skipUnrendered && !param.isRendered()))
260 {
261
262 continue;
263 }
264
265 String name = param.getName();
266 if (skipNullName && (name == null || HtmlRendererUtils.STR_EMPTY.equals(name)))
267 {
268
269 log.log(Level.WARNING, "The UIParameter " + RendererUtils.getPathToComponent(param)
270 + " has a name of null or empty string and thus will not be added to the URL.");
271
272 continue;
273 }
274
275 if (skipNullValue && param.getValue() == null)
276 {
277 if (facesContext.isProjectStage(ProjectStage.Development))
278 {
279
280 log.log(Level.INFO, "The UIParameter " + RendererUtils.getPathToComponent(param)
281 + " has a value of null and thus will not be added to the URL.");
282 }
283
284 continue;
285 }
286
287 if (params == null)
288 {
289 params = new ArrayList<UIParameter>();
290 }
291 params.add(param);
292 }
293 }
294 if (params == null)
295 {
296 params = Collections.emptyList();
297 }
298 return params;
299 }
300
301 }