/*
* 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;
}
}