001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.util.resource.locator;
018:
019: import java.util.Iterator;
020: import java.util.Locale;
021:
022: import org.apache.wicket.util.string.Strings;
023:
024: /**
025: * Contains the logic to build the various combinations of file path, style and
026: * locale required while searching for Wicket resources. The full filename will
027: * be built like: <path>_<style>_<locale>.<extension>.
028: * <p>
029: * Resource matches will be attempted in the following order:
030: * <ol>
031: * <li>1. <path>_<style>_<locale>.<extension></li>
032: * <li>2. <path>_<locale>.<extension></li>
033: * <li>3. <path>_<style>.<extension></li>
034: * <li>4. <path>.<extension></li>
035: * </ol>
036: * <p>
037: * Locales may contain a language, a country and a region or variant.
038: * Combinations of these components will be attempted in the following order:
039: * <ol>
040: * <li>locale.toString() see javadoc for Locale for more details</li>
041: * <li><language>_<country></li>
042: * <li><language></li>
043: * </ol>
044: *
045: * @author Juergen Donnerstag
046: * @author Jonathan Locke
047: */
048: public class LocaleResourceNameIterator implements Iterator {
049: /** The base path */
050: private final String path;
051:
052: /** The locale (see Session) */
053: private final Locale locale;
054:
055: /** Internal state */
056: private int state = 0;
057:
058: /**
059: * While iterating the various combinations, it will always contain the
060: * current combination used to create the path
061: */
062: private Locale currentLocale;
063:
064: /** Internal: used to compare with previous path to avoid duplicates */
065: private String currentPath;
066:
067: /**
068: * Construct.
069: *
070: * @param path
071: * @param locale
072: * @param style
073: */
074: public LocaleResourceNameIterator(final String path,
075: final Locale locale) {
076: this .path = path;
077: this .locale = locale;
078: }
079:
080: /**
081: * @return Locale
082: */
083: public Locale getLocale() {
084: return currentLocale;
085: }
086:
087: /**
088: *
089: * @see java.util.Iterator#hasNext()
090: */
091: public boolean hasNext() {
092: return (this .state < 4);
093: }
094:
095: /**
096: *
097: * @see java.util.Iterator#next()
098: */
099: public Object next() {
100: if (locale == null) {
101: state = 999;
102: return path;
103: }
104:
105: // 1. Apply Locale default toString() implementation. See Locale.
106: if (state == 0) {
107: this .state++;
108: this .currentLocale = locale;
109: this .currentPath = path + '_' + locale.toString();
110: return this .currentPath;
111: }
112:
113: // Get language and country, either of which may be the empty string
114: final String language = locale.getLanguage();
115: final String country = locale.getCountry();
116:
117: // 2. If country and language are available
118: if (state == 1) {
119: this .state++;
120:
121: if (!Strings.isEmpty(language) && !Strings.isEmpty(country)) {
122: this .currentLocale = new Locale(language, country);
123: String newPath = path + '_' + language + '_' + country;
124: if (this .currentPath.equals(newPath) == false) {
125: return newPath;
126: }
127: }
128: }
129:
130: // 3. If language is available
131: if (state == 2) {
132: this .state++;
133:
134: if (!Strings.isEmpty(language)) {
135: this .currentLocale = new Locale(language);
136: return path + '_' + language;
137: }
138: }
139:
140: // 4. The path only; without locale
141: this .state++;
142:
143: this .currentLocale = null;
144: return path;
145: }
146:
147: /**
148: *
149: * @see java.util.Iterator#remove()
150: */
151: public void remove() {
152: }
153: }
|