final IPortletWindowId portletWindowId = portletWindow.getPortletWindowId();
final IPortletEntity parentPortletEntity = this.portletWindowRegistry.getParentPortletEntity(request, portletWindowId);
final String channelSubscribeId = parentPortletEntity.getChannelSubscribeId();
WindowState windowState = portletUrl.getWindowState();
PortletMode portletMode = portletUrl.getPortletMode();
final WindowState previousWindowState = portletWindow.getWindowState();
final PortletMode previousPortletMode = portletWindow.getPortletMode();
//Only do this stuff for the top level window
if (delegationParentId == null) {
//Get the channel runtime data from the request attributes, it should have been set there by the portlet adapter
final ChannelRuntimeData channelRuntimeData = (ChannelRuntimeData)request.getAttribute(IPortletAdaptor.ATTRIBUTE__RUNTIME_DATA);
if (channelRuntimeData == null) {
throw new IllegalStateException("No ChannelRuntimeData was found as a request attribute for key '" + IPortletAdaptor.ATTRIBUTE__RUNTIME_DATA + "' on request '" + request + "'");
}
// Determine the base path for the URL
// If the next state is EXCLUSIVE or there is no state change and the current state is EXCLUSIVE use the worker URL base
if (IPortletAdaptor.EXCLUSIVE.equals(windowState) || (windowState == null && IPortletAdaptor.EXCLUSIVE.equals(previousWindowState))) {
final String urlBase = channelRuntimeData.getBaseWorkerURL(UPFileSpec.FILE_DOWNLOAD_WORKER);
url.append(urlBase);
}
//In detached, need to make sure the URL is right
else if (IPortletAdaptor.DETACHED.equals(windowState) || (windowState == null && IPortletAdaptor.DETACHED.equals(previousWindowState))) {
final UPFileSpec upFileSpec = new UPFileSpec(channelRuntimeData.getUPFile());
upFileSpec.setMethodNodeId(channelSubscribeId);
upFileSpec.setTargetNodeId(channelSubscribeId);
final String urlBase = upFileSpec.getUPFile();
url.append(urlBase);
}
//Switching back from detached to a normal state
else if (IPortletAdaptor.DETACHED.equals(previousWindowState) && windowState != null && !previousWindowState.equals(windowState)) {
final UPFileSpec upFileSpec = new UPFileSpec(channelRuntimeData.getUPFile());
upFileSpec.setMethodNodeId(UPFileSpec.USER_LAYOUT_ROOT_NODE);
final String urlBase = upFileSpec.getUPFile();
url.append(urlBase);
}
//No special handling, just use the base action URL
else {
final String urlBase = channelRuntimeData.getBaseActionURL();
url.append(urlBase);
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Using root url base '" + url + "' for " + portletUrl);
}
}
//Set the request target, creating a transient window ID if needed
boolean forceWindowState = false;
final String portletWindowIdString;
//If rendering as a delegate just reuse the id (it will always be transient)
if (delegationParentId != null) {
portletWindowIdString = portletWindowId.toString();
}
//If switching from a non-transient state to a transient state generate a new transient window id
else if (this.transientWindowStates.contains(windowState) && !this.transientWindowStates.contains(previousWindowState)) {
final IPortletWindowId transientPortletWindowId = this.portletWindowRegistry.createTransientPortletWindowId(request, portletWindowId);
portletWindowIdString = transientPortletWindowId.toString();
}
//If the window is transient, it is in a transient state and it is switching from a non-transient state
else if (this.portletWindowRegistry.isTransient(request, portletWindowId) &&
!this.transientWindowStates.contains(windowState) &&
(windowState != null || !this.transientWindowStates.contains(previousWindowState))) {
//Get non-transient version of id
final IPortletEntityId portletEntityId = portletWindow.getPortletEntityId();
final IPortletWindowId defaultPortletWindowId = this.portletWindowRegistry.getDefaultPortletWindowId(portletEntityId);
portletWindowIdString = defaultPortletWindowId.getStringId();
if (windowState == null) {
final IPortletWindow defaultPortletWindow = this.portletWindowRegistry.getPortletWindow(request, defaultPortletWindowId);
if (!previousWindowState.equals(defaultPortletWindow.getWindowState())) {
forceWindowState = true;
windowState = previousWindowState;
}
if (!previousPortletMode.equals(defaultPortletWindow.getPortletMode())) {
portletMode = previousPortletMode;
}
}
}
else {
portletWindowIdString = portletWindowId.getStringId();
}
//Only one target per url
if (delegationParentId == null) {
this.encodeAndAppend(url.append("?"), encoding, PARAM_REQUEST_TARGET, portletWindowIdString);
}
//Only if actually delegating rendering
if (delegationChildId != null) {
this.encodeAndAppend(url.append("&"), encoding, PARAM_DELEGATE_PREFIX + SEPERATOR + portletWindowIdString, delegationChildId.toString());
}
//Set the request type
final RequestType requestType = portletUrl.getRequestType();
final String requestTypeString = requestType != null ? requestType.toString() : RequestType.RENDER.toString();
this.encodeAndAppend(url.append("&"), encoding, PARAM_REQUEST_TYPE_PREFIX + SEPERATOR + portletWindowIdString, requestTypeString);
// If set add the window state
if (windowState != null && (forceWindowState || !previousWindowState.equals(windowState))) {
this.encodeAndAppend(url.append("&"), encoding, PARAM_WINDOW_STATE_PREFIX + SEPERATOR + portletWindowIdString, windowState.toString());
//uPortal specific parameters are only needed the top most parent portlet window
if (delegationParentId == null) {
//Add the parameters needed by the portal structure & theme to render the correct window state
if (WindowState.MAXIMIZED.equals(windowState)) {
this.encodeAndAppend(url.append("&"), encoding, "uP_root", channelSubscribeId);
}
else if (WindowState.NORMAL.equals(windowState)) {
this.encodeAndAppend(url.append("&"), encoding, "uP_root", IUserLayout.ROOT_NODE_NAME);
this.encodeAndAppend(url.append("&"), encoding, "uP_tcattr", "minimized");
this.encodeAndAppend(url.append("&"), encoding, "minimized_channelId", channelSubscribeId);
this.encodeAndAppend(url.append("&"), encoding, "minimized_" + channelSubscribeId + "_value", "false");
this.encodeAndAppend(url.append("&"), encoding, "uP_save", "all");
}
else if (WindowState.MINIMIZED.equals(windowState)) {
this.encodeAndAppend(url.append("&"), encoding, "uP_root", IUserLayout.ROOT_NODE_NAME);
this.encodeAndAppend(url.append("&"), encoding, "uP_tcattr", "minimized");
this.encodeAndAppend(url.append("&"), encoding, "minimized_channelId", channelSubscribeId);
this.encodeAndAppend(url.append("&"), encoding, "minimized_" + channelSubscribeId + "_value", "true");
this.encodeAndAppend(url.append("&"), encoding, "uP_save", "all");
}
else if (IPortletAdaptor.DETACHED.equals(windowState)) {
this.encodeAndAppend(url.append("&"), encoding, "uP_detach_target", channelSubscribeId);
}
}
}
//Or for any transient state always add the window state
else if (this.transientWindowStates.contains(windowState) || this.transientWindowStates.contains(previousWindowState)) {
this.encodeAndAppend(url.append("&"), encoding, PARAM_WINDOW_STATE_PREFIX + SEPERATOR + portletWindowIdString, previousWindowState.toString());
}
//If set add the portlet mode
if (portletMode != null) {
this.encodeAndAppend(url.append("&"), encoding, PARAM_PORTLET_MODE_PREFIX + SEPERATOR + portletWindowIdString, portletMode.toString());