View Javadoc

1   /*
2    * Copyright 2010 FatWire 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  package com.fatwire.gst.foundation.wra;
17  
18  import java.util.Arrays;
19  import java.util.Collections;
20  
21  import COM.FutureTense.Interfaces.ICS;
22  
23  import com.fatwire.assetapi.data.AssetData;
24  import com.fatwire.assetapi.data.AssetId;
25  import com.fatwire.cs.core.db.PreparedStmt;
26  import com.fatwire.cs.core.db.StatementParam;
27  import com.fatwire.gst.foundation.controller.AssetIdWithSite;
28  import com.fatwire.gst.foundation.facade.assetapi.AssetDataUtils;
29  import com.fatwire.gst.foundation.facade.assetapi.AssetMapper;
30  import com.fatwire.gst.foundation.facade.assetapi.AttributeDataUtils;
31  import com.fatwire.gst.foundation.facade.assetapi.asset.TemplateAsset;
32  import com.fatwire.gst.foundation.facade.sql.Row;
33  import com.fatwire.gst.foundation.facade.sql.SqlHelper;
34  
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /**
40   * Dao for dealing with core fields in a WRA This DAO is not aware of Aliases.
41   * To work with Alias assets, see {@link AliasCoreFieldDao}.}
42   * 
43   * @author Tony Field
44   * @since Jul 21, 2010
45   */
46  public class AssetApiWraCoreFieldDao implements WraCoreFieldDao {
47  
48      public static final AssetApiWraCoreFieldDao getInstance(ICS ics) {
49          if (ics == null) {
50              throw new IllegalArgumentException("ics must not be null.");
51          }
52  
53          Object o = ics.GetObj(AssetApiWraCoreFieldDao.class.getName());
54          if (o == null) {
55              o = new AssetApiWraCoreFieldDao(ics);
56              ics.SetObj(AssetApiWraCoreFieldDao.class.getName(), o);
57          }
58          return (AssetApiWraCoreFieldDao) o;
59      }
60  
61      private final ICS ics;
62  
63      public AssetApiWraCoreFieldDao(ICS ics) {
64          this.ics = ics;
65      }
66  
67      private static final Log LOG = LogFactory.getLog(AssetApiWraCoreFieldDao.class);
68  
69      /**
70       * Return an AssetData object containing the core fields found in a
71       * web-referenceable asset.
72       * <p/>
73       * Also includes selected metadata fields:
74       * <ul>
75       * <li>id</li>
76       * <li>name</li>
77       * <li>subtype</li>
78       * <li>startdate</li>
79       * <li>enddate</li>
80       * <li>status</li>
81       * </ul>
82       * 
83       * @param id id of web-referenceable asset
84       * @return AssetData containing core fields for Web-Referencable asset
85       */
86      private AssetData getAsAssetData(AssetId id) {
87          return AssetDataUtils.getAssetData(ics, id, WRA_ATTRIBUTE_NAMES);
88      }
89  
90      /**
91       * Method to test whether or not an asset is web-referenceable.
92       * 
93       * @param id asset ID to check
94       * @return true if the asset is a valid web-referenceable asset, false if it
95       *         is not
96       */
97      public boolean isWebReferenceable(AssetId id) {
98          try {
99              WebReferenceableAsset wra = getWra(id);
100             return isWebReferenceable(wra);
101         } catch (RuntimeException e) {
102             return false;
103         }
104     }
105 
106     public boolean isWebReferenceable(TemplateAsset candidate) {
107         return isWebReferenceable(new WraBeanImpl(candidate));
108     }
109 
110     /**
111      * Method to test whether or not an asset is web-referenceable. 
112      *
113      * @param candidate asset to test
114      * @return true if the asset is a valid web-referenceable asset, false if it
115      *         is not
116      */
117     public boolean isWebReferenceable(WebReferenceableAsset candidate) {
118         return StringUtils.isNotBlank(candidate.getPath());
119     }
120 
121     /**
122      * Return a web referenceable asset bean given an input id. Required fields
123      * must be set or an exception is thrown.
124      * 
125      * @param id asset id
126      * @return WebReferenceableAsset, never null
127      * @see #isWebReferenceable
128      */
129     public WebReferenceableAsset getWra(AssetId id) {
130         AssetData data = getAsAssetData(id);
131         return mapper.map(data);
132     }
133 
134     private AssetMapper<WebReferenceableAsset> mapper = new AssetMapper<WebReferenceableAsset>() {
135 
136         public WebReferenceableAsset map(AssetData data) {
137             WraBeanImpl wra = new WraBeanImpl();
138             wra.setId(data.getAssetId());
139             wra.setName(AttributeDataUtils.getWithFallback(data, "name"));
140             wra.setDescription(AttributeDataUtils.asString(data.getAttributeData("description")));
141             wra.setSubtype(AttributeDataUtils.asString(data.getAttributeData("subtype")));
142             wra.setStatus(AttributeDataUtils.asString(data.getAttributeData("status")));
143             wra.setStartDate(AttributeDataUtils.asDate(data.getAttributeData("startdate")));
144             wra.setEndDate(AttributeDataUtils.asDate(data.getAttributeData("enddate")));
145             wra.setMetaTitle(AttributeDataUtils.getWithFallback(data, "metatitle"));
146             wra.setMetaDescription(AttributeDataUtils.getWithFallback(data, "metadescription"));
147             wra.setMetaKeyword(AttributeDataUtils.asString(data.getAttributeData("metakeyword")));
148             wra.setH1Title(AttributeDataUtils.getWithFallback(data, "h1title"));
149             wra.setLinkText(AttributeDataUtils.getWithFallback(data, "linktext", "h1title"));
150             wra.setPath(AttributeDataUtils.asString(data.getAttributeData("path")));
151             wra.setTemplate(AttributeDataUtils.asString(data.getAttributeData("template")));
152             return wra;
153         }
154 
155     };
156     private AssetMapper<VanityAsset> vmapper = new AssetMapper<VanityAsset>() {
157 
158         public VanityAsset map(AssetData data) {
159             VanityAssetBean wra = new VanityAssetBean();
160             wra.setId(data.getAssetId());
161             wra.setName(AttributeDataUtils.getWithFallback(data, "name"));
162             wra.setDescription(AttributeDataUtils.asString(data.getAttributeData("description")));
163             wra.setSubtype(AttributeDataUtils.asString(data.getAttributeData("subtype")));
164             wra.setStatus(AttributeDataUtils.asString(data.getAttributeData("status")));
165             wra.setStartDate(AttributeDataUtils.asDate(data.getAttributeData("startdate")));
166             wra.setEndDate(AttributeDataUtils.asDate(data.getAttributeData("enddate")));
167             wra.setPath(AttributeDataUtils.asString(data.getAttributeData("path")));
168             wra.setTemplate(AttributeDataUtils.asString(data.getAttributeData("template")));
169             return wra;
170         }
171 
172     };
173 
174     private static final String ASSETPUBLICATION_QRY = "SELECT p.name from Publication p, AssetPublication ap "
175             + "WHERE ap.assettype = ? " + "AND ap.assetid = ? " + "AND ap.pubid=p.id";
176     static final PreparedStmt AP_STMT = new PreparedStmt(ASSETPUBLICATION_QRY,
177             Collections.singletonList("AssetPublication")); // todo: low
178                                                             // priority:
179     // determine
180     // why publication
181     // cannot fit there.
182 
183     static {
184         AP_STMT.setElement(0, "AssetPublication", "assettype");
185         AP_STMT.setElement(1, "AssetPublication", "assetid");
186     }
187 
188     public String resolveSite(String c, String cid) {
189         final StatementParam param = AP_STMT.newParam();
190         param.setString(0, c);
191         param.setLong(1, Long.parseLong(cid));
192         String result = null;
193         for (Row pubid : SqlHelper.select(ics, AP_STMT, param)) {
194             if (result != null) {
195                 LOG.warn("Found asset "
196                         + c
197                         + ":"
198                         + cid
199                         + " in more than one publication. It should not be shared; aliases are to be used for cross-site sharing.  Controller will use first site found: "
200                         + result);
201             } else {
202                 result = pubid.getString("name");
203             }
204         }
205         return result;
206     }
207 
208     static final PreparedStmt FIND_P = new PreparedStmt(
209             "SELECT art.oid FROM AssetRelationTree art, AssetPublication ap, Publication p WHERE ap.assetid = art.oid "
210                     + "AND ap.assettype = 'Page' AND ap.pubid = p.id AND p.name = ? "
211                     + "AND art.otype = ap.assettype AND art.nid in "
212                     + "(SELECT nparentid FROM AssetRelationtree WHERE otype=? AND oid=? AND ncode='-') ORDER BY ap.id",
213             Arrays.asList("AssetRelationTree", "AssetPublication", "Publication"));
214 
215     static {
216         FIND_P.setElement(0, "Publication", "name");
217         FIND_P.setElement(1, "AssetRelationTree", "otype");
218         FIND_P.setElement(2, "AssetRelationTree", "oid");
219     }
220 
221     /**
222      * Locate the page that contains the specified Web-Referenceable Asset.
223      * <p/>
224      * A WRA is supposed to just be placed on one page (in the unnamed
225      * association block), and this method locates it. If it is not found, 0L is
226      * returned.
227      * <p/>
228      * If multiple matches are found, a warning is logged and the first one is
229      * returned.
230      * 
231      * @param wraAssetIdWithSite id of the web-referenceable asset. Site is
232      *            included
233      * @return page asset ID or 0L.
234      */
235     public long findP(AssetIdWithSite wraAssetIdWithSite) {
236         ics.ClearErrno();
237         final StatementParam param = FIND_P.newParam();
238         param.setString(0, wraAssetIdWithSite.getSite());
239         param.setString(1, wraAssetIdWithSite.getType());
240         param.setLong(2, wraAssetIdWithSite.getId());
241         long result = 0L;
242         for (final Row r : SqlHelper.select(ics, FIND_P, param)) {
243             if (result != 0L)
244                 LOG.warn("Asset "
245                         + wraAssetIdWithSite
246                         + " was found as the primary content on multiple pages in the site.  Web-referenceable assets should only be the primary content on one Page to comply with SEO rules.  Automatically selecting the oldest page");
247             else
248                 result = r.getLong("oid");
249         }
250         if (result == 0L) {
251             // could not locate
252         }
253         return result;
254 
255     }
256 
257     @Override
258     public boolean isVanityAsset(AssetId id) {
259         try {
260 
261             AssetData data = AssetDataUtils.getAssetData(ics, id, "path");
262             String path = AttributeDataUtils.asString(data.getAttributeData("path"));
263             return StringUtils.isNotBlank(path);
264         } catch (RuntimeException e) {
265             return false;
266         }
267     }
268 
269     @Override
270     public VanityAsset getVanityWra(AssetId id) {
271         AssetData data = AssetDataUtils.getAssetData(ics, id, VANITY_ATTRIBUTE_NAMES);
272         return vmapper.map(data);
273     }
274 
275 }