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 015 package org.apache.hivemind.util; 016 017 import java.util.Locale; 018 import java.util.NoSuchElementException; 019 020 import 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 030 public 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 }