View Javadoc

1   /*
2    * Copyright 2008 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  
17  package com.fatwire.gst.foundation.facade.runtag.asset;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.List;
25  
26  import COM.FutureTense.Interfaces.FTValList;
27  import COM.FutureTense.Interfaces.ICS;
28  import COM.FutureTense.Interfaces.IList;
29  import COM.FutureTense.Util.IterableIListWrapper;
30  
31  import com.fatwire.assetapi.data.AssetId;
32  import com.fatwire.gst.foundation.CSRuntimeException;
33  import com.fatwire.gst.foundation.facade.assetapi.AssetIdUtils;
34  import com.fatwire.gst.foundation.facade.runtag.render.LogDep;
35  import com.fatwire.gst.foundation.facade.sql.Row;
36  import com.fatwire.gst.foundation.facade.sql.TreeHelper;
37  import com.openmarket.xcelerate.asset.AssetIdImpl;
38  import com.openmarket.xcelerate.publish.Render;
39  
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  
43  import static com.fatwire.gst.foundation.IListUtils.getStringValue;
44  
45  /**
46   * Utilities for working efficiently with the AssetRelationTree.
47   *
48   * @author Tony Field
49   * @since Jun 7, 2009
50   */
51  public final class AssetRelationTreeUtils {
52  
53      private static final Log LOG = LogFactory.getLog(AssetRelationTreeUtils.class);
54  
55      /**
56       * Get all of the parent assets in the AssetRelationTree for the specified
57       * asset. Association name is required, but expectedParentType is an
58       * optional filter argument.
59       * <p/>
60       * Does not record any asset dependencies
61       *
62       * @param ics                ICS context
63       * @param log                logger. May be null.
64       * @param child              child asset id
65       * @param expectedParentType asset type of the parent to be returned. If
66       *                           null, type of parent is irrelevant.
67       * @param associationName    name of association to use while looking for
68       *                           parents. may not be null
69       * @return list of parents, never null.
70       * @see #getParents(ICS, AssetId, String[])
71       */
72      public static List<AssetId> getAssetRelationTreeParents(ICS ics, Log log, AssetId child, String expectedParentType, String associationName) {
73          FTValList vl = new FTValList();
74          vl.setValString("ftcmd", "findnode");
75          vl.setValString("treename", "AssetRelationTree");
76          vl.setValString("where", "oid");
77          vl.setValString("oid", Long.toString(child.getId()));
78          if (ics.TreeManager(vl)) {
79              int errno = ics.GetErrno();
80              if (errno < 0) {
81                  switch (errno) {
82                      case -111:
83                          if (log != null && log.isTraceEnabled()) {
84                              log.trace("Node not found in AssetRelationTree for asset " + child);
85                          }
86                          return Collections.emptyList();
87                      default: {
88                          throw new CSRuntimeException("Failed to look up asset " + child + " in AssetRelationTree.", errno);
89                      }
90                  }
91              }
92  
93              // found node. get its parent
94              IList art = ics.GetList("AssetRelationTree");
95              ics.RegisterList("AssetRelationTree", null);
96  
97              List<AssetId> parents = new ArrayList<AssetId>();
98  
99              if (art == null || !art.hasData() || art.numRows() == 0) {
100                 if (log != null && log.isTraceEnabled()) {
101                     log.trace("Failed to locate " + child + " in AssetRelationTree.");
102                 }
103             } else {
104 
105                 List<String> childNodeIds = new ArrayList<String>();
106                 for (IList row : new IterableIListWrapper(art)) {
107                     if (child.getType().equals(getStringValue(row, "otype"))) {
108                         String nid = getStringValue(row, "nid");
109                         String ncode = getStringValue(row, "ncode");
110                         if (log != null && log.isTraceEnabled()) {
111                             log.trace("Found " + child + " in AssetRelationTree.  Node ID: " + nid + ", ncode: " + ncode + ", expecting ncode: " + associationName);
112                         }
113                         if (associationName.equals(ncode)) {
114                             childNodeIds.add(getStringValue(row, "nid"));
115                         }
116                     }
117                 }
118 
119                 for (String nid : childNodeIds) {
120                     vl.clear();
121                     vl.setValString("ftcmd", "getparent");
122                     vl.setValString("treename", "AssetRelationTree");
123                     vl.setValString("node", nid);
124                     if (ics.TreeManager(vl) && ics.GetErrno() >= 0) {
125                         art = ics.GetList("AssetRelationTree");
126                         ics.RegisterList("AssetRelationTree", null);
127                         AssetId parent = new AssetIdImpl(getStringValue(art, "otype"), Long.valueOf(getStringValue(art, "oid")));
128                         if (log != null && log.isTraceEnabled()) {
129                             log.trace(child + " in AssetRelationTree has a parent " + parent);
130                         }
131                         if (expectedParentType == null) {
132                             parents.add(parent);
133                         } else {
134                             if (expectedParentType.equals(parent.getType())) {
135                                 parents.add(parent);
136                             } else {
137                                 if (log != null && log.isDebugEnabled()) {
138                                     log.debug("Parent " + parent + " is not of the expected type (" + expectedParentType + ") so it is being excluded from the return list for child: " + child);
139                                 }
140                             }
141                         }
142                     } else {
143                         throw new CSRuntimeException("Failed to look up parent of article " + child + " in AssetRelationTree.  TreeManager call failed unexpectedly", ics.GetErrno());
144                     }
145 
146                 }
147             }
148 
149             return parents;
150         } else {
151             throw new CSRuntimeException("Failed to look up article " + child + " in AssetRelationTree.  TreeManager call failed unexpectedly", ics.GetErrno());
152         }
153     }
154 
155     /**
156      * Look up parents in Asset Relation Tree for the specified child.  Records asset dependencies as required (either a
157      * qualified or an unqualified unknowndeps).
158      *
159      * @param ics             context
160      * @param child           asset id that will have its parents retrieved
161      * @param associationName name of association to use for lookup.  May not ever be null.
162      * @return list of parents, never null.
163      */
164     public static Collection<AssetId> getParents(ICS ics, AssetId child, String... associationName) {
165 
166         // validate input
167         if (ics == null) throw new IllegalArgumentException("ICS cannot be null");
168         if (child == null) throw new IllegalArgumentException("Child asset id is required");
169         if (associationName == null) throw new IllegalArgumentException("Association name may not be null");
170 
171         List<String> assocNames = Arrays.asList(associationName); // so lame...
172 
173         Collection<AssetId> parents = new HashSet<AssetId>();
174 
175         for (Row childInfo : TreeHelper.findNode(ics, "AssetRelationTree", child)) {
176 
177             // right assoc name?
178             String ncode = childInfo.getString("ncode");
179             if (!assocNames.contains(ncode)) {
180                 if (LOG.isTraceEnabled())
181                     LOG.trace("Asset " + child + " with node " + childInfo.getString("nid") + " is not the child of any other asset using the association name " + assocNames + ". (This node is for the name " + ncode + ".)");
182                 // nope...
183                 continue;
184             }
185 
186             // Yup. Find its parent.
187             for (Row parentInfo : TreeHelper.findParents(ics, "AssetRelationTree", childInfo.getString("nid"))) {
188                 AssetId parent = AssetIdUtils.createAssetId(parentInfo.getString("otype"), parentInfo.getString("oid"));
189                 if (LOG.isTraceEnabled())
190                     LOG.trace("Found parent " + parent + " of child " + child + " with association name " + ncode);
191                 parents.add(parent);
192             }
193         }
194 
195         // log dep on child asset
196         LogDep.logDep(ics, child);
197 
198         // log dep on context
199         // todo: inspect the specified association definitions in "associationName" and only
200         // record asset-type specific deps instead of unknowndep if possible
201         Render.UnknownDeps(ics);
202 
203         if (LOG.isDebugEnabled()) {
204             LOG.debug("Looked up child asset " + child + " in AssetRelationTree for parents with the association names " + Arrays.asList(associationName) + " and found " + parents.size() + " results.  Details: " + (LOG.isTraceEnabled() ? parents : ""));
205         }
206 
207         return parents;
208     }
209 }