View Javadoc

1   /*
2    * Copyright 2012 Oracle Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.fatwire.gst.foundation.wra.navigation;
18  
19  import static com.fatwire.gst.foundation.facade.runtag.asset.FilterAssetsByDate.isValidOnDate;
20  
21  import java.util.Arrays;
22  import java.util.Collection;
23  import java.util.Date;
24  import java.util.LinkedList;
25  import java.util.List;
26  
27  import org.apache.commons.lang.StringEscapeUtils;
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  import COM.FutureTense.Interfaces.ICS;
33  import COM.FutureTense.Interfaces.Utilities;
34  
35  import com.fatwire.assetapi.data.AssetId;
36  import com.fatwire.cs.core.db.PreparedStmt;
37  import com.fatwire.cs.core.db.StatementParam;
38  import com.fatwire.gst.foundation.facade.assetapi.asset.TemplateAsset;
39  import com.fatwire.gst.foundation.facade.assetapi.asset.TemplateAssetAccess;
40  import com.fatwire.gst.foundation.facade.runtag.render.LogDep;
41  import com.fatwire.gst.foundation.facade.sql.IListIterable;
42  import com.fatwire.gst.foundation.facade.sql.Row;
43  import com.fatwire.gst.foundation.facade.sql.SqlHelper;
44  import com.fatwire.gst.foundation.facade.uri.TemplateUriBuilder;
45  import com.fatwire.gst.foundation.navigation.NavigationNode;
46  import com.fatwire.gst.foundation.navigation.NavigationService;
47  import com.fatwire.gst.foundation.navigation.support.AbstractNavigationService;
48  import com.fatwire.gst.foundation.wra.Alias;
49  import com.fatwire.gst.foundation.wra.AliasCoreFieldDao;
50  import com.fatwire.gst.foundation.wra.WraUriBuilder;
51  import com.fatwire.mda.DimensionFilterInstance;
52  
53  /**
54   * @author Dolf Dijkstra
55   * 
56   */
57  public class WraNavigationService extends AbstractNavigationService implements NavigationService {
58  
59      private static final Log LOG = LogFactory.getLog(WraNavigationService.class);
60      /**
61       * Name of the page subtype indicating that this page is NOT rendered on the
62       * site but is instead merely used to group navigation components on the
63       * site.
64       */
65      public static final String NAVBAR_NAME = "GSTNavName";
66      /**
67       * Name of the page subtype indicating that this page is a Link, meaning
68       * that the content is in the unnamed association
69       */
70      public static final String NAVBAR_LINK = "GSTNavLink";
71  
72      /**
73       * Constant containing the asset type of the GST Alias asset.
74       */
75      public final String GST_ALIAS_TYPE = Alias.ALIAS_ASSET_TYPE_NAME;
76  
77      private static final String CHILD_SQL = "SELECT otype,oid,nrank,nid from SitePlanTree where nparentid=? and ncode='Placed' order by nrank";
78      private static final PreparedStmt CHILD_STMT = new PreparedStmt(CHILD_SQL, Arrays.asList("SitePlanTree"));
79  
80      static {
81  
82          CHILD_STMT.setElement(0, "SitePlanTree", "nparentid");
83  
84      }
85  
86      /**
87       * Local instance of the AliasCoreFieldDao.
88       */
89      protected final AliasCoreFieldDao aliasDao;
90  
91      protected final DimensionFilterInstance dimensionFilter;
92      private final Date date;
93  
94      public WraNavigationService(ICS ics, TemplateAssetAccess assetTemplate, AliasCoreFieldDao aliasDao,
95              final DimensionFilterInstance dimensionFilter, Date previewDate) {
96          super(ics, assetTemplate, "linktext", "path");
97          this.aliasDao = aliasDao;
98          this.dimensionFilter = dimensionFilter;
99          this.date = previewDate;
100 
101     }
102 
103     @Override
104     protected NavigationNode getNode(Row row, int level, int depth, String linkAttribute) {
105         long nid = row.getLong("nid");
106         long pageId = row.getLong("oid");
107 
108         AssetId pid = assetTemplate.createAssetId(row.getString("otype"), pageId);
109         if (!isValidOnDate(ics, pid, date)) {
110             // the input object is not valid. Abort
111             if (LOG.isDebugEnabled()) {
112                 LOG.debug("Input asset " + pid + " is not effective.");
113             }
114             return null;
115         }
116         LogDep.logDep(ics, pid); // probably redundant call
117         TemplateAsset asset = assetTemplate.read(pid, "name", "subtype", "template", pathAttribute, linkAttribute);
118 
119         final NavigationNode node = new NavigationNode();
120 
121         node.setPage(pid);
122         node.setLevel(level);
123         node.setPagesubtype(asset.getSubtype());
124         node.setPagename(asset.asString("name"));
125         final boolean isNavigationPlaceholder = NAVBAR_NAME.equals(asset.asString("subtype"));
126         final boolean isNavigationLink = NAVBAR_LINK.equals(asset.asString("subtype"));
127         if (isNavigationPlaceholder) {
128             // return node without an associated asset
129         } else if (isNavigationLink) {
130 
131             Collection<AssetId> assocs;
132             assocs = assetTemplate.readAssociatedAssetIds(pid, "-");
133             if (dimensionFilter != null)
134                 assocs = dimensionFilter.filterAssets(assocs);
135             for (AssetId assoc : assocs) {
136                 if (isValidOnDate(ics, assoc, date)) {
137                     if (isGstAlias(assoc)) {
138                         final Alias alias = aliasDao.getAlias(assoc);
139                         node.setId(alias.getId());
140 
141                         final String url = alias.getTargetUrl() != null ? alias.getTargetUrl() : getUrl(alias
142                                 .getTarget());
143                         final String linktext = alias.getLinkText();
144 
145                         if (url != null) {
146                             node.setUrl(url);
147                         }
148                         if (linktext != null) {
149                             node.setLinktext(linktext);
150                         }
151                     } else {
152                         node.setId(assoc);
153                         asset = assetTemplate.read(assoc, "name", "subtype", "template", pathAttribute, linkAttribute);
154                         final String url = getUrl(asset);
155 
156                         if (url != null) {
157                             node.setUrl(url); // escape by default.
158                         }
159 
160                         final String linktext = asset.asString(linkAttribute);
161 
162                         if (linktext != null) {
163                             node.setLinktext(linktext);
164                         } else {
165                             node.setLinktext(asset.asString("name"));
166                         }
167                     }
168                 }
169             }
170 
171         } else {
172             // TODO Add support for locale (date checking is already done at
173             // start of this function).
174 
175             // other subtype
176             final String url = getUrl(asset);
177 
178             if (url != null) {
179                 node.setUrl(url); // escape by default.
180             }
181 
182             final String linktext = asset.asString(linkAttribute);
183 
184             if (linktext != null) {
185                 node.setLinktext(linktext);
186             } else {
187                 node.setLinktext(asset.asString("name"));
188             }
189 
190         }
191 
192         if (depth < 0 || depth > level) {
193             // get the children in the Site Plan, note recursing here
194             Collection<NavigationNode> children = getNodeChildren(nid, level + 1, depth, linkAttribute);
195             for (final NavigationNode kid : children) {
196                 if (kid != null && kid.getPage() != null) {
197                     node.addChild(kid);
198                 }
199             }
200         }
201         return node;
202 
203     }
204 
205     private String getUrl(AssetId assoc) {
206         TemplateAsset asset = assetTemplate.read(assoc, "name", "subtype", "template", pathAttribute);
207         return getUrl(asset);
208     }
209 
210     @Override
211     protected Collection<NavigationNode> getNodeChildren(final long nodeId, final int level, final int depth,
212             String linkAttribute) {
213         StatementParam param = CHILD_STMT.newParam();
214         param.setLong(0, nodeId);
215 
216         IListIterable root = SqlHelper.select(ics, CHILD_STMT, param);
217         List<NavigationNode> collection = new LinkedList<NavigationNode>();
218         for (Row row : root) {
219             final NavigationNode node = getNode(row, level, depth, linkAttribute);
220             if (node != null)
221                 collection.add(node);
222 
223         }
224         return collection;
225     }
226 
227     /**
228      * Builds up a URI for this asset, using the pathAttribute and the template
229      * field of the asset
230      * 
231      * @param asset
232      * @return the uri, xml escaped
233      */
234     protected String getUrl(TemplateAsset asset) {
235         String template = asset.asString("template");
236         String path = asset.asString(pathAttribute);
237         if (StringUtils.isBlank(template)) {
238             LOG.debug("Asset " + asset.getAssetId() + " does not have a valid template set.");
239             return null;
240         }
241         if (StringUtils.isBlank(path)) {
242             LOG.debug("Asset " + asset.getAssetId()
243                     + " does not have a valid path set. Defaulting to a non Vanity Url.");
244             return new TemplateUriBuilder(asset.getAssetId(), template).toURI(ics);
245         }
246 
247         String wrapper = ics.GetProperty("com.fatwire.gst.foundation.url.wrapathassembler.dispatcher",
248                 "ServletRequest.properties", true);
249         if (!Utilities.goodString(wrapper)) {
250             wrapper = "GST/Dispatcher";
251         }
252         String uri = new WraUriBuilder(asset.getAssetId()).wrapper(wrapper).template(template).toURI(ics);
253         return StringEscapeUtils.escapeXml(uri);
254     }
255 
256     /**
257      * Return true if the asset type is a GSTAlias asset type. May be overridden
258      * if customers are attempting to retrofit this class for alias-like
259      * functionality that is not implemented by the GSTAlias asset type.
260      * 
261      * @param id asset for which a link is required
262      * @return true if the asset is an alias, false if it is a web-referenceable
263      *         asset
264      */
265     protected boolean isGstAlias(final AssetId id) {
266         return GST_ALIAS_TYPE.equals(id.getType());
267     }
268 
269 }