aboutsummaryrefslogtreecommitdiff
path: root/java/src/com/android/i18n/addressinput/FormOptions.java
blob: 07bc38ed0225b54e92cd9dc5cced4b35dead13a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
 * 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 mBaseId;

    private final EnumSet<AddressField> mHiddenFields;

    private final EnumSet<AddressField> mReadonlyFields;

    private final EnumSet<AddressField> mRequiredFields;

    private final EnumMap<AddressField, String> mCustomLabels =
            new EnumMap<AddressField, String>(AddressField.class);

    private final Map<String, AddressField[]> mOverrideFieldOrder =
            new HashMap<String, AddressField[]>();

    private final EnumMap<AddressField, Integer> mMaxLengths =
            new EnumMap<AddressField, Integer>(AddressField.class);

    private final String mServerUrl;

    private FormOptions(Builder builder) {
        // copy values from builder
        mBaseId = builder.mBaseId;
        mHiddenFields = EnumSet.copyOf(builder.mHiddenFields);
        mReadonlyFields = EnumSet.copyOf(builder.mReadonlyFields);
        mRequiredFields = EnumSet.copyOf(builder.mRequiredFields);
        mCustomLabels.putAll(builder.mCustomLabels);
        mOverrideFieldOrder.putAll(builder.mOverrideFieldOrder);
        mMaxLengths.putAll(builder.mMaxLengths);
        mServerUrl = builder.mServerUrl;
    }

    /**
     * Gets base ID of the address form. Default is "addressform".
     */
    String getBaseId() {
        return mBaseId;
    }

    boolean isHidden(AddressField field) {
        return mHiddenFields.contains(field);
    }

    boolean isReadonly(AddressField field) {
        return mReadonlyFields.contains(field);
    }

    boolean isRequired(AddressField field) {
        return mRequiredFields.contains(field);
    }

    EnumSet<AddressField> getRequiredFields() {
        return mRequiredFields;
    }

    /**
     * Gets the customized label for the {@code field}, or returns null if none.
     */
    String getCustomLabel(AddressField field) {
        return mCustomLabels.get(field);
    }

    /**
     * Gets the URL of the Address Data Server.
     */
    String getUrl() {
        return mServerUrl;
    }

    /**
     * Gets the overridden field orders with their corresponding region code. Returns null if field
     * orders for {@code regionCode} is not specified.
     */
    AddressField[] getCustomFieldOrder(String regionCode) {
        if (regionCode == null) {
            throw new RuntimeException("regionCode cannot be null.");
        }
        return mOverrideFieldOrder.get(regionCode);
    }

    /**
     * Gets the customized max length for the {@code field}, or null if none.
     */
    Integer getCustomMaxLength(AddressField field) {
        return mMaxLengths.get(field);
    }

    /**
     * Class to build the form, specifying the attributes for each field.
     */
    public static class Builder {

        private String mBaseId = "addressform";

        private final EnumSet<AddressField> mRequiredFields =
                EnumSet.noneOf(AddressField.class);

        private final EnumSet<AddressField> mHiddenFields =
                EnumSet.noneOf(AddressField.class);

        private final EnumSet<AddressField> mReadonlyFields =
                EnumSet.noneOf(AddressField.class);

        private final EnumMap<AddressField, String> mCustomLabels =
                new EnumMap<AddressField, String>(AddressField.class);

        private final Map<String, AddressField[]> mOverrideFieldOrder =
                new HashMap<String, AddressField[]>();

        private final EnumMap<AddressField, Integer> mMaxLengths =
                new EnumMap<AddressField, Integer>(AddressField.class);

        /**
         * Uses the default server URL from CacheData.
         */
        private String mServerUrl = new CacheData().getUrl();

        /**
         * Sets the base ID of the address form.
         */
        public Builder baseId(String baseId) {
            if (baseId == null) {
                throw new RuntimeException("baseId cannot be null.");
            }
            mBaseId = baseId;
            return this;
        }

        public Builder hide(AddressField field) {
            if (field == null) {
                throw new RuntimeException("AddressField field cannot be null.");
            }
            mHiddenFields.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.");
            }
            mReadonlyFields.add(field);
            return this;
        }

        /**
         * Make a field required.
         */
        public Builder required(AddressField field) {
            if (field == null) {
                throw new RuntimeException("AddressField field cannot be null.");
            }
            mRequiredFields.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.");
            }
            mCustomLabels.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++;
            }
            mOverrideFieldOrder.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.");
            }
            mServerUrl = 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.");
            }
            mMaxLengths.put(field, maxLength);
            return this;
        }

        public FormOptions build() {
            return new FormOptions(this);
        }
    }
}