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  package com.fatwire.gst.foundation.facade.mda;
17  
18  import java.util.ArrayList;
19  import java.util.Arrays;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Enumeration;
23  import java.util.List;
24  import java.util.Locale;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.commons.logging.Log;
28  
29  import COM.FutureTense.Interfaces.FTValList;
30  import COM.FutureTense.Interfaces.ICS;
31  
32  import com.fatwire.assetapi.data.AssetId;
33  import com.fatwire.cs.core.db.PreparedStmt;
34  import com.fatwire.cs.core.db.StatementParam;
35  import com.fatwire.gst.foundation.facade.logging.LogUtil;
36  import com.fatwire.gst.foundation.facade.runtag.asset.AssetLoadByName;
37  import com.fatwire.gst.foundation.facade.runtag.render.LogDep;
38  import com.fatwire.gst.foundation.facade.sql.IListIterable;
39  import com.fatwire.gst.foundation.facade.sql.Row;
40  import com.fatwire.gst.foundation.facade.sql.SqlHelper;
41  import com.fatwire.mda.Dimension;
42  import com.fatwire.mda.DimensionException;
43  import com.fatwire.mda.DimensionFilterInstance;
44  import com.fatwire.mda.DimensionManager;
45  import com.fatwire.mda.DimensionSetInstance;
46  import com.fatwire.mda.DimensionableAssetManager;
47  import com.fatwire.system.Session;
48  import com.fatwire.system.SessionFactory;
49  import com.openmarket.xcelerate.asset.AssetIdImpl;
50  
51  public class DefaultLocaleService implements LocaleService {
52      private static final Log LOG = LogUtil.getLog(DefaultLocaleService.class);
53  
54      /** the variable name for the id of the current Dimension */
55  
56      private final String localeVar;
57  
58      /** the variable name for the current requested language */
59  
60      private final String langVar;
61  
62      private final ICS ics;
63  
64      private Session session;
65  
66      /**
67       * Constructor with "lang" and "locale" as variable names for langVar and
68       * localeVar.
69       * 
70       * @param ics
71       */
72      public DefaultLocaleService(final ICS ics) {
73          this(ics, "lang", "locale");
74      }
75  
76      /**
77       * 
78       * Constructor.
79       * 
80       * @param ics
81       * @param langVar the name of the ics variable for the current 'language',
82       *            as in en_US.
83       * @param localeVar the name of the ics variable for the current dimension
84       *            id.
85       */
86      public DefaultLocaleService(ICS ics, String langVar, String localeVar) {
87          if (ics == null) {
88              throw new IllegalArgumentException("ICS must not be null.");
89          }
90  
91          this.ics = ics;
92          this.langVar = langVar;
93          this.localeVar = localeVar;
94  
95      }
96  
97      /*
98       * (non-Javadoc)
99       * 
100      * @see
101      * com.fatwire.gst.foundation.facade.mda.LocaleService#findTranslation(java
102      * .lang.String, java.lang.String, java.lang.String, java.lang.String)
103      */
104     @Override
105     public AssetId findTranslation(final String c, final String cid, final String site,
106             final String preferredLocaleDimensionId) {
107         return findTranslation(new AssetIdImpl(c, Long.parseLong(cid)), site,
108                 Long.parseLong(preferredLocaleDimensionId));
109     }
110 
111     /*
112      * (non-Javadoc)
113      * 
114      * @see
115      * com.fatwire.gst.foundation.facade.mda.LocaleService#findTranslation(com
116      * .fatwire.assetapi.data.AssetId, java.lang.String, long)
117      */
118 
119     @Override
120     public AssetId findTranslation(final AssetId id, final String site, final long preferredDimension) {
121 
122         final long dimensionSetId = locateDimensionSetForSite(site);
123 
124         return findTranslation(id, preferredDimension, dimensionSetId);
125     }
126 
127     /*
128      * (non-Javadoc)
129      * 
130      * @see
131      * com.fatwire.gst.foundation.facade.mda.LocaleService#findTranslation(com
132      * .fatwire.assetapi.data.AssetId, long, long)
133      */
134 
135     @Override
136     public AssetId findTranslation(final AssetId id, final long preferredDimension, final long dimensionSetId) {
137         if (id == null) {
138             throw new IllegalArgumentException("Required Asset ID missing");
139         }
140 
141         if (_isInputAssetDimensionPreferred(id, preferredDimension)) {
142             LOG.debug("Input dimension is already in the preferred dimension.  Not invoking dimension set filter.  Asset: "
143                     + id + ", dimension: " + preferredDimension);
144             return id;
145         } else {
146             LOG.debug("About to look for translations.  Input asset id: " + id + ", dimension set: " + dimensionSetId
147                     + ", preferred dimension: " + preferredDimension);
148         }
149 
150         // *****************************************************************************
151         // The core business logic of this helper class is encapsulated in these
152         // 3 lines
153         final DimensionSetInstance dimset = _getDimensionSet(dimensionSetId);
154         return findTranslation(id, preferredDimension, dimset);
155 
156     }
157 
158     /*
159      * (non-Javadoc)
160      * 
161      * @see
162      * com.fatwire.gst.foundation.facade.mda.LocaleService#findTranslation(com
163      * .fatwire.assetapi.data.AssetId, long, java.lang.String)
164      */
165 
166     @Override
167     public AssetId findTranslation(final AssetId id, final long preferredDimension, final String dimensionSetName) {
168         if (id == null) {
169             throw new IllegalArgumentException("Required Asset ID missing");
170         }
171         final Dimension locale = getLocaleForAsset(id);
172 
173         if (locale == null) {
174             LOG.debug("Asset is not localized.  Not invoking dimension set filter.  Asset: " + id);
175             return id;
176         }
177         if (locale.getId().getId() == preferredDimension) {
178             LOG.debug("Input dimension is already in the preferred dimension.  Not invoking dimension set filter.  Asset: "
179                     + id + ", dimension: " + preferredDimension);
180             return id;
181         } else {
182             LOG.debug("About to look for translations.  Input asset id: " + id + ", dimension set: " + dimensionSetName
183                     + ", preferred dimension: " + preferredDimension);
184         }
185 
186         // *****************************************************************************
187         // The core business logic of this helper class is encapsulated in these
188         // 3 lines
189         final DimensionSetInstance dimset = getDimensionSet(dimensionSetName);
190 
191         return findTranslation(id, preferredDimension, dimset);
192     }
193 
194     /*
195      * (non-Javadoc)
196      * 
197      * @see
198      * com.fatwire.gst.foundation.facade.mda.LocaleService#findTranslation(com
199      * .fatwire.assetapi.data.AssetId, long,
200      * com.fatwire.mda.DimensionSetInstance)
201      */
202 
203     @Override
204     public AssetId findTranslation(final AssetId id, final long preferredDimension, final DimensionSetInstance dimset) {
205 
206         final DimensionFilterInstance filter = _getPopulatedDimensionFilter(dimset, preferredDimension);
207         AssetId translated = findTranslation(id, filter);
208         if (translated == null)
209             LOG.warn("No translation found for asset " + id + " in dimension set " + dimset.getId() + " for dimension "
210                     + preferredDimension + ".");
211         return translated;
212     }
213 
214     // ///////////////////////////////////////////////////////////////////////////
215     // Helper functions
216 
217     private boolean _isInputAssetDimensionPreferred(final AssetId id, final long preferredDimension) {
218         final Dimension dim = getLocaleForAsset(id);
219         if (dim == null) {
220             return true; // if locale not found, tell that the asset is expected
221         }
222         // locale
223         return dim.getId().getId() == preferredDimension;
224     }
225 
226     private static final PreparedStmt FIND_DIMSET_FOR_SITE_PREPAREDSTMT = new PreparedStmt(
227             "select ds.id as id from DimensionSet ds, Publication p, AssetPublication ap where p.name = ? and p.id = ap.pubid and ap.assetid = ds.id and ds.status != 'VO' order by ds.updateddate",
228             Arrays.asList("DimensionSet", "AssetPublication", "Publication"));
229 
230     static {
231         FIND_DIMSET_FOR_SITE_PREPAREDSTMT.setElement(0, "Publication", "name");
232     }
233 
234     /**
235      * Locates a single dimension set in a site. If no match is found, an
236      * exception is thrown. If more than one match is found, an exception is
237      * thrown.
238      * 
239      * @param site site containing a dimension set
240      * @return DimensionSet ID
241      */
242     public long locateDimensionSetForSite(final String site) {
243         if (StringUtils.isBlank(site)) {
244             throw new IllegalArgumentException("Required site name missing");
245         }
246         final StatementParam params = FIND_DIMSET_FOR_SITE_PREPAREDSTMT.newParam();
247         params.setString(0, site);
248         final IListIterable list = SqlHelper.select(ics, FIND_DIMSET_FOR_SITE_PREPAREDSTMT, params);
249 
250         final int numRows = list.size();
251         if (numRows == 0) {
252             throw new IllegalStateException(
253                     "A DimensionSet has not been defined for site '"
254                             + site
255                             + "'. Cannot determine any translation unless some locales (Dimensions) are enabled for that site. Aborting operation.");
256         }
257         if (numRows > 1) {
258             final StringBuilder msg = new StringBuilder("More than one dimension set found in site " + site
259                     + ".  Exactly one is expected.  Dimension set ids: ");
260             for (final Row row : list) {
261                 final String id = row.getString("id");
262                 LogDep.logDep(ics, "DimensionSet", id);
263                 msg.append(id).append(" ");
264             }
265             throw new IllegalStateException(msg.append(".").toString());
266         }
267 
268         final String id = list.iterator().next().getString("id");
269         LogDep.logDep(ics, "DimensionSet", id);
270         return Long.parseLong(id);
271     }
272 
273     private DimensionFilterInstance _getPopulatedDimensionFilter(final DimensionSetInstance dimset,
274             final long dimensionId) {
275 
276         // Set the filter's preferred dimension
277         // Equivalent to:
278         // %><dimensionset:asset assettype="Dimension"
279         // assetid="<%=localeDimensionId%>" /><%
280         final Dimension preferredDimension = getDM().loadDimension(dimensionId);
281         if (preferredDimension == null) {
282             throw new RuntimeException("Attempted to load Dimension with id " + dimensionId + " but it came back null");
283         }
284         return _getPopulatedDimensionFilter(dimset, preferredDimension);
285     }
286 
287     private DimensionFilterInstance _getPopulatedDimensionFilter(final DimensionSetInstance dimset,
288             final Dimension preferredDimension) {
289         DimensionFilterInstance filter;
290         try {
291             filter = dimset.getFilter();
292         } catch (final DimensionException e) {
293             throw new RuntimeException("Could not get Dimension Filter from DimensionSet", e);
294         }
295 
296         filter.setDimensonPreference(Collections.singletonList(preferredDimension));
297         return filter;
298     }
299 
300     private DimensionSetInstance _getDimensionSet(final long dimSetId) {
301         final String DIMSET_OBJ_NAME = "LocaleUtils:findTranslation:theDimensionSet:DimensionSet";
302         // Load the site-specific DimensionSet asset
303         ics.SetObj(DIMSET_OBJ_NAME, null); // clear first
304         final FTValList args = new FTValList();
305         args.put("NAME", DIMSET_OBJ_NAME);
306         args.put("TYPE", "DimensionSet");
307         args.put("OBJECTID", Long.toString(dimSetId));
308         args.put("EDITABLE", "FALSE");
309         ics.runTag("ASSET.LOAD", args);
310 
311         if (ics.GetErrno() < 0) {
312             throw new IllegalStateException("Could not load dimension set.  Errno: " + ics.GetErrno());
313         }
314 
315         final Object o = ics.GetObj(DIMSET_OBJ_NAME);
316         ics.SetObj(DIMSET_OBJ_NAME, null);
317         if (o == null) {
318             throw new IllegalStateException("Could not load dimension set but we got no errno... unexpected...");
319         }
320 
321         DimensionSetInstance dimset;
322         if (o instanceof DimensionSetInstance) {
323             dimset = (DimensionSetInstance) o;
324         } else {
325             throw new IllegalStateException("Loaded an asset that is not a DimensionSetInstance.");
326         }
327         return dimset;
328     }
329 
330     /*
331      * (non-Javadoc)
332      * 
333      * @see
334      * com.fatwire.gst.foundation.facade.mda.LocaleService#getDimensionSet(java
335      * .lang.String)
336      */
337 
338     @Override
339     public DimensionSetInstance getDimensionSet(final String name) {
340         final String DIMSET_OBJ_NAME = "LocaleUtils:findTranslation:theDimensionSet:DimensionSet";
341         ics.SetObj(DIMSET_OBJ_NAME, null);
342         final AssetLoadByName a = new AssetLoadByName();
343         a.setAssetType("DimensionSet");
344         a.setAssetName(name);
345         a.setEditable(false);
346         a.setName(DIMSET_OBJ_NAME);
347         a.execute(ics);
348 
349         if (ics.GetErrno() < 0) {
350             throw new IllegalStateException("Could not load dimension set.  Errno: " + ics.GetErrno());
351         }
352 
353         final Object o = ics.GetObj(DIMSET_OBJ_NAME);
354         ics.SetObj(DIMSET_OBJ_NAME, null);
355         if (o == null) {
356             throw new IllegalStateException("Could not load dimension set but we got no errno... unexpected...");
357         }
358 
359         DimensionSetInstance dimset;
360         if (o instanceof DimensionSetInstance) {
361             dimset = (DimensionSetInstance) o;
362         } else {
363             throw new IllegalStateException("Loaded an asset that is not a DimensionSetInstance");
364         }
365         return dimset;
366     }
367 
368     private DimensionableAssetManager dam;
369 
370     /**
371      * Shorthand function for returning the DimensionableAssetManager.
372      * 
373      * @return DimensionableAssetManager
374      */
375     public DimensionableAssetManager getDAM() {
376         if (dam == null) {
377             dam = getManager(DimensionableAssetManager.class);
378         }
379         return dam;
380     }
381 
382     private DimensionManager dm;
383 
384     /**
385      * Shorthand function for returning the DimensionManager.
386      * 
387      * @return DimensionManager
388      */
389     protected DimensionManager getDM() {
390         if (dm == null) {
391             dm = getManager(DimensionManager.class);
392         }
393         return dm;
394     }
395 
396     /*
397      * (non-Javadoc)
398      * 
399      * @see
400      * com.fatwire.gst.foundation.facade.mda.LocaleService#getLocaleForAsset
401      * (com.fatwire.assetapi.data.AssetId)
402      */
403 
404     @Override
405     public Dimension getLocaleForAsset(final AssetId id) {
406         final Collection<Dimension> dims = getDAM().getDimensionsForAsset(id);
407         for (final Dimension dim : dims) {
408             if ("locale".equalsIgnoreCase(dim.getGroup())) {
409                 return dim;
410             }
411         }
412         return null;
413     }
414 
415     /*
416      * (non-Javadoc)
417      * 
418      * @see
419      * com.fatwire.gst.foundation.facade.mda.LocaleService#getDimensionIdForName
420      * (java.lang.String)
421      */
422 
423     @Override
424     public long getDimensionIdForName(final String name) {
425         final AssetId id = getDimensionAssetIdForName(name);
426         return id == null ? -1 : id.getId();
427     }
428 
429     /*
430      * (non-Javadoc)
431      * 
432      * @see com.fatwire.gst.foundation.facade.mda.LocaleService#
433      * getDimensionAssetIdForName(java.lang.String)
434      */
435 
436     @Override
437     public AssetId getDimensionAssetIdForName(final String name) {
438         final Dimension dim = getDimensionForName(name);
439         return dim == null ? null : dim.getId();
440     }
441 
442     /*
443      * (non-Javadoc)
444      * 
445      * @see
446      * com.fatwire.gst.foundation.facade.mda.LocaleService#getDimensionForName
447      * (java.lang.String)
448      */
449 
450     @Override
451     public Dimension getDimensionForName(final String name) {
452         return getDM().loadDimension(name);
453 
454     }
455 
456     /*
457      * (non-Javadoc)
458      * 
459      * @see
460      * com.fatwire.gst.foundation.facade.mda.LocaleService#getNameForDimensionId
461      * (long)
462      */
463 
464     @Override
465     public String getNameForDimensionId(final long dimensionid) {
466         final Dimension dim = getDM().loadDimension(dimensionid);
467         return dim == null ? null : dim.getName();
468     }
469 
470     protected Session getSession() {
471         if (session == null) {
472             session = SessionFactory.getSession(ics);
473 
474         }
475         return session;
476     }
477 
478     @SuppressWarnings("unchecked")
479     protected <T> T getManager(final Class<T> c) {
480         return (T) getSession().getManager(c.getName());
481     }
482 
483     @Override
484     public AssetId findTranslation(AssetId id, DimensionFilterInstance filter) {
485         // Get the relatives using the appropriate filter
486         final Collection<AssetId> relatives = getDAM().getRelatives(id, filter, "Locale");
487         // *****************************************************************************
488 
489         // make the result pretty
490         if (relatives == null) {
491             LOG.debug("No translation found for asset " + id + ".");
492             return null;
493         } else {
494             switch (relatives.size()) {
495                 case 0: {
496                     LOG.debug("No translation found for " + id + ".");
497                     // Note May 4, 2010 by Tony Field - this had been changed to
498                     // return the input ID but that
499                     // is incorrect. The contract clearly states that null is to
500                     // be returned if no matching
501                     // relatives are found. When null is returned and it is not
502                     // expected, often the incorrect
503                     // dimension filter is configured.
504                     return null;
505                 }
506                 case 1: {
507                     final AssetId relative = relatives.iterator().next();
508                     LOG.trace("LocaleUtils.findTranslation: RELATIVE FOUND... " + relative.getType() + " '"
509                             + relative.getId() + "' // errno = " + ics.GetErrno());
510                     return relative;
511 
512                 }
513                 default: {
514                     throw new IllegalStateException("found more than one translation for asset " + id
515                             + " and that is not supposed to be possible.");
516                 }
517             }
518         }
519     }
520 
521     /**
522      * Return a dimension filter instance corresponding to the dimension set
523      * specified by the user (or discovered by the tag). The dimension filter is
524      * configured with the preferred dimensions of the user (also configured).
525      * <p/>
526      * The preferred locales are identified by checking the following locations,
527      * in the order specified:
528      * <ol>
529      * <li>set by the lang attribute by locale name
530      * <li>detected by finding the locale dimension id in the ics variable
531      * "locale"
532      * <li>detected by finding the locale name in the ics variable "locale"
533      * <li>detected by finding the locale dimension id in the ics session
534      * variable "locale"
535      * <li>detected by finding the locale name in the ics session variable
536      * "locale"
537      * <li>detected by reading the Accept-Language header
538      * </ol>
539      * The dimension set is identified by checking in the following places, in
540      * order:
541      * <ol>
542      * <li>set by the dimset attribute by name of dimension set
543      * <li>set by dimset attribute by the id of the dimension set
544      * <li>looked up by finding the site name in the ics variable "site" and
545      * loading the single dimension set associated with that site
546      * </ol>
547      * 
548      * @return a dimension filter, configured with the set preferred locales, or
549      *         null, if either the dimension set or the preferred dimensions
550      *         could not be found (with extensive errors)
551      */
552     public DimensionFilterInstance getDimensionFilter(String site) {
553 
554         DimensionFilterInstance filter;
555         try {
556             DimensionSetInstance dimSet = locateDimensionSetInstanceForSite(site);
557             if (dimSet == null) {
558                 if (LOG.isTraceEnabled()) {
559                     LOG.trace("no DimensionSet returned from getDimensionSet().");
560                 }
561                 return null;
562             }
563             Collection<AssetId> preferredLocales = getPreferredLocales();
564 
565             filter = DimensionUtils.getDimensionFilter(DimensionUtils.getDM(ics), preferredLocales, dimSet);
566             if (LOG.isDebugEnabled()) {
567                 LOG.debug("Located dimension filter: " + filter + " in dimensionSet " + dimSet
568                         + " with preferred locales: " + preferredLocales + " ");
569             }
570         } catch (DimensionException e) {
571             LOG.error("Could not locate dimension filter", e);
572             filter = null;
573         } catch (RuntimeException e) {
574             LOG.error("Could not locate dimension filter", e);
575             filter = null;
576         }
577         return filter;
578     }
579 
580     /**
581      * Get the locale that the user explicitly specified. If not set, null is
582      * returned.
583      * 
584      * @return the id of the locale that the user explicitly set. Handles
585      *         setting by name or assetid.
586      */
587     protected final AssetId getExplicitlySpecifiedLocale() {
588 
589         String localeName = ics.GetVar(langVar);
590         // check for explicitly specified by name
591         if (StringUtils.isNotBlank(localeName)) {
592             Dimension d = DimensionUtils.getDimensionForName(ics, localeName);
593             if (d != null) {
594                 LOG.trace("Preferred locale explicitly set to " + localeName);
595                 return d.getId();
596             }
597         }
598         return null;
599     }
600 
601     /**
602      * Get the ordered list of preferred locales that the user wants. Multiple
603      * attempts are made to figure out the right locale.
604      * 
605      * @return collection of asset identifiers of the preferred locales
606      */
607     protected final Collection<AssetId> getPreferredLocales() {
608         AssetId result = getExplicitlySpecifiedLocale();
609         if (result != null)
610             return Collections.singleton(result);
611 
612         // next, check for implicitly specified by ID using locale variable
613         String l = ics.GetVar(localeVar);
614         try {
615             long localeIdFromVar = Long.parseLong(l);
616             DimensionManager dm = DimensionUtils.getDM(ics);
617             Dimension d = dm.loadDimension(localeIdFromVar);
618             if (d != null) {
619                 LOG.trace("Preferred locale detected in ICS context using 'locale' variable: " + localeIdFromVar);
620                 return Collections.singletonList(d.getId());
621             }
622         } catch (NumberFormatException e) {
623             // maybe it's a locale name...
624             try {
625                 Dimension d = DimensionUtils.getDimensionForName(ics, localeVar);
626                 if (d != null) {
627                     LOG.trace("Preferred locale detected in ICS context using 'locale' variable: " + localeVar);
628                     return Collections.singletonList(d.getId());
629                 }
630             } catch (Exception ex) {
631                 // nope... don't worry, we'll find it....
632             }
633         }
634 
635         // next, check for implicitly specified by ID using locale session
636         // variable
637         String localeSSVar = ics.GetSSVar(localeVar);
638         try {
639             long localeIdFromSSVar = Long.parseLong(localeSSVar);
640             DimensionManager dm = DimensionUtils.getDM(ics);
641             Dimension d = dm.loadDimension(localeIdFromSSVar);
642             if (d != null) {
643                 LOG.trace("Preferred locale detected in ICS context using 'locale' session variable: "
644                         + localeIdFromSSVar);
645                 return Collections.singletonList(d.getId());
646             }
647         } catch (NumberFormatException e) {
648             // maybe it's a locale name...
649             try {
650                 Dimension d = DimensionUtils.getDimensionForName(ics, localeSSVar);
651                 if (d != null) {
652                     LOG.trace("Preferred locale detected in ICS context using 'locale' session variable: "
653                             + localeSSVar);
654                     return Collections.singletonList(d.getId());
655                 }
656             } catch (Exception ex) {
657                 // nope... don't worry, we'll find it....
658             }
659         }
660 
661         // finally, get the locale from the servlet request's Accept-Language
662         // header..
663         List<AssetId> preferredLocales = new ArrayList<AssetId>();
664         @SuppressWarnings({ "rawtypes", "deprecation" })
665         Enumeration locales = ics.getIServlet().getServletRequest().getLocales();
666         while (locales.hasMoreElements()) {
667             Locale locale = (Locale) locales.nextElement();
668             if (locale != null) {
669                 String localeName = locale.toString();
670                 if (localeName != null && localeName.length() > 0) {
671                     try {
672                         Dimension dimension = DimensionUtils.getDimensionForName(ics, localeName);
673                         if (dimension != null) {
674                             preferredLocales.add(dimension.getId());
675                             LOG.trace("Found registered locale in user's Accept-Language header (or default): "
676                                     + localeName);
677                         }
678                     } catch (RuntimeException e) {
679                         // don't care if the dimension is not in the system -
680                         // they probably won't all be there
681                         // and we're guessing anyway, so it's okay.
682                         LOG.trace(
683                                 "Found a locale in the user's Accept-Language header, but it was not registered as a dimension: "
684                                         + localeName + " (this is not usually an error)", e);
685                     }
686                 }
687             }
688         }
689         return preferredLocales;
690     }
691 
692     /**
693      * Returns the DimensionSetInstance. This implementation expects one
694      * DimensionSet enabled for the current site.
695      * 
696      * @param ics
697      * @return
698      */
699     public final DimensionSetInstance locateDimensionSetInstanceForSite(String site) {
700         try {
701             if (StringUtils.isNotBlank(site)) {
702                 long discoveredId = locateDimensionSetForSite(site);
703                 LOG.trace("Auto-discovered dimension set because there is only one in site " + site + ": DimensionSet:"
704                         + discoveredId);
705                 return _getDimensionSet(discoveredId);
706             }
707         } catch (RuntimeException e) {
708             if (LOG.isTraceEnabled())
709                 LOG.trace("Could not auto-discover dimensionset: " + e);
710         }
711         return null;
712     }
713 }