blob: 76af32789d1338cbc66a4b6ff652524b75cba972 [file] [log] [blame]
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.i18n.addressinput;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* Configuration Options that can be used by Address Display components for things like show/hide
* fields or make them readonly. By default, all the fields are visible and editable.
*
* <p>Also, provides the ability to add additional required fields, for e.g. {@link
* AddressField#RECIPIENT}.
*/
public class FormOptions {
private final String baseId;
private final EnumSet<AddressField> hiddenFields;
private final EnumSet<AddressField> readonlyFields;
private final EnumSet<AddressField> requiredFields;
private final EnumMap<AddressField, String> customLabels =
new EnumMap<AddressField, String>(AddressField.class);
private final Map<String, AddressField[]> overrideFieldOrder =
new HashMap<String, AddressField[]>();
private final EnumMap<AddressField, Integer> maxLengths =
new EnumMap<AddressField, Integer>(AddressField.class);
private final String serverUrl;
private FormOptions(Builder builder) {
// copy values from builder
this.baseId = builder.baseId;
this.hiddenFields = EnumSet.copyOf(builder.hiddenFields);
this.readonlyFields = EnumSet.copyOf(builder.readonlyFields);
this.requiredFields = EnumSet.copyOf(builder.requiredFields);
this.customLabels.putAll(builder.customLabels);
this.overrideFieldOrder.putAll(builder.overrideFieldOrder);
this.maxLengths.putAll(builder.maxLengths);
this.serverUrl = builder.serverUrl;
}
/**
* Gets base ID of the address form. Default is "addressform".
*/
public String getBaseId() {
return baseId;
}
public boolean isHidden(AddressField field) {
return hiddenFields.contains(field);
}
public boolean isReadonly(AddressField field) {
return readonlyFields.contains(field);
}
public boolean isRequired(AddressField field) {
return requiredFields.contains(field);
}
public EnumSet<AddressField> getRequiredFields() {
return requiredFields;
}
/**
* Gets the customized label for the {@code field}, or returns null if none.
*/
public String getCustomLabel(AddressField field) {
return customLabels.get(field);
}
/**
* Gets the URL of the Address Data Server.
*/
public String getUrl() {
return serverUrl;
}
/**
* Gets the overridden field orders with their corresponding region code. Returns null if field
* orders for {@code regionCode} is not specified.
*/
public AddressField[] getCustomFieldOrder(String regionCode) {
if (regionCode == null) {
throw new RuntimeException("regionCode cannot be null.");
}
return overrideFieldOrder.get(regionCode);
}
/**
* Gets the customized max length for the {@code field}, or null if none.
*/
public Integer getCustomMaxLength(AddressField field) {
return maxLengths.get(field);
}
/**
* Class to build the form, specifying the attributes for each field.
*/
public static class Builder {
private String baseId = "addressform";
private final EnumSet<AddressField> requiredFields =
EnumSet.noneOf(AddressField.class);
private final EnumSet<AddressField> hiddenFields =
EnumSet.noneOf(AddressField.class);
private final EnumSet<AddressField> readonlyFields =
EnumSet.noneOf(AddressField.class);
private final EnumMap<AddressField, String> customLabels =
new EnumMap<AddressField, String>(AddressField.class);
private final Map<String, AddressField[]> overrideFieldOrder =
new HashMap<String, AddressField[]>();
private final EnumMap<AddressField, Integer> maxLengths =
new EnumMap<AddressField, Integer>(AddressField.class);
// TODO: When CacheData is ported, need to update this.
private String serverUrl = "";
// private String serverUrl = CacheData.INSTANCE.getUrl();
/**
* Sets the base ID of the address form.
*/
public Builder baseId(String baseId) {
if (baseId == null) {
throw new RuntimeException("baseId cannot be null.");
}
this.baseId = baseId;
return this;
}
public Builder hide(AddressField field) {
if (field == null) {
throw new RuntimeException("AddressField field cannot be null.");
}
hiddenFields.add(field);
return this;
}
/**
* Make a field read-only.
*/
public Builder readonly(AddressField field) {
if (field == null) {
throw new RuntimeException("AddressField field cannot be null.");
}
readonlyFields.add(field);
return this;
}
/**
* Make a field required.
*/
public Builder required(AddressField field) {
if (field == null) {
throw new RuntimeException("AddressField field cannot be null.");
}
requiredFields.add(field);
return this;
}
/**
* Customizes label for an {@code AddressField}.
*/
public Builder customizeLabel(AddressField field, String label) {
if (field == null) {
throw new RuntimeException("AddressField field cannot be null.");
}
if (label == null) {
throw new RuntimeException("Label cannot be null.");
}
customLabels.put(field, label);
return this;
}
/**
* Sets the field order for a region code. The order you set here will override the
* predefined one. For example, you can set field order for US to be first {@code
* AddressField#ORGANIZATION} then {@code AddressField#RECIPIENT}. Repeated address fields
* in {@code fields} are not allowed. Size of {@code fields} has to be larger than one.
* Input {@code fields} can be partial or even contain field not needed in the specified
* {@code regionCode}. For example, German addresses contain the following fields
* (in order):<br/>
{@link AddressField#RECIPIENT}, {@link AddressField#ORGANIZATION}, {@link
* AddressField#STREET_ADDRESS}, {@link AddressField#POSTAL_CODE}, {@link
* AddressField#LOCALITY}. <br/>
*
* <p>With the following call: <br/>
*
* customizeFieldOrder("DE", AddressField.ORGANIZATION, AddressField.RECIPIENT,
* AddressField.ADMIN_AREA);
*
* <p>Field order for Germany will become: <br/> {@link AddressField#ORGANIZATION}, {@link
* AddressField#RECIPIENT}, {@link AddressField#STREET_ADDRESS}, {@link
* AddressField#POSTAL_CODE}, {@link AddressField#LOCALITY}. </p>
*
* <p>Notice that:<br/> <ol> <li>{@link AddressField#ORGANIZATION} comes before {@link
* AddressField#RECIPIENT} after reordering.</li>
* <li>Fields not specified stays the same.</li>
* <li>{@link AddressField#ADMIN_AREA} is specified but since it is not in German address
* format, it is simpled neglected.</li> </ol>
*
* @param fields the overridden field order.
*/
public Builder customizeFieldOrder(String regionCode,
AddressField... fields) {
if (regionCode == null) {
throw new RuntimeException("regionCode cannot be null.");
}
if (fields == null) {
throw new RuntimeException("Fields cannot be null.");
}
if (fields.length <= 1) {
throw new RuntimeException("There must be more than one field.");
}
HashSet<AddressField> checkList = new HashSet<AddressField>();
AddressField[] f = new AddressField[fields.length];
int i = 0;
for (AddressField field : fields) {
// Can't contain repeated address fields.
if (checkList.contains(field)) {
throw new RuntimeException("Address fields cannot be repeated.");
}
checkList.add(field);
f[i] = field;
i++;
}
overrideFieldOrder.put(regionCode, f);
return this;
}
/**
* Sets the URL of address data server. {@code url} cannot be null. This url will override
* the default address server url.
*/
public Builder setUrl(String url) {
if (url == null) {
throw new RuntimeException("Can't set address server URL to null.");
}
serverUrl = url;
return this;
}
/**
* Customizes max length for a {@code AddressField}.
*/
public Builder customizeMaxLength(AddressField field, int maxLength) {
if (field == null) {
throw new RuntimeException("AddressField field cannot be null.");
}
maxLengths.put(field, maxLength);
return this;
}
public FormOptions build() {
return new FormOptions(this);
}
}
}