org.apache.myfaces.trinidadinternal.ui.action.FirePartialAction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of trinidad-impl Show documentation
Show all versions of trinidad-impl Show documentation
Private implementation of the Apache MyFaces Trinidad project
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.trinidadinternal.ui.action;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.apache.myfaces.trinidadinternal.share.url.FormEncoder;
import org.apache.myfaces.trinidadinternal.share.url.URLEncoder;
import org.apache.myfaces.trinidadinternal.ui.UIXRenderingContext;
import org.apache.myfaces.trinidadinternal.ui.UIConstants;
import org.apache.myfaces.trinidadinternal.ui.UINode;
import org.apache.myfaces.trinidadinternal.ui.beans.MarlinBean;
import org.apache.myfaces.trinidadinternal.ui.collection.Parameter;
import org.apache.myfaces.trinidadinternal.ui.data.BoundValue;
import org.apache.myfaces.trinidadinternal.ui.data.bind.AccessKeyBoundValue;
// =-=ags We probably should not depend on the following LAF classes!
import org.apache.myfaces.trinidadinternal.ui.laf.base.SkinTranslatedBoundValue;
import org.apache.myfaces.trinidadinternal.ui.laf.base.xhtml.FormValueRenderer;
import org.apache.myfaces.trinidadinternal.ui.laf.base.xhtml.XhtmlLafRenderer;
import org.apache.myfaces.trinidadinternal.ui.laf.base.xhtml.XhtmlLafUtils;
import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.jsLibs.Scriptlet;
import org.apache.myfaces.trinidadinternal.ui.partial.PartialPageRendererUtils;
/**
* An implementation of FireAction which supports Partial Page Rendering.
*
* @version $Name: $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/ui/action/FirePartialAction.java#0 $) $Date: 10-nov-2005.18:57:43 $
* @deprecated This class comes from the old Java 1.2 UIX codebase and should not be used anymore.
*/
@Deprecated
public class FirePartialAction extends FireAction
{
/**
* Creates a FirePartialAction with the no partial targets which will fire an
* update event by submiting the enclosing form.
*/
public FirePartialAction()
{
this(null, true, null, null);
}
/**
* Creates a FirePartialAction with the specified partial targets which
* will submit the enclosing form.
*
* @param event The name of the event that should be sent when
* the FirePartialAction is activated. If
* null, the event name defaults to "update".
*/
public FirePartialAction(String event)
{
this(event, true, null, null);
}
/**
* Creates a FirePartialAction with the specified partial targets which
* will submit the enclosing form. This constructor will use the default
* event and submit parameters ("Update" and true).
*
* @param targets The IDs of the partial target nodes to update in
* response to the event generated by this action.
*/
public FirePartialAction(String[] targets)
{
this(null, true, targets, null);
}
/**
* Creates a FirePartialAction with the specified partial
* targets and event name which will submit the enclosing form.
*
* @param event The name of the event that should be sent when
* the FirePartialAction is activated. If
* null, the event name defaults to "update".
* @param submit Whether or not a form submit will be used to fire the event
*/
public FirePartialAction(
String event,
boolean submit
)
{
this(event, submit, null, null);
}
/**
* Creates a FirePartialAction with the specified partial
* targets and event name.
*
* @param event The name of the event that should be sent when
* the FirePartialAction is activated. If
* null, the event name defaults to "update".
* @param submit Whether or not a form submit will be used to fire the event
* @param targets The IDs of the partial target nodes to update in
* response to the event generated by this action.
*/
public FirePartialAction(
String event,
boolean submit,
String[] targets
)
{
this(event, submit, targets, null);
}
/**
* Creates a FirePartialAction with the specified partial
* targets and event name.
*
* @param event The name of the event that should be sent when
* the FirePartialAction is activated. If
* null, the event name defaults to "update".
* @param submit Whether or not a form submit will be used to fire the event
* @param targets The IDs of the partial target nodes to update in
* response to the event generated by this action.
* @param triggerText The text that will be rendered on the ClientAction
* button or link if the target browser does not support
* partial page rendering, and a button or link has to be
* rendered to trigger the action.
*/
public FirePartialAction(
String event,
boolean submit,
String[] targets,
String triggerText
)
{
setEvent(event);
setFormSubmitted(submit);
setTargets(targets);
setTriggerText(triggerText);
}
/**
* Implementation of FireAction.getSubmitScript().
*/
@Override
protected String getSubmitScript
(UIXRenderingContext context,
UINode node,
String returnScript)
{
String startScript = "_uixspu(\'";
String endScript = ");";
// Get the formName
String formName = ActionUtils.getFormName(context);
if (formName == null)
return null;
// Get the source attr...
String source = getSource(context, node);
boolean unvalidated = isUnvalidated(context);
Parameter[] parameters = getParameters();
String event = getEventValue(context);
boolean isPartial = XhtmlLafRenderer.supportsPartialRendering(context);
String partialTargets = null;
if (isPartial)
partialTargets = _getPartialTargets(context);
// Figure out how big our buffer needs to be
int length = getBufferSize(context,
startScript,
endScript,
null,
formName,
event,
source,
partialTargets,
null, null, null,
returnScript,
parameters);
// Create the buffer
StringBuilder buffer = new StringBuilder(length);
// Build up the script
buffer.append(startScript);
buffer.append(formName);
buffer.append("\',");
buffer.append(unvalidated ? "0" : "1");
URLEncoder encoder = context.getURLEncoder();
String eventKey = encoder.encodeParameter(UIConstants.EVENT_PARAM);
String sourceKey = encoder.encodeParameter(UIConstants.SOURCE_PARAM);
String partialTargetsKey = encoder.encodeParameter(
UIConstants.PARTIAL_TARGETS_PARAM);
FormEncoder formEncoder = context.getFormEncoder();
String encodedEvent = XhtmlLafUtils.
getFormEncodedParameter(formEncoder,
formName,
eventKey,
event);
String encodedSource = XhtmlLafUtils.
getFormEncodedParameter(formEncoder,
formName,
sourceKey,
source);
String encodedPartialTargets = XhtmlLafUtils.
getFormEncodedParameter(formEncoder,
formName,
partialTargetsKey,
partialTargets);
appendJSParameter(buffer, encodedEvent);
appendJSParameter(buffer, encodedSource);
appendJSParameter(buffer, encodedPartialTargets);
// Note: This value is not FormEncoded because _uixspu needs it in a boolean
// form, and because it is never sent back from the client to the server.
_appendBooleanParameter(buffer, isPartial);
// need to pass formName for FormEncoder
ActionUtils.appendClientParameters(context, buffer, parameters,
null /*event*/, null /*source*/,
formName);
buffer.append(endScript);
buffer.append(returnScript);
return buffer.toString();
}
@Override
protected String getChangeScript
(UIXRenderingContext context,
UINode node,
String returnScript)
{
// First off, check to see if we are doing partial page rendering -
// it might not be supported...
boolean isPartial = XhtmlLafRenderer.supportsPartialRendering(context);
// Assign some vars based on whether we are doing full or partial
String startScript = FULL_START_SCRIPT;
String endScript = FULL_END_SCRIPT;
String partialTargets = null;
String partialTargetsKey = null;
if (isPartial)
{
startScript = _PARTIAL_START_SCRIPT;
endScript = _PARTIAL_END_SCRIPT;
partialTargets = _getPartialTargets(context);
partialTargetsKey = _getPartialTargetsKey(context.getURLEncoder(),
partialTargets);
}
// Now let the main change script builder build the actual script
return getChangeScript(context, node, returnScript,
startScript, endScript,
partialTargetsKey, partialTargets);
}
/**
* Returns the set of partial targets that are updated when this
* ClientAction is activated.
*/
public final String[] getTargets()
{
return ActionUtils.copyPartialTargets(_targets);
}
/**
* Returns the set of partial targets that are updated when this
* ClientAction is activated.
*/
public final String getTriggerText()
{
return _triggerText;
}
/**
* Override of FireAction.renderAsEvent().
*/
@Override
public boolean renderAsEvent(
UIXRenderingContext context,
UINode node)
{
return true;
}
/**
* Sets the partial targets to update.
*/
public final void setTargets(String[] partialTargets)
{
_targets = (partialTargets == null) ? null : partialTargets.clone();
}
/**
* Sets a BoundValue that will dynamically evaluate the partial
* targets.
*/
public void setTargetsBinding(BoundValue partialTargetsBinding)
{
_targetsBinding = partialTargetsBinding;
}
/**
* Sets the text that will be rendered on the ClientAction button or link if
* the target browser does not support partial page rendering, and a button
* or link has to be rendered to trigger the action.
*/
public final void setTriggerText(String triggerText)
{
_triggerText = triggerText;
}
/**
* Override of ClientAction.writeDependencies().
*/
@Override
public void writeDependencies(
UIXRenderingContext context,
UINode node
) throws IOException
{
super.writeDependencies(context, node);
if (isFormSubmitted())
{
// Render our scriptlet
XhtmlLafUtils.addLib(context, _FIRE_PARTIAL_ACTION_SCRIPTLET);
if (XhtmlLafRenderer.supportsPartialRendering(context))
{
// Render hidden fields needed for PPR
String formName = ActionUtils.getFormName(context);
if (formName != null)
{
URLEncoder encoder = context.getURLEncoder();
String partialTargetsKey
= encoder.encodeParameter(UIConstants.PARTIAL_TARGETS_PARAM);
String partialKey
= encoder.encodeParameter(UIConstants.PARTIAL_PARAM);
FormValueRenderer.addNeededValue(context,
formName,
partialTargetsKey,
partialKey,
null, null);
}
}
}
}
/**
* Override of ClientAction.isTriggerRequired()
*/
@Override
public boolean isTriggerRequired(
UIXRenderingContext context,
UINode node
)
{
// We use an explicit trigger when PPR is not supported, since
// we don't want to do full page refreshes in response to
// interactions such as selecting an item from a choice or
// tabbing out of a text field.
return !XhtmlLafRenderer.supportsPartialRendering(context);
}
/**
* Override of ClientAction.renderTrigger().
*/
@Override
public void renderTrigger(
UIXRenderingContext context,
UINode node
) throws IOException
{
Object text = _triggerText;
Object accessKey = null;
if (text == null)
{
BoundValue buttonTextandAccessKeyBV =
new SkinTranslatedBoundValue("PPR_TRIGGER_LABEL");
text = new AccessKeyBoundValue( buttonTextandAccessKeyBV, false);
accessKey = new AccessKeyBoundValue( buttonTextandAccessKeyBV, true);
}
renderTrigger(context, node, text, accessKey);
}
/**
* Override of ClientAction.renderTrigger().
*/
public void renderTrigger(
UIXRenderingContext context,
UINode node,
Object text,
Object accessKey
) throws IOException
{
// We render a button as our trigger when PPR is not supported.
String script = getScript(context, node, Boolean.FALSE);
// =-=ags We could use a singleton here, but I'm not sure that
// performance is actually an issue.
// =-=ags We should probably provide description text for the button.
MarlinBean button = new MarlinBean(UIConstants.BUTTON_NAME);
button.setAttributeValue(UIConstants.TEXT_ATTR, text);
button.setAttributeValue(UIConstants.ACCESS_KEY_ATTR, accessKey);
button.setOnClick(script);
button.render(context);
}
// Appends a parameter to our buffer
private static void _appendBooleanParameter(
StringBuilder buffer,
boolean value
)
{
if (buffer.charAt(buffer.length() - 1) != ',')
buffer.append(",");
buffer.append(value ? "1" : "0");
}
@Override
public Parameter[] getParameters(
UIXRenderingContext context,
UINode node)
{
// Get the encoded names for our event parameters
URLEncoder encoder = context.getURLEncoder();
String targets = _getPartialTargets(context);
Parameter[] allParams = super.getParameters(context, node);
if (targets != null)
{
String targetsKey = _getPartialTargetsKey(encoder, targets);
String partialKey = encoder.encodeParameter(UIConstants.PARTIAL_PARAM);
Parameter[] localParams = new Parameter[2];
localParams[0] = ActionUtils.buildParameter(context, node,
null, "true",
partialKey);
localParams[1] = ActionUtils.buildParameter(context, node,
null, targets,
targetsKey);
allParams = ActionUtils.joinParameterArrays(localParams, allParams);
}
return allParams;
}
// Returns the set of partial targets encoded as a string
private String _getPartialTargets(UIXRenderingContext context)
{
// Get the partial targets
String[] targets = (String[])ActionUtils.getValue(context,
_targetsBinding,
_targets);
// Return the encoded value
return PartialPageRendererUtils.encodePartialTargets(targets);
}
// Returns the partialTargets event parameter key, if necessary
private static String _getPartialTargetsKey(
URLEncoder encoder,
String partialTargets
)
{
if (partialTargets == null)
return null;
return encoder.encodeParameter(UIConstants.PARTIAL_TARGETS_PARAM);
}
// Scriptlet that renders the submitPartialUpdate script
private static class FirePartialActionScriptlet extends Scriptlet
{
static public Scriptlet sharedInstance()
{
return _sInstance;
}
@Override
public Object getScriptletKey()
{
return _FIRE_PARTIAL_ACTION_SCRIPTLET;
}
@Override
protected void outputScriptletContent(
FacesContext context,
RenderingContext arc)
throws IOException
{
// Make sure we have a form
if (arc.getFormData() == null)
return;
String formName = arc.getFormData().getName();
if (formName == null)
return;
// We output a function "_uixspu" (UIX Submit Partial Update)
// which takes the following arguments:
// - f: The form name
// - v: The validation flag
// - e: The event name (defaults to "update")
// - s: The source parameter
// - pt: The partial targets parameter
// - p: boolean indicating whether this is partial or full
// - o: Object containing client-defined parameters
// To support redirecting on IE, we need to check if the parent page is
// actually responding to a partial update call, so we keep track of it
// here. We don't worry about re-setting this to false because the only
// time it comes into play is when the back button is causing a re-render
// of the iframe and, hence, a re-execution of the redirect script. In
// that case, we'll have a new javascript context, and _pprUpdateMode will
// be invalid, or will be initialized to false.
ResponseWriter writer = context.getResponseWriter();
writer.writeText("var _pprUpdateMode=false;", null);
writer.writeText("function _uixspu(f,v,e,s,pt,p,o){", null);
writer.writeText("_pprUpdateMode=true;", null);
writer.writeText("if(!o)o=new Object();", null);
writer.writeText("o.", null);
writer.writeText(UIConstants.EVENT_PARAM, null);
// Should this 'update' value be formEncoded?
writer.writeText("=(e)?e:\'update\';", null);
writer.writeText("if(s)o.", null);
writer.writeText(UIConstants.SOURCE_PARAM, null);
writer.writeText("=s;if(p){o.", null);
writer.writeText(UIConstants.PARTIAL_PARAM, null);
// Should this 'true' value be formEncoded?
writer.writeText("=\'true\';if(pt)o.", null);
writer.writeText(UIConstants.PARTIAL_TARGETS_PARAM, null);
writer.writeText("=pt;_submitPartialChange(f,v,o);}else ", null);
writer.writeText("submitForm(f,v,o);}", null);
}
private static FirePartialActionScriptlet _sInstance =
new FirePartialActionScriptlet();
}
// Name for our Scriptlet
private static final String _FIRE_PARTIAL_ACTION_SCRIPTLET =
"FirePartialAction";
static
{
// Register our scriptlet
FirePartialActionScriptlet.sharedInstance().registerSelf();
}
private String[] _targets;
private BoundValue _targetsBinding;
private String _triggerText;
private static final String _PARTIAL_START_SCRIPT = "_firePartialChange(\'";
private static final String _PARTIAL_END_SCRIPT = "\');";
}