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.WicketRuntimeException;
023: import org.apache.wicket.util.string.Strings;
024:
025: /**
026: * Contains the logic to locate a resource based on a path, a style (see
027: * {@link org.apache.wicket.Session}), a locale and a extension strings. The full filename
028: * will be built like:
029: * <path>_<style>_<locale>.<extension>.
030: * <p>
031: * Resource matches will be attempted in the following order:
032: * <ol>
033: * <li>1. <path>_<style>_<locale>.<extension></li>
034: * <li>2. <path>_<locale>.<extension></li>
035: * <li>3. <path>_<style>.<extension></li>
036: * <li>4. <path>.<extension></li>
037: * </ol>
038: * <p>
039: * Locales may contain a language, a country and a region or variant.
040: * Combinations of these components will be attempted in the following order:
041: * <ol>
042: * <li>locale.toString() see javadoc for Locale for more details</li>
043: * <li><language>_<country></li>
044: * <li><language></li>
045: * </ol>
046: * <p>
047: * Extensions may be a comma separated list of extensions, e.g. "properties,xml"
048: *
049: * @author Juergen Donnerstag
050: */
051: public class ResourceNameIterator implements Iterator {
052: // The locale to search for the resource file
053: private final Locale locale;
054:
055: // The extensions (comma separated) to search for the resource file
056: private final String extensions;
057:
058: // The various iterators used to locate the resource file
059: private final Iterator styleIterator;
060: private LocaleResourceNameIterator localeIterator;
061: private Iterator extenstionsIterator;
062:
063: // The latest exact Locale used
064: private Locale currentLocale;
065:
066: /**
067: * Construct.
068: *
069: * @param path
070: * The path of the resource without extension
071: * @param style
072: * A theme or style (see {@link org.apache.wicket.Session})
073: * @param locale
074: * The Locale to apply
075: * @param extensions
076: * the filname's extensions (comma separated)
077: */
078: public ResourceNameIterator(String path, final String style,
079: final Locale locale, final String extensions) {
080: this .locale = locale;
081: if (extensions == null) {
082: this .extensions = Strings.afterLast(path, '.');
083: path = Strings.beforeLast(path, '.');
084: } else {
085: this .extensions = extensions;
086: }
087:
088: this .styleIterator = new StyleAndVariationResourceNameIterator(
089: path, style, null);
090: }
091:
092: /**
093: * Get the exact Locale which has been used for the latest resource path.
094: *
095: * @return current Locale
096: */
097: public final Locale getLocale() {
098: return this .currentLocale;
099: }
100:
101: /**
102: * @see java.util.Iterator#hasNext()
103: */
104: public boolean hasNext() {
105: // Most inner loop. Loop through all extensions provided
106: if (this .extenstionsIterator != null) {
107: if (this .extenstionsIterator.hasNext() == true) {
108: return true;
109: }
110:
111: // If there are no more extensions, than return to the next outer
112: // loop (locale), get the next value from that loop and start
113: // over again with the first extension in the list.
114: extenstionsIterator = null;
115: }
116:
117: // 2nd inner loop: Loop through all Locale combinations
118: if (this .localeIterator != null) {
119: while (this .localeIterator.hasNext()) {
120: // Get the next Locale from the iterator and start the next
121: // inner iterator over again.
122: String newPath = (String) this .localeIterator.next();
123: this .currentLocale = this .localeIterator.getLocale();
124: this .extenstionsIterator = new ExtensionResourceNameIterator(
125: newPath, this .extensions);
126: if (this .extenstionsIterator.hasNext() == true) {
127: return true;
128: }
129: }
130: this .localeIterator = null;
131: }
132:
133: // Most outer loop: Loop through all combinations of styles and
134: // variations
135: while (this .styleIterator.hasNext()) {
136: String newPath = (String) this .styleIterator.next();
137:
138: this .localeIterator = new LocaleResourceNameIterator(
139: newPath, this .locale);
140: while (this .localeIterator.hasNext()) {
141: newPath = (String) this .localeIterator.next();
142: this .currentLocale = this .localeIterator.getLocale();
143: this .extenstionsIterator = new ExtensionResourceNameIterator(
144: newPath, this .extensions);
145: if (this .extenstionsIterator.hasNext() == true) {
146: return true;
147: }
148: }
149: }
150:
151: // No more combinations found. End of iteration.
152: return false;
153: }
154:
155: /**
156: * @see java.util.Iterator#next()
157: */
158: public Object next() {
159: if (extenstionsIterator != null) {
160: return extenstionsIterator.next();
161: }
162: throw new WicketRuntimeException(
163: "Illegal call of next(). Iterator not properly initialized");
164: }
165:
166: /**
167: * @see java.util.Iterator#remove()
168: */
169: public void remove() {
170: // ignore
171: }
172: }
|