001 // Copyright 2010 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5;
016
017 import java.io.Serializable;
018
019 import org.apache.tapestry5.annotations.ImmutableSessionPersistedObject;
020 import org.apache.tapestry5.internal.InternalConstants;
021 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
022 import org.apache.tapestry5.services.PageRenderLinkSource;
023
024 /**
025 * A way of capturing the name of a page and the page activation context so that, at a future date,
026 * the page can be invoked with that data. This kind of callback is very useful when creating more
027 * complicated workflows, where access to a page is "interrupted" with some operation before
028 * returning (via a callback) to the original flow.
029 * <p>
030 * Since the callback is serializable, it can be stored in the session.
031 *
032 * @since 5.2.0
033 */
034 @ImmutableSessionPersistedObject
035 public class PageCallback implements Serializable
036 {
037 private static final long serialVersionUID = -8067619978636824702L;
038
039 private String pageName;
040
041 private String[] activationContext;
042
043 public PageCallback(String pageName, String[] activationContext)
044 {
045 assert InternalUtils.isNonBlank(pageName);
046 this.pageName = pageName;
047 assert activationContext != null;
048 this.activationContext = activationContext;
049 }
050
051 public PageCallback(String pageName, EventContext activationContext)
052 {
053 this(pageName, activationContext.toStrings());
054 }
055
056 public PageCallback(String pageName)
057 {
058 this(pageName, InternalConstants.EMPTY_STRING_ARRAY);
059 }
060
061 public String getPageName()
062 {
063 return pageName;
064 }
065
066 @Override
067 public String toString()
068 {
069 if (hasActivationContext())
070 return String.format("PageCallback[%s %s]", pageName, activationContextDescription());
071
072 return String.format("PageCallback[%s]", pageName);
073 }
074
075 /** Does the activation context have any values? Used, typically, inside an override of {@link #toString()}. */
076 protected final boolean hasActivationContext()
077 {
078 return activationContext.length > 0;
079 }
080
081 /**
082 * Returns the activation context as a string of value separated by slashes. Typically used inside
083 * an override of {@link #toString()}.
084 */
085 protected final String activationContextDescription()
086 {
087 StringBuilder builder = new StringBuilder();
088
089 String sep = "";
090
091 for (String c : activationContext)
092 {
093 builder.append(sep);
094 builder.append(c);
095
096 sep = "/";
097 }
098
099 return builder.toString();
100 }
101
102 /**
103 * Converts the callback (the page name and activation context) to a link; such a link may be
104 * returned from a event handler method to cause Tapestry to redirect to the page. Most of the
105 * details
106 * are encapsulated inside the {@link PageRenderLinkSource} service.
107 *
108 * @param linkSource
109 * used to generate the link
110 * @return link corresponding to this callback
111 */
112 public Link toLink(PageRenderLinkSource linkSource)
113 {
114 return linkSource.createPageRenderLinkWithContext(pageName, (Object[]) activationContext);
115 }
116 }