/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package javax.faces.application; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import java.util.List; import javax.el.ValueExpression; import javax.el.ExpressionFactory; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; /** * <p class="changed_added_2_0"><strong class="changed_modified_2_2"> * NavigationCase</strong> * represents a <code><navigation-case></code> in the navigation * rule base, as well as the <span class="changed_modified_2_2"><code><from-view-id></code> with * which this <code><navigation-case></code> is a sibling</span>.</p> * * @since 2.0 */ public class NavigationCase { private final String fromViewId; private final String fromAction; private final String fromOutcome; private final String condition; private final String toViewId; private final String toFlowDocumentId; private final Map<String,List<String>> parameters; private final boolean redirect; private final boolean includeViewParams; private ValueExpression toViewIdExpr; private ValueExpression conditionExpr; private String toString; private int hashCode; // ------------------------------------------------------------ Constructors /** * <p class="changed_added_2_0"> Construct a new * <code>NavigationCase</code> based on the provided arguments. See * section JSF.7.4.2 for how a <code>NavigationCase</code> is used * by the standard {@link ConfigurableNavigationHandler}</p> * * @param fromViewId return from {@link #getFromViewId} * @param fromAction return from {@link #getFromAction} * @param fromOutcome return from {@link #getFromOutcome} * @param condition A string to be interpreted as a * <code>ValueExpression</code> by a call to {@link #getCondition} * @param toViewId return from {@link #getToViewId} * @param parameters return from {@link #getParameters} * @param redirect return from {@link #isRedirect} * @param includeViewParams return {@link #isIncludeViewParams} */ public NavigationCase(String fromViewId, String fromAction, String fromOutcome, String condition, String toViewId, Map<String,List<String>> parameters, boolean redirect, boolean includeViewParams) { this.fromViewId = fromViewId; this.fromAction = fromAction; this.fromOutcome = fromOutcome; this.condition = condition; this.toViewId = toViewId; this.toFlowDocumentId = null; this.parameters = parameters; this.redirect = redirect; this.includeViewParams = includeViewParams; } /** * <p class="changed_added_2_0"> Construct a new * <code>NavigationCase</code> based on the provided arguments. See * section JSF.7.4.2 for how a <code>NavigationCase</code> is used * by the standard {@link ConfigurableNavigationHandler}</p> * * @param fromViewId return from {@link #getFromViewId} * @param fromAction return from {@link #getFromAction} * @param fromOutcome return from {@link #getFromOutcome} * @param condition A string to be interpreted as a * <code>ValueExpression</code> by a call to {@link #getCondition} * @param toViewId return from {@link #getToViewId} * @param parameters return from {@link #getParameters} * @param redirect return from {@link #isRedirect} * @param includeViewParams return {@link #isIncludeViewParams} */ public NavigationCase(String fromViewId, String fromAction, String fromOutcome, String condition, String toViewId, String toFlowDocumentId, Map<String,List<String>> parameters, boolean redirect, boolean includeViewParams) { this.fromViewId = fromViewId; this.fromAction = fromAction; this.fromOutcome = fromOutcome; this.condition = condition; this.toViewId = toViewId; this.toFlowDocumentId = toFlowDocumentId; this.parameters = parameters; this.redirect = redirect; this.includeViewParams = includeViewParams; } // ---------------------------------------------------------- Public Methods /** * <p class="changed_added_2_0">Construct an absolute URL to this * <code>NavigationCase</code> instance using {@link * javax.faces.application.ViewHandler#getActionURL} on the path * portion of the url.</p> * * @param context the {@link FacesContext} for the current request * * @throws MalformedURLException if the process of constructing the * URL causes this exception to be thrown. */ public URL getActionURL(FacesContext context) throws MalformedURLException { ExternalContext extContext = context.getExternalContext(); return new URL(extContext.getRequestScheme(), extContext.getRequestServerName(), extContext.getRequestServerPort(), context.getApplication().getViewHandler().getActionURL(context, getToViewId(context))); } /** * <p class="changed_added_2_0">Construct an absolute URL to this * <code>NavigationCase</code> instance using {@link * javax.faces.application.ViewHandler#getResourceURL} on the path * portion of the url.</p> * * @param context the {@link FacesContext} for the current request * * @throws MalformedURLException if the process of constructing the * URL causes this exception to be thrown. */ public URL getResourceURL(FacesContext context) throws MalformedURLException { ExternalContext extContext = context.getExternalContext(); return new URL(extContext.getRequestScheme(), extContext.getRequestServerName(), extContext.getRequestServerPort(), context.getApplication().getViewHandler().getResourceURL(context, getToViewId(context))); } /** * <p class="changed_added_2_0">Construct an absolute URL suitable for a * "redirect" to this <code>NavigationCase</code> instance using {@link * javax.faces.application.ViewHandler#getRedirectURL} on the path * portion of the url.</p> * * @param context the {@link FacesContext} for the current request * * @throws MalformedURLException if the process of constructing the * URL causes this exception to be thrown. */ public URL getRedirectURL(FacesContext context) throws MalformedURLException { ExternalContext extContext = context.getExternalContext(); return new URL(extContext.getRequestScheme(), extContext.getRequestServerName(), extContext.getRequestServerPort(), context.getApplication().getViewHandler().getRedirectURL(context, getToViewId(context), SharedUtils.evaluateExpressions(context, getParameters()), isIncludeViewParams())); } /** * <p class="changed_added_2_0">Construct an absolute URL suitable for a * bookmarkable link to this <code>NavigationCase</code> instance using {@link * javax.faces.application.ViewHandler#getBookmarkableURL} on the path * portion of the url. This URL may include view parameters specified * as metadata within the view.</p> * * @param context the {@link FacesContext} for the current request * * @throws MalformedURLException if the process of constructing the * URL causes this exception to be thrown. */ public URL getBookmarkableURL(FacesContext context) throws MalformedURLException { ExternalContext extContext = context.getExternalContext(); return new URL(extContext.getRequestScheme(), extContext.getRequestServerName(), extContext.getRequestServerPort(), context.getApplication().getViewHandler().getBookmarkableURL(context, getToViewId(context), getParameters(), isIncludeViewParams())); } /** * <p class="changed_added_2_0">Return the * <code><from-view-id></code> of the * <code><navigation-rule></code> inside which this * <code><navigation-case></code> is nested.</p> */ public String getFromViewId() { return fromViewId; } /** * <p class="changed_added_2_0">Return the <code><from-action> * for this <code><navigation-case></code></code></p> */ public String getFromAction() { return fromAction; } /** * <p class="changed_added_2_0">Return the <code><from-outcome> * for this <code><navigation-case></code></code></p> */ public String getFromOutcome() { return fromOutcome; } /** * <p class="changed_added_2_0">Evaluates the <code><to-view-id></code> * for this <code><navigation-case></code></p> * * @param context the {@link FacesContext} for the current request * * @return the view ID that should be navigated to */ public String getToViewId(FacesContext context) { if (toViewIdExpr == null) { ExpressionFactory factory = context.getApplication().getExpressionFactory(); toViewIdExpr = factory.createValueExpression(context.getELContext(), toViewId, String.class); } String result = (String) toViewIdExpr.getValue(context.getELContext()); if (result.charAt(0) != '/') { result = '/' + result; } return result; } /** * <p class="changed_added_2_2">If this navigation case represents * a flow invocation, this property is the documentId in which the flow * whose id is given by the return from {@link #getFromOutcome()} is * defined. Implementations must override this method to return * the value defined in the corresponding application configuration resources * element. The base implementation returns the empty string.</p> * * @since 2.2 */ public String getToFlowDocumentId() { return toFlowDocumentId; } /** * <p class="changed_added_2_0">Test if this navigation case has an * associated <code><if></code> element. * * @return <code>true</code> if there's an <code><if></code> * element associated with this <code><navigation-case></code>, * otherwise <code>false</code> */ public boolean hasCondition() { return (condition != null); } /** * <p class="changed_added_2_0">Evaluates the * <code><if></code> for this * <code><navigation-case></code>, if any. The expression to * be evaluated is passed into the constructor as a string. When * the expression is evaluated, its value must be coerced into a * <code>boolean</code> per the normal EL coercion rules.</p> * * @param context the {@link FacesContext} for the current request * * @return <code>null</code> if there is no <code><if></code> element * associated with this <code><navigation-case></code>, otherwise * return the evaluation result of the condition * * @throws any exceptions encountered during the process of * evaluating the expression or obtaining its value. */ public Boolean getCondition(FacesContext context) { if (conditionExpr == null && condition != null) { ExpressionFactory factory = context.getApplication().getExpressionFactory(); conditionExpr = factory.createValueExpression(context.getELContext(), condition, Boolean.class); } return ((conditionExpr != null) ? (Boolean) conditionExpr.getValue(context.getELContext()) : null); } /** * <p class="changed_added_2_0">Return the parameters to be included * for navigation cases requiring a redirect. If no parameters are * defined, <code>null</code> will be returned. The keys in the * <code>Map</code> are parameter names. For each key, the * corresponding value is a <code>List</code> of unconverted * values.</p> */ public Map<String, List<String>> getParameters() { return parameters; } /** * <p class="changed_added_2_0">Return the * <code><redirect></code> value for this * <code><navigation-case></code>. This will be * <code>true</code> if the new view should be navigated to via a * {@link javax.faces.context.ExternalContext#redirect(String)}</p> */ public boolean isRedirect() { return redirect; } /** * <p class="changed_added_2_0">Return the * <code><redirect></code> value for this * <code><navigation-case></code>. This will be * <code>true</code> if the view parametets should be encoded into * the redirect URL (only applies to redirect case)</p> */ public boolean isIncludeViewParams() { return includeViewParams; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } NavigationCase that = (NavigationCase) o; return (redirect == that.redirect && !(fromAction != null ? !fromAction.equals(that.fromAction) : that.fromAction != null) && !(fromOutcome != null ? !fromOutcome.equals(that.fromOutcome) : that.fromOutcome != null) && !(condition != null ? !condition.equals(that.condition) : that.condition != null) && !(fromViewId != null ? !fromViewId.equals(that.fromViewId) : that.fromViewId != null) && !(toViewId != null ? !toViewId.equals(that.toViewId) : that.toViewId != null) && !(toFlowDocumentId != null ? !toFlowDocumentId.equals(that.toFlowDocumentId) : that.toFlowDocumentId != null) && !(parameters != null ? !parameters.equals(that.parameters) : that.parameters != null)); } @Override public int hashCode() { if (hashCode == 0) { int result = fromViewId != null ? fromViewId.hashCode() : 0; result = 31 * result + (fromAction != null ? fromAction.hashCode() : 0); result = 31 * result + (fromOutcome != null ? fromOutcome.hashCode() : 0); result = 31 * result + (condition != null ? condition.hashCode() : 0); result = 31 * result + (toViewId != null ? toViewId.hashCode() : 0); result = 31 * result + (toFlowDocumentId != null ? toFlowDocumentId.hashCode() : 0); result = 31 * result + (redirect ? 1 : 0); result = 31 * result + (parameters != null ? parameters.hashCode() : 0); hashCode = result; } return hashCode; } @Override public String toString() { if (toString == null) { StringBuilder sb = new StringBuilder(64); sb.append("NavigationCase{"); sb.append("fromViewId='").append(fromViewId).append('\''); sb.append(", fromAction='").append(fromAction).append('\''); sb.append(", fromOutcome='").append(fromOutcome).append('\''); sb.append(", if='").append(condition).append('\''); sb.append(", toViewId='").append(toViewId).append('\''); sb.append(", faces-redirect=").append(redirect); sb.append(", includeViewParams=").append(includeViewParams).append('\''); sb.append(", parameters=").append(((parameters != null) ? parameters.toString() : "")); sb.append('}'); toString = sb.toString(); } return toString; } }