001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.hivemind.util;
016
017import java.util.Locale;
018import java.util.NoSuchElementException;
019
020import org.apache.hivemind.HiveMind;
021
022/**
023 *  Used in a wide variety of resource searches.  Generates
024 *  a series of name variations from a base name, a 
025 *  {@link java.util.Locale} and an optional suffix.
026 *
027 *  @author Howard Lewis Ship
028 */
029
030public class LocalizedNameGenerator
031{
032    private int _baseNameLength;
033    private String _suffix;
034    private StringBuffer _buffer;
035    private String _language;
036    private String _country;
037    private String _variant;
038    private int _state;
039    private int _prevState;
040
041    private static final int INITIAL = 0;
042    private static final int LCV = 1;
043    private static final int LC = 2;
044    private static final int LV = 3;
045    private static final int L = 4;
046    private static final int BARE = 5;
047    private static final int EXHAUSTED = 6;
048
049    public LocalizedNameGenerator(String baseName, Locale locale, String suffix)
050    {
051        _baseNameLength = baseName.length();
052
053        if (locale != null)
054        {
055            _language = locale.getLanguage();
056            _country = locale.getCountry();
057            _variant = locale.getVariant();
058        }
059
060        _state = INITIAL;
061        _prevState = INITIAL;
062
063        _suffix = suffix;
064
065        _buffer = new StringBuffer(baseName);
066
067        advance();
068    }
069
070    private void advance()
071    {
072        _prevState = _state;
073
074        while (_state != EXHAUSTED)
075        {
076            _state++;
077
078            switch (_state)
079            {
080                case LCV :
081
082                    if (HiveMind.isBlank(_variant))
083                        continue;
084
085                    return;
086
087                case LC :
088
089                    if (HiveMind.isBlank(_country))
090                        continue;
091
092                    return;
093
094                case LV :
095
096                    // If _country is null, then we've already generated this string
097                    // as state LCV and we can continue directly to state L
098
099                    if (HiveMind.isBlank(_variant) || HiveMind.isBlank(_country))
100                        continue;
101
102                    return;
103
104                case L :
105
106                    if (HiveMind.isBlank(_language))
107                        continue;
108
109                    return;
110
111                case BARE :
112                default :
113                    return;
114            }
115        }
116    }
117
118    /**
119     *  Returns true if there are more name variants to be
120     *  returned, false otherwise.
121     * 
122     **/
123
124    public boolean more()
125    {
126        return _state != EXHAUSTED;
127    }
128
129    /**
130     *  Returns the next localized variant.
131     * 
132     *  @throws NoSuchElementException if all variants have been
133     *  returned.
134     * 
135     **/
136
137    public String next()
138    {
139        if (_state == EXHAUSTED)
140            throw new NoSuchElementException();
141
142        String result = build();
143
144        advance();
145
146        return result;
147    }
148
149    private String build()
150    {
151        _buffer.setLength(_baseNameLength);
152
153        if (_state == LC || _state == LCV || _state == L)
154        {
155            _buffer.append('_');
156            _buffer.append(_language);
157        }
158
159        // For LV, we want two underscores between language
160        // and variant.
161
162        if (_state == LC || _state == LCV || _state == LV)
163        {
164            _buffer.append('_');
165
166            if (_state != LV)
167                _buffer.append(_country);
168        }
169
170        if (_state == LV || _state == LCV)
171        {
172            _buffer.append('_');
173            _buffer.append(_variant);
174        }
175
176        if (_suffix != null)
177            _buffer.append(_suffix);
178
179        return _buffer.toString();
180    }
181
182    public Locale getCurrentLocale()
183    {
184        switch (_prevState)
185        {
186            case LCV :
187
188                return new Locale(_language, _country, _variant);
189
190            case LC :
191
192                return new Locale(_language, _country, "");
193
194            case LV :
195
196                return new Locale(_language, "", _variant);
197
198            case L :
199
200                return new Locale(_language, "", "");
201
202            default :
203                return null;
204        }
205    }
206}