/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jsf.cfg;
import java.io.IOException;
import java.util.*;
import java.util.regex.*;
import java.util.logging.*;
import javax.el.*;
import javax.faces.*;
import javax.faces.application.*;
import javax.faces.component.*;
import javax.faces.component.html.*;
import javax.faces.context.*;
import javax.faces.convert.*;
import javax.faces.el.*;
import javax.faces.event.*;
import javax.faces.validator.*;
import com.caucho.config.*;
import com.caucho.util.*;
public class NavigationRule implements Comparable<NavigationRule>
{
private static final Logger log
= Logger.getLogger(NavigationRule.class.getName());
private String _id;
private String _fromViewId;
private Pattern _fromViewIdPattern;
private int _cost;
private ArrayList<NavigationCase> _caseList
= new ArrayList<NavigationCase>();
public void setId(String id)
{
_id = id;
}
public void setDescription(String description)
{
}
public void setDisplayName(String displayName)
{
}
public int getCost()
{
return _cost;
}
public int compareTo(NavigationRule rule)
{
return rule.getCost() - _cost;
}
public void setFromViewId(String viewId)
{
_fromViewId = viewId;
_cost = viewId.length();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < viewId.length(); i++) {
char ch = viewId.charAt(i);
switch (ch) {
case '*':
if (i < _cost)
_cost = i;
sb.append(".*");
break;
case '.': case '?': case '+': case '|': case '[': case ']':
case '$': case '^': case '\\': case '(': case ')':
sb.append("\\");
sb.append(ch);
break;
default:
sb.append(ch);
break;
}
}
_fromViewIdPattern = Pattern.compile(sb.toString());
}
public boolean isMatch(String url)
{
return (_fromViewIdPattern == null
|| _fromViewIdPattern.matcher(url).matches());
}
public void addNavigationCase(NavigationCase navCase)
{
_caseList.add(navCase);
}
public boolean handleNavigation(FacesContext context,
String action,
String outcome)
{
NavigationCase navCase = findCase(action, outcome);
if (navCase != null) {
if (log.isLoggable(Level.FINE))
log.fine("Jsf[" + context.getViewRoot().getViewId() + "] navigation action:" + action + " outcome:" + outcome + " matches " + navCase);
navCase.handleNavigation(context);
return true;
}
return false;
}
private NavigationCase findCase(String action, String outcome)
{
NavigationCase bestCase = null;
int bestCost = -1;
for (int i = 0; i < _caseList.size(); i++) {
NavigationCase navCase = _caseList.get(i);
int cost = 0;
if (navCase.getFromAction() == null) {
}
else if (action != null && action.equals(navCase.getFromAction()))
cost |= 1;
else
continue;
if (navCase.getFromOutcome() == null) {
}
else if (outcome != null && outcome.equals(navCase.getFromOutcome()))
cost |= 2;
else
continue;
if (cost == 3)
return navCase;
else if (bestCost < cost) {
bestCost = cost;
bestCase = navCase;
}
}
return bestCase;
}
public String toString()
{
return "NavigationRule[" + _fromViewIdPattern + "]";
}
public static class NavigationCase {
private String _fromAction;
private String _fromOutcome;
private String _toViewId;
private boolean _isRedirect;
public void setId(String id)
{
}
public void setDescription(String description)
{
}
public void setDisplayName(String displayName)
{
}
public void setFromAction(String expr)
{
_fromAction = expr;
}
public String getFromAction()
{
return _fromAction;
}
public void setFromOutcome(String expr)
{
_fromOutcome = expr;
}
public String getFromOutcome()
{
return _fromOutcome;
}
public void setToViewId(String viewId)
{
_toViewId = viewId;
}
public void setRedirect(Redirect redirect)
{
_isRedirect = true;
}
public void handleNavigation(FacesContext context)
{
if (_isRedirect) {
try {
ExternalContext extContext = context.getExternalContext();
ViewHandler viewHandler = context.getApplication().getViewHandler();
String actionUrl = viewHandler.getActionURL(context, _toViewId);
extContext.redirect(extContext.encodeActionURL(actionUrl));
context.responseComplete();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
else {
UIViewRoot oldView = context.getViewRoot();
ViewHandler view = context.getApplication().getViewHandler();
UIViewRoot viewRoot = view.createView(context, _toViewId);
// XXX: is this in spec?
if (oldView != null)
viewRoot.setLocale(oldView.getLocale());
context.setViewRoot(viewRoot);
}
}
public String toString()
{
if (_isRedirect)
return "NavCase[redirect," + _toViewId + "]";
else
return "NavCase[" + _toViewId + "]";
}
}
public static class Redirect {
public void setId(String id)
{
}
}
}