ba5fde5df13a9d86381b965aa1487d702ff61be8
[jvcard.git] / src / be / nikiroo / jvcard / Data.java
1 package be.nikiroo.jvcard;
2
3 import java.security.InvalidParameterException;
4 import java.util.LinkedList;
5 import java.util.List;
6
7 /**
8 * A data is a piece of information present in a {@link Contact}. It is
9 * basically a key/value pair with optional types and an optional group name.
10 *
11 * @author niki
12 *
13 */
14 public class Data extends BaseClass<TypeInfo> {
15 public enum DataPart {
16 FN_FAMILY, FN_GIVEN, FN_ADDITIONAL, // Name
17 FN_PRE, FN_POST, // Pre/Post
18 BDAY_YYYY, BDAY_MM, BDAY_DD, // BDay
19 ADR_PBOX, ADR_EXTENDED, ADR_STREET, ADR_CITY, ADR_REGION, ADR_POSTAL_CODE, ADR_COUNTRY
20 // Address
21 }
22
23 private String name;
24 private String value;
25 private String group;
26 private int b64; // -1 = no, 0 = still not ordered, the rest is order
27
28 /**
29 * Create a new {@link Data} with the given values.
30 *
31 * @param types
32 * the types of this {@link Data}
33 * @param name
34 * its name (<b>MUST NOT</b> be NULL)
35 * @param value
36 * its value (<b>MUST NOT</b> be NULL)
37 * @param group
38 * its group if any (or NULL if none)
39 */
40 public Data(List<TypeInfo> types, String name, String value, String group) {
41 super(types);
42
43 this.name = name.toUpperCase();
44 this.value = value.toString(); // crash NOW if null
45 this.group = group;
46
47 b64 = -1;
48 for (TypeInfo type : this) {
49 if (type.getName().equals("ENCODING")
50 && type.getValue().equals("b")) {
51 b64 = 0;
52 break;
53 }
54 }
55 }
56
57 /**
58 * Return the name of this {@link Data}
59 *
60 * @return the name
61 */
62 public String getName() {
63 return name;
64 }
65
66 /**
67 * Return the value of this {@link Data}
68 *
69 * @return the value
70 */
71 public String getValue() {
72 return unescape(value);
73 }
74
75 /**
76 * Change the value of this {@link Data}
77 *
78 * @param value
79 * the new value
80 */
81 public void setValue(String value) {
82 setRawValue(escape(value));
83 }
84
85 /**
86 * Return the raw value of this {@link Data}
87 *
88 * @return the raw value
89 */
90 public String getRawValue() {
91 return value;
92 }
93
94 /**
95 * Change the raw value of this {@link Data}
96 *
97 * @param value
98 * the new raw value
99 */
100 public void setRawValue(String value) {
101 if ((value == null && this.value != null)
102 || (value != null && !value.equals(this.value))) {
103 this.value = value;
104 setDirty();
105 }
106 }
107
108 /**
109 * Return the {@link List} of comma-listed values from this {@link Data}.
110 *
111 * @return the {@link List} of values
112 */
113 public List<String> getValues() {
114 return getList(',');
115 }
116
117 /**
118 * Set the {@link List} of comma-listed values from this {@link Data}.
119 *
120 * @param values
121 * the {@link List} of values
122 */
123 public void setValues(List<String> values) {
124 setList(values, ',');
125 }
126
127 /**
128 * Return the {@link List} of semi-column-listed fields from this
129 * {@link Data}.
130 *
131 * @return the {@link List} of values
132 */
133 public List<String> getFields() {
134 return getList(';');
135 }
136
137 /**
138 * Set the {@link List} of comma-listed values from this {@link Data}.
139 *
140 * @param values
141 * the {@link List} of values
142 */
143 public void setFields(List<String> values) {
144 setList(values, ';');
145 }
146
147 /**
148 * Return the group of this {@link Data}
149 *
150 * @return the group
151 */
152 public String getGroup() {
153 return group;
154 }
155
156 /**
157 * Change the group of this {@link Data}
158 *
159 * @param group
160 * the new group
161 */
162 public void setGroup(String group) {
163 if ((group == null && this.group != null)
164 || (group != null && !group.equals(this.group))) {
165 this.group = group;
166 setDirty();
167 }
168 }
169
170 /**
171 * Return the bkey number of this {@link Data} or -1 if it is not binary.
172 *
173 * @return the bkey or -1
174 */
175 public int getB64Key() {
176 return b64;
177 }
178
179 /**
180 * Check if this {@link Data} is binary
181 *
182 * @return TRUE if it is
183 */
184 public boolean isBinary() {
185 return b64 >= 0;
186 }
187
188 /**
189 * Check if this {@link Data} has the "preferred" flag.
190 *
191 * @return TRUE if it has
192 */
193 public boolean isPreferred() {
194 for (TypeInfo type : this) {
195 if (type.getName().equals("TYPE") && type.getValue().equals("pref")) {
196 return true;
197 }
198 }
199
200 return false;
201 }
202
203 /**
204 * Change the bkey of this {@link Data}
205 *
206 * @param i
207 * the new bkey
208 *
209 * @throw InvalidParameterException if the {@link Data} is not binary or if
210 * it is but you try to set a negative bkey
211 */
212 void resetB64Key(int i) {
213 if (!isBinary())
214 throw new InvalidParameterException(
215 "Cannot add a BKey on a non-binary object");
216 if (i < 0)
217 throw new InvalidParameterException(
218 "Cannot remove the BKey on a binary object");
219
220 b64 = i;
221 }
222
223 /**
224 * Return the {@link List} of sep-listed values from this {@link String}
225 * data.
226 *
227 * @param value
228 * the data
229 *
230 * @param the
231 * separator
232 *
233 * @return the {@link List} of values
234 */
235 private List<String> getList(char sep) {
236 List<String> rep = new LinkedList<String>();
237
238 if (value != null && value.length() > 0) {
239 int last = 0;
240 for (int i = 0; i < value.length(); i++) {
241 if (value.charAt(i) == sep
242 && (i == 0 || value.charAt(i - 1) != '\\')) {
243 rep.add(value.substring(last, i));
244 last = i + 1;
245 }
246 }
247
248 if (last < value.length())
249 rep.add(value.substring(last));
250 }
251
252 return rep;
253 }
254
255 /**
256 * Create the {@link String}-encoded {@link List} of sep-listed values from
257 * the given values.
258 *
259 * @param values
260 * the {@link List} of values
261 *
262 * @param sep
263 * the separator
264 *
265 * @return the {@link String}
266 */
267 private void setList(List<String> values, char sep) {
268 StringBuilder builder = new StringBuilder();
269 boolean first = true;
270 for (String value : values) {
271 if (!first)
272 builder.append(sep);
273
274 builder.append(escape(value));
275
276 first = false;
277 }
278
279 value = builder.toString();
280 }
281
282 @Override
283 public String getId() {
284 return "" + name;
285 }
286
287 @Override
288 public String getState() {
289 return ("" + name + value + group).replace(' ', '_');
290 }
291 }