Coverage Report - org.apache.tiles.request.locale.PostfixedApplicationResource
 
Classes in this File Line Coverage Branch Coverage Complexity
PostfixedApplicationResource
65%
63/96
46%
29/62
4.727
 
 1  
 /*
 2  
  * $Id$
 3  
  *
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  * http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 package org.apache.tiles.request.locale;
 23  
 
 24  
 import java.util.Arrays;
 25  
 import java.util.HashSet;
 26  
 import java.util.List;
 27  
 import java.util.Set;
 28  
 import java.util.Locale;
 29  
 import org.apache.tiles.request.ApplicationResource;
 30  
 import org.slf4j.Logger;
 31  
 import org.slf4j.LoggerFactory;
 32  
 
 33  
 /**
 34  
  * An ApplicationResource whose localization is managed by postfixing the file name.
 35  
  * The various localizations are file sitting next to each other, with the locale identified in the postfix.
 36  
  *
 37  
  * For instance:
 38  
  * <pre>
 39  
  * /WEB-INF/tiles.xml
 40  
  * /WEB-INF/tiles_fr.xml
 41  
  * /WEB-INF/tiles_it.xml
 42  
  * /WEB-INF/tiles_it_IT.xml
 43  
  * </pre>
 44  
  *
 45  
  * Two PostfixedApplicationResources are equals if they share the same localized path and the same class.
 46  
  *
 47  
  * @version $Rev$ $Date$
 48  
  */
 49  
 public abstract class PostfixedApplicationResource implements ApplicationResource {
 50  
 
 51  1
     private static final Logger LOG = LoggerFactory.getLogger(PostfixedApplicationResource.class);
 52  
 
 53  
     /** The path without its suffix and its locale postfix. */
 54  
     private String pathPrefix;
 55  
     /** The suffix. */
 56  
     private String suffix;
 57  
     /** The Locale. */
 58  
     private Locale locale;
 59  
 
 60  
     /**
 61  
      * Create a new PostfixedApplicationResource for the specified path.
 62  
      * @param localePath the path including localization.
 63  
      */
 64  30
     protected PostfixedApplicationResource(String localePath) {
 65  30
         int prefixIndex = localePath.indexOf('_', localePath.lastIndexOf("/"));
 66  30
         int suffixIndex = localePath.lastIndexOf('.');
 67  30
         if (suffixIndex < 0) {
 68  0
             suffix = "";
 69  0
             suffixIndex = localePath.length();
 70  
         } else {
 71  30
             suffix = localePath.substring(suffixIndex);
 72  
         }
 73  30
         if (prefixIndex < 0) {
 74  9
             pathPrefix = localePath.substring(0, suffixIndex);
 75  9
             locale = Locale.ROOT;
 76  
         } else {
 77  21
             pathPrefix = localePath.substring(0, prefixIndex);
 78  21
             String localeString = localePath.substring(prefixIndex + 1, suffixIndex);
 79  21
             Locale found = localeFrom(localeString);
 80  21
             locale = validateLocale(found);
 81  21
             if (Locale.ROOT.equals(locale)) {
 82  6
                 pathPrefix = suffixIndex < 0 ? localePath : localePath.substring(0, suffixIndex);
 83  
 
 84  6
                 LOG.warn("No supported matching language for locale \"" + localeString + "\". Using "
 85  
                         + getPath() + " as a non-localized resource path. see TILES-571");
 86  
 
 87  15
             } else if (!localeString.equalsIgnoreCase(getPostfix(locale).substring(1))) {
 88  6
                 LOG.warn("For resource " + localePath
 89  
                         + " the closest supported matching locale to \"" + localeString + "\" is \"" + locale
 90  
                         + "\". Using " + getPath() + " as resource path. see TILES-571");
 91  
             }
 92  
         }
 93  30
     }
 94  
 
 95  
     /**
 96  
      * Create a new PostfixedApplicationResource for the specified path.
 97  
      * @param path the path excluding localization.
 98  
      * @param locale the Locale.
 99  
      */
 100  8
     protected PostfixedApplicationResource(String path, Locale locale) {
 101  8
         int suffixIndex = path.lastIndexOf('.');
 102  8
         if (suffixIndex < 0) {
 103  0
             suffix = "";
 104  0
             pathPrefix = path;
 105  
         } else {
 106  8
             pathPrefix = path.substring(0, suffixIndex);
 107  8
             suffix = path.substring(suffixIndex);
 108  
         }
 109  8
         this.locale = locale;
 110  8
     }
 111  
 
 112  
     /** {@inheritDoc} */
 113  
     @Override
 114  
     public final String getLocalePath() {
 115  28
         return getLocalePath(locale);
 116  
     }
 117  
 
 118  
     /** {@inheritDoc} */
 119  
     @Override
 120  
     public final String getPath() {
 121  40
         return pathPrefix + suffix;
 122  
     }
 123  
 
 124  
     /** {@inheritDoc} */
 125  
     @Override
 126  
     public final String getLocalePath(Locale newLocale) {
 127  38
         return pathPrefix + getPostfix(newLocale) + suffix;
 128  
     }
 129  
 
 130  
     /**
 131  
      * Get the postfix for that Locale.
 132  
      * @param locale a locale.
 133  
      * @return the matching postfix.
 134  
      */
 135  
     private static final String getPostfix(Locale locale) {
 136  53
         if (locale == null) {
 137  2
             return "";
 138  
         }
 139  
 
 140  51
         StringBuilder builder = new StringBuilder();
 141  51
         String language = locale.getLanguage();
 142  51
         String country = locale.getCountry();
 143  51
         String variant = locale.getVariant();
 144  51
         if (!"".equals(language)) {
 145  39
             builder.append("_");
 146  39
             builder.append(language);
 147  39
             if (!"".equals(country)) {
 148  16
                 builder.append("_");
 149  16
                 builder.append(country);
 150  16
                 if (!"".equals(variant)) {
 151  8
                     builder.append("_");
 152  8
                     builder.append(variant);
 153  
                 }
 154  
             }
 155  
         }
 156  51
         return builder.toString();
 157  
     }
 158  
 
 159  
     /** {@inheritDoc} */
 160  
     @Override
 161  
     public final Locale getLocale() {
 162  28
         return locale;
 163  
     }
 164  
 
 165  
     /** {@inheritDoc} */
 166  
     @Override
 167  
     public int hashCode() {
 168  0
         final int prime = 31;
 169  0
         int result = 1;
 170  0
         result = prime * result + ((locale == null) ? 0 : locale.hashCode());
 171  0
         result = prime * result + ((pathPrefix == null) ? 0 : pathPrefix.hashCode());
 172  0
         result = prime * result + ((suffix == null) ? 0 : suffix.hashCode());
 173  0
         return result;
 174  
     }
 175  
 
 176  
     /** {@inheritDoc} */
 177  
     @Override
 178  
     public boolean equals(Object obj) {
 179  0
         if (this == obj)
 180  0
             return true;
 181  0
         if (obj == null)
 182  0
             return false;
 183  0
         if (getClass() != obj.getClass())
 184  0
             return false;
 185  0
         PostfixedApplicationResource other = (PostfixedApplicationResource) obj;
 186  0
         if (locale == null) {
 187  0
             if (other.locale != null)
 188  0
                 return false;
 189  0
         } else if (!locale.equals(other.locale))
 190  0
             return false;
 191  0
         if (pathPrefix == null) {
 192  0
             if (other.pathPrefix != null)
 193  0
                 return false;
 194  0
         } else if (!pathPrefix.equals(other.pathPrefix))
 195  0
             return false;
 196  0
         if (suffix == null) {
 197  0
             if (other.suffix != null)
 198  0
                 return false;
 199  0
         } else if (!suffix.equals(other.suffix))
 200  0
             return false;
 201  0
         return true;
 202  
     }
 203  
 
 204  
     private static Locale localeFrom(String localeString) {
 205  
         Locale result;
 206  21
         int countryIndex = localeString.indexOf('_');
 207  21
         if (countryIndex < 0) {
 208  11
             result = new Locale(localeString);
 209  
         } else {
 210  10
             int variantIndex = localeString.indexOf('_', countryIndex + 1);
 211  10
             if (variantIndex < 0) {
 212  8
                 result = new Locale(
 213  
                         localeString.substring(0, countryIndex),
 214  
                         localeString.substring(countryIndex + 1));
 215  
             } else {
 216  2
                 result = new Locale(
 217  
                         localeString.substring(0, countryIndex),
 218  
                         localeString.substring(countryIndex + 1, variantIndex),
 219  
                         localeString.substring(variantIndex + 1));
 220  
             }
 221  
         }
 222  21
         return result;
 223  
     }
 224  
     /*
 225  
     private static Locale java7_localeFrom(String localeString) {
 226  
         Locale.Builder builder = new Locale.Builder();
 227  
         try {
 228  
             int countryIndex = localeString.indexOf('_');
 229  
             if (countryIndex < 0) {
 230  
                 builder.setLanguage(localeString);
 231  
             } else {
 232  
                 int variantIndex = localeString.indexOf('_', countryIndex + 1);
 233  
                 builder.setLanguage(localeString.substring(0, countryIndex));
 234  
                 if (variantIndex < 0) {
 235  
                     builder.setRegion(localeString.substring(countryIndex + 1));
 236  
                 } else {
 237  
                     builder.setRegion(localeString.substring(countryIndex + 1, variantIndex));
 238  
                     builder.setVariant(localeString.substring(variantIndex + 1));
 239  
                 }
 240  
             }
 241  
         } catch (IllformedLocaleException ex) {
 242  
             LOG.debug(localeString + " is an ill-formed locale", ex);
 243  
         }
 244  
         return builder.build();
 245  
     }
 246  
     */
 247  
 
 248  1
     private static Set<Locale> availableLocales = new HashSet<Locale>(Arrays.asList(Locale.getAvailableLocales()));
 249  
 
 250  
     private static Locale validateLocale(Locale locale) {
 251  21
         Locale withoutVariant = locale.getVariant().isEmpty()
 252  
                 ? locale
 253  
                 : new Locale(locale.getLanguage(), locale.getCountry());
 254  
 
 255  21
         Locale result = locale;
 256  21
         if (!availableLocales.contains(withoutVariant)) {
 257  12
             if (!result.getCountry().isEmpty()) {
 258  6
                 result = new Locale(result.getLanguage());
 259  
             }
 260  12
             if (!availableLocales.contains(result)) {
 261  6
                 result = Locale.ROOT;
 262  
             }
 263  
         }
 264  21
         return result;
 265  
     }
 266  
 }