1/* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.i18n.addressinput; 18 19import java.util.EnumMap; 20import java.util.EnumSet; 21import java.util.HashMap; 22import java.util.HashSet; 23import java.util.Map; 24 25/** 26 * Configuration Options that can be used by Address Display components for things like show/hide 27 * fields or make them readonly. By default, all the fields are visible and editable. 28 * 29 * <p>Also, provides the ability to add additional required fields, for e.g. {@link 30 * AddressField#RECIPIENT}. 31 */ 32public class FormOptions { 33 34 private final String mBaseId; 35 36 private final EnumSet<AddressField> mHiddenFields; 37 38 private final EnumSet<AddressField> mReadonlyFields; 39 40 private final EnumSet<AddressField> mRequiredFields; 41 42 private final EnumMap<AddressField, String> mCustomLabels = 43 new EnumMap<AddressField, String>(AddressField.class); 44 45 private final Map<String, AddressField[]> mOverrideFieldOrder = 46 new HashMap<String, AddressField[]>(); 47 48 private final EnumMap<AddressField, Integer> mMaxLengths = 49 new EnumMap<AddressField, Integer>(AddressField.class); 50 51 private final String mServerUrl; 52 53 private FormOptions(Builder builder) { 54 // copy values from builder 55 mBaseId = builder.mBaseId; 56 mHiddenFields = EnumSet.copyOf(builder.mHiddenFields); 57 mReadonlyFields = EnumSet.copyOf(builder.mReadonlyFields); 58 mRequiredFields = EnumSet.copyOf(builder.mRequiredFields); 59 mCustomLabels.putAll(builder.mCustomLabels); 60 mOverrideFieldOrder.putAll(builder.mOverrideFieldOrder); 61 mMaxLengths.putAll(builder.mMaxLengths); 62 mServerUrl = builder.mServerUrl; 63 } 64 65 /** 66 * Gets base ID of the address form. Default is "addressform". 67 */ 68 String getBaseId() { 69 return mBaseId; 70 } 71 72 boolean isHidden(AddressField field) { 73 return mHiddenFields.contains(field); 74 } 75 76 boolean isReadonly(AddressField field) { 77 return mReadonlyFields.contains(field); 78 } 79 80 boolean isRequired(AddressField field) { 81 return mRequiredFields.contains(field); 82 } 83 84 EnumSet<AddressField> getRequiredFields() { 85 return mRequiredFields; 86 } 87 88 /** 89 * Gets the customized label for the {@code field}, or returns null if none. 90 */ 91 String getCustomLabel(AddressField field) { 92 return mCustomLabels.get(field); 93 } 94 95 /** 96 * Gets the URL of the Address Data Server. 97 */ 98 String getUrl() { 99 return mServerUrl; 100 } 101 102 /** 103 * Gets the overridden field orders with their corresponding region code. Returns null if field 104 * orders for {@code regionCode} is not specified. 105 */ 106 AddressField[] getCustomFieldOrder(String regionCode) { 107 if (regionCode == null) { 108 throw new RuntimeException("regionCode cannot be null."); 109 } 110 return mOverrideFieldOrder.get(regionCode); 111 } 112 113 /** 114 * Gets the customized max length for the {@code field}, or null if none. 115 */ 116 Integer getCustomMaxLength(AddressField field) { 117 return mMaxLengths.get(field); 118 } 119 120 /** 121 * Class to build the form, specifying the attributes for each field. 122 */ 123 public static class Builder { 124 125 private String mBaseId = "addressform"; 126 127 private final EnumSet<AddressField> mRequiredFields = 128 EnumSet.noneOf(AddressField.class); 129 130 private final EnumSet<AddressField> mHiddenFields = 131 EnumSet.noneOf(AddressField.class); 132 133 private final EnumSet<AddressField> mReadonlyFields = 134 EnumSet.noneOf(AddressField.class); 135 136 private final EnumMap<AddressField, String> mCustomLabels = 137 new EnumMap<AddressField, String>(AddressField.class); 138 139 private final Map<String, AddressField[]> mOverrideFieldOrder = 140 new HashMap<String, AddressField[]>(); 141 142 private final EnumMap<AddressField, Integer> mMaxLengths = 143 new EnumMap<AddressField, Integer>(AddressField.class); 144 145 /** 146 * Uses the default server URL from CacheData. 147 */ 148 private String mServerUrl = new CacheData().getUrl(); 149 150 /** 151 * Sets the base ID of the address form. 152 */ 153 public Builder baseId(String baseId) { 154 if (baseId == null) { 155 throw new RuntimeException("baseId cannot be null."); 156 } 157 mBaseId = baseId; 158 return this; 159 } 160 161 public Builder hide(AddressField field) { 162 if (field == null) { 163 throw new RuntimeException("AddressField field cannot be null."); 164 } 165 mHiddenFields.add(field); 166 return this; 167 } 168 169 /** 170 * Make a field read-only. 171 */ 172 public Builder readonly(AddressField field) { 173 if (field == null) { 174 throw new RuntimeException("AddressField field cannot be null."); 175 } 176 mReadonlyFields.add(field); 177 return this; 178 } 179 180 /** 181 * Make a field required. 182 */ 183 public Builder required(AddressField field) { 184 if (field == null) { 185 throw new RuntimeException("AddressField field cannot be null."); 186 } 187 mRequiredFields.add(field); 188 return this; 189 } 190 191 /** 192 * Customizes label for an {@code AddressField}. 193 */ 194 public Builder customizeLabel(AddressField field, String label) { 195 if (field == null) { 196 throw new RuntimeException("AddressField field cannot be null."); 197 } 198 if (label == null) { 199 throw new RuntimeException("Label cannot be null."); 200 } 201 mCustomLabels.put(field, label); 202 return this; 203 } 204 205 /** 206 * Sets the field order for a region code. The order you set here will override the 207 * predefined one. For example, you can set field order for US to be first {@code 208 * AddressField#ORGANIZATION} then {@code AddressField#RECIPIENT}. Repeated address fields 209 * in {@code fields} are not allowed. Size of {@code fields} has to be larger than one. 210 * Input {@code fields} can be partial or even contain field not needed in the specified 211 * {@code regionCode}. For example, German addresses contain the following fields 212 * (in order):<br/> 213 {@link AddressField#RECIPIENT}, {@link AddressField#ORGANIZATION}, {@link 214 * AddressField#STREET_ADDRESS}, {@link AddressField#POSTAL_CODE}, {@link 215 * AddressField#LOCALITY}. <br/> 216 * 217 * <p>With the following call: <br/> 218 * 219 * customizeFieldOrder("DE", AddressField.ORGANIZATION, AddressField.RECIPIENT, 220 * AddressField.ADMIN_AREA); 221 * 222 * <p>Field order for Germany will become: <br/> {@link AddressField#ORGANIZATION}, {@link 223 * AddressField#RECIPIENT}, {@link AddressField#STREET_ADDRESS}, {@link 224 * AddressField#POSTAL_CODE}, {@link AddressField#LOCALITY}. </p> 225 * 226 * <p>Notice that:<br/> <ol> <li>{@link AddressField#ORGANIZATION} comes before {@link 227 * AddressField#RECIPIENT} after reordering.</li> 228 * <li>Fields not specified stays the same.</li> 229 * <li>{@link AddressField#ADMIN_AREA} is specified but since it is not in German address 230 * format, it is simpled neglected.</li> </ol> 231 * 232 * @param fields the overridden field order. 233 */ 234 public Builder customizeFieldOrder(String regionCode, AddressField... fields) { 235 if (regionCode == null) { 236 throw new RuntimeException("regionCode cannot be null."); 237 } 238 if (fields == null) { 239 throw new RuntimeException("Fields cannot be null."); 240 } 241 if (fields.length <= 1) { 242 throw new RuntimeException("There must be more than one field."); 243 } 244 HashSet<AddressField> checkList = new HashSet<AddressField>(); 245 AddressField[] f = new AddressField[fields.length]; 246 int i = 0; 247 for (AddressField field : fields) { 248 // Can't contain repeated address fields. 249 if (checkList.contains(field)) { 250 throw new RuntimeException("Address fields cannot be repeated."); 251 } 252 checkList.add(field); 253 f[i] = field; 254 i++; 255 } 256 mOverrideFieldOrder.put(regionCode, f); 257 return this; 258 } 259 260 /** 261 * Sets the URL of address data server. {@code url} cannot be null. This url will override 262 * the default address server url. 263 */ 264 public Builder setUrl(String url) { 265 if (url == null) { 266 throw new RuntimeException("Can't set address server URL to null."); 267 } 268 mServerUrl = url; 269 return this; 270 } 271 272 /** 273 * Customizes max length for a {@code AddressField}. 274 */ 275 public Builder customizeMaxLength(AddressField field, int maxLength) { 276 if (field == null) { 277 throw new RuntimeException("AddressField field cannot be null."); 278 } 279 mMaxLengths.put(field, maxLength); 280 return this; 281 } 282 283 public FormOptions build() { 284 return new FormOptions(this); 285 } 286 } 287} 288