/*
* Copyright 2012 Oracle Corporation. All Rights Reserved.
*
* Licensed 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 com.fatwire.gst.foundation.controller;
import static COM.FutureTense.Interfaces.Utilities.goodString;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import COM.FutureTense.Interfaces.ICS;
import COM.FutureTense.Util.ftErrors;
import COM.FutureTense.Util.ftMessage;
import com.fatwire.gst.foundation.CSRuntimeException;
import com.fatwire.gst.foundation.facade.RenderUtils;
import com.fatwire.gst.foundation.facade.runtag.render.CallTemplate;
import com.fatwire.gst.foundation.facade.runtag.render.CallTemplate.Style;
import com.fatwire.gst.foundation.facade.runtag.render.SatellitePage;
import com.openmarket.xcelerate.publish.PubConstants;
/**
* Helper class to be used in an outer wrapper to run the correct childtemplate based on c/cid/site arguments.
*
* @author Dolf Dijkstra
*
*
* @deprecated as of release 12.x, replace with WCS 12c's native features (Controllers, wrappers, etc...)
*
*/
public abstract class BaseRenderPage {
public static final String PACKEDARGS = PubConstants.PACKEDARGS.toLowerCase(Locale.US);//"packedargs";
public static final List<String> CALLTEMPLATE_EXCLUDE_VARS = Collections.unmodifiableList(Arrays.asList("c", "cid",
"eid", "seid", PACKEDARGS, "variant", "context", "pagename", "childpagename", "site", "tid",
"SystemAssetsRoot", "rendermode", "cshttp", "errno", "tablename", "empty", "ft_ss", "errdetail", "null"));
protected static final Logger LOG = LoggerFactory.getLogger("tools.gsf.legacy.controller.BaseRenderPage");
protected ICS ics;
public BaseRenderPage() {
super();
}
protected void callPage(AssetIdWithSite id, String pagename, String packedArgs) {
final SatellitePage sp = new SatellitePage(pagename);
if (StringUtils.isNotBlank(packedArgs))
sp.setPackedArgs(packedArgs);
sp.setArgument(PubConstants.c, id.getType());
sp.setArgument(PubConstants.cid, id.getId());
String[] pc = ics.pageCriteriaKeys(pagename);
if (pc != null) {
for (String p : pc) {
if (!CALLTEMPLATE_EXCLUDE_VARS.contains(p)) {
// add only if page critera and not excluded
sp.setArgument(p, ics.GetVar(p));
}
}
}
String s = sp.execute(ics);
if (s != null) {
ics.StreamText(s);
}
}
protected AssetIdWithSite resolveAssetId() {
final AssetIdWithSite id;
if (goodString(ics.GetVar(PubConstants.c)) && goodString(ics.GetVar(PubConstants.cid)) && goodString(ics.GetVar(PubConstants.site))) {
String site = ics.GetVar(PubConstants.site);
id = new AssetIdWithSite(ics.GetVar(PubConstants.c), Long.parseLong(ics.GetVar(PubConstants.cid)), site);
} else {
throw new CSRuntimeException("Missing required param c, cid.", ftErrors.pagenotfound);
}
return id;
}
protected void renderPage() {
// the preview code path is adding all the additional arguments in
// packedargs.
// unpack here so we can use
String pa = unpackPackedArgs();// ics.GetVar(PubConstants.PACKEDARGS);
final AssetIdWithSite id = resolveAssetId();
if (id == null || id.getSite() == null) {
throw new CSRuntimeException("Asset or site not found: '" + id + "' for url " + ics.pageURL(),
ftErrors.pagenotfound);
}
if (LOG.isDebugEnabled())
LOG.debug("RenderPage found a valid asset and site: " + id);
// if childpagename is passed in (preview code path) we use this and do
// a render:satellitepage
if (ics.GetVar(PubConstants.CHILDPAGENAME) != null) {
// preview UI support
callPage(id, ics.GetVar(PubConstants.CHILDPAGENAME), pa);
} else {
// alternatively, render the live logic.
// the template is expected to have the layout itself.
}
LOG.debug("WraRenderPage execution complete");
}
protected void findAndSetP(final AssetIdWithSite id, final Map<String, String> arguments) {
final String pVar = ics.GetVar("p");
if (pVar != null && pVar.length() > 0) {
arguments.put("p", pVar);
}
}
protected void callTemplate(final AssetIdWithSite id, final String tname) {
final CallTemplate ct = new CallTemplate();
ct.setSite(id.getSite());
ct.setSlotname("wrapper");
String tid = ics.GetVar(PubConstants.eid);// renderpage action is intended to be
// rendered from the controller
if (StringUtils.isBlank(tid)) {
if (LOG.isDebugEnabled()) {
LOG.debug("CSVar eid is not found, compensating with eid=1. Is this element not a CSElement");
}
tid = "1";
}
ct.setTid(tid);
ct.setAsset(id);
ct.setTname(tname);
ct.setContext("");
ct.setArgument(PubConstants.site, id.getSite());
final String packedargs = ics.GetVar(PACKEDARGS);
if (StringUtils.isNotBlank(packedargs)) {
if (LOG.isDebugEnabled()) {
LOG.debug("packedargs is " + packedargs);
}
ct.setPackedargs(massagePackedArgs(packedargs));
}
// typeless or not...
final String targetPagename = tname.startsWith("/") ? (id.getSite() + tname) : (id.getSite() + "/"
+ id.getType() + "/" + tname);
if (LOG.isDebugEnabled()) {
LOG.debug("Target pagename is " + targetPagename);
}
// create a list of parameters that can be specified as arguments to the
// CallTemplate tag.
final Map<String, String> arguments = new HashMap<String, String>();
// Prime the map with the ics variable scope for the architect to make
// the controller as transparent as possible
String[] pageKeys = ics.pageCriteriaKeys(targetPagename);
if (pageKeys != null) {
for (final String pcVarName : pageKeys) {
if (!CALLTEMPLATE_EXCLUDE_VARS.contains(pcVarName) && StringUtils.isNotBlank(ics.GetVar(pcVarName))) {
arguments.put(pcVarName, ics.GetVar(pcVarName));
}
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("PageCriteria for " + targetPagename + " is null.");
}
}
// allow users to set their own
getCallTemplateArguments(id, arguments);
// add them to the tag
for (final Entry<String, String> e : arguments.entrySet()) {
ct.setArgument(e.getKey(), e.getValue());
if (LOG.isTraceEnabled()) {
LOG.trace("CallTemplate param added: " + e.getKey() + "=" + e.getValue());
}
}
// override calltemplate call style
imposeCallTemplateStyle(ct, targetPagename);
final String s = ct.execute(ics);
if (s != null) {
ics.StreamText(s);
}
}
/**
* This method collects additional arguments for the CallTemplate call. New
* arguments are added to the map as name-value pairs.
*
* @param id AssetIdWithSite object
* @param arguments Map{@literal<String,String>} containing arguments for the nested
* CallTemplate call
*/
protected void getCallTemplateArguments(AssetIdWithSite id, Map<String, String> arguments) {
findAndSetP(id, arguments);
}
protected Style getCallTemplateCallStyle(String target) {
if (RenderUtils.isCacheable(ics, ics.GetVar(ftMessage.PageName))) {
// call as element when current is caching.
// note that it may be useful to set this to "embedded" in some
// cases.
// override it in that situation
return Style.element;
} else if (RenderUtils.isCacheable(ics, target)) {
// call as embedded when current is not caching and target is
return Style.embedded;
} else {
// call as element when current is not caching and target is not
return Style.element;
}
}
/**
* This method allows developers to override the automatically-selected
* CallTemplate call style. By default, no override is done and the
* CallTemplate class determines the best call style.
*
* @param ct CallTemplate tag
* @param targetPagename target pagename
* @see CallTemplate #setStyle(CallTemplate.Style)
*/
protected void imposeCallTemplateStyle(final CallTemplate ct, final String targetPagename) {
}
protected String massagePackedArgs(String packedargs) {
return packedargs;
}
/**
* Record compositional dependencies that are required for the controller
*/
protected void recordCompositionalDependencies() {
RenderUtils.recordBaseCompositionalDependencies(ics);
}
protected String unpackPackedArgs() {
// for RenderPage unpacking and throwing away packedargs seems the
// correct thing to do
final String packedargs = ics.GetVar(PACKEDARGS);
if (StringUtils.isNotBlank(packedargs)) {
if (LOG.isDebugEnabled()) {
LOG.debug("packedargs is " + packedargs);
}
Map<String, String> map = new HashMap<String, String>();
ics.decode(packedargs, map);
for (Map.Entry<String, String> e : map.entrySet()) {
ics.SetVar(e.getKey(), e.getValue());
}
ics.RemoveVar(PACKEDARGS);
}
return packedargs;
}
}