4c4e5d174e419bb47c9037e2f4477a08438a3b73
[jvcard.git] / src / be / nikiroo / jvcard / Card.java
1 package be.nikiroo.jvcard;
2
3 import java.io.BufferedReader;
4 import java.io.BufferedWriter;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileWriter;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.security.InvalidParameterException;
11 import java.util.Arrays;
12 import java.util.LinkedList;
13 import java.util.List;
14
15 import be.nikiroo.jvcard.parsers.Format;
16 import be.nikiroo.jvcard.parsers.Parser;
17
18 /**
19 * A card is a contact information card. It contains data about one or more
20 * contacts.
21 *
22 * @author niki
23 *
24 */
25 public class Card {
26 private List<Contact> contacts;
27 private File file;
28 private boolean dirty;
29 private String name;
30 private Format format;
31
32 /**
33 * Create a new {@link Card} from the given {@link File} and {@link Format}.
34 *
35 * @param file
36 * the file containing the {@link Card} data, must not be NULL
37 * @param format
38 * the {@link Format} to use to parse it
39 *
40 * @throws IOException
41 * in case of IO error
42 * @throws NullPointerException
43 * if file is NULL
44 * @throws InvalidParameterException
45 * if format is NULL
46 */
47 public Card(File file, Format format) throws IOException {
48 this.file = file;
49 this.format = format;
50 this.name = file.getName();
51
52 BufferedReader buffer = new BufferedReader(new InputStreamReader(
53 new FileInputStream(file), "UTF-8"));
54 List<String> lines = new LinkedList<String>();
55 for (String line = buffer.readLine(); line != null; line = buffer
56 .readLine()) {
57 lines.add(line);
58 }
59 buffer.close();
60
61 load(lines, format);
62 dirty = false; // initial load, so no change yet, so no need to call
63 // setPristine()
64 }
65
66 /**
67 * Return the number of {@link Contact} present in this {@link Card}.
68 *
69 * @return the number of {@link Contact}s
70 */
71 public int size() {
72 return contacts.size();
73 }
74
75 /**
76 * Return the {@link Contact} at index <i>index</i>.
77 *
78 * @param index
79 * the index of the {@link Contact} to find
80 *
81 * @return the {@link Contact}
82 *
83 * @throws IndexOutOfBoundsException
84 * if the index is < 0 or >= {@link Card#size()}
85 */
86 public Contact get(int index) {
87 return contacts.get(index);
88 }
89
90 /**
91 * Save the {@link Card} to the given {@link File} with the given
92 * {@link Format}.
93 *
94 * @param file
95 * the {@link File} to save to
96 * @param format
97 * the {@link Format} to use
98 *
99 * @return TRUE if it was saved
100 *
101 * @throws IOException
102 * in case of IO errors
103 */
104 public boolean saveAs(File file, Format format) throws IOException {
105 if (file == null)
106 return false;
107
108 BufferedWriter writer = new BufferedWriter(new FileWriter(file));
109 writer.append(toString(format));
110 writer.close();
111
112 if (file.equals(this.file)) {
113 setPristine();
114 }
115
116 return true;
117 }
118
119 /**
120 * Save the {@link Card} to the original {@link File} it was open from.
121 *
122 * @return TRUE if it was saved
123 *
124 * @throws IOException
125 * in case of IO errors
126 */
127 public boolean save() throws IOException {
128 return saveAs(file, format);
129 }
130
131 /**
132 * Return a {@link String} representation of this {@link Card} in the given
133 * {@link Format}.
134 *
135 * @param format
136 * the {@link Format} to use
137 *
138 * @return the {@link String}
139 */
140 public String toString(Format format) {
141 return Parser.toString(this, format);
142 }
143
144 /**
145 * Check if this {@link Card} has unsaved changes.
146 *
147 * @return TRUE if it has
148 */
149 public boolean isDirty() {
150 return dirty;
151 }
152
153 /**
154 * Return the name of this card (the name of the {@link File} which it was
155 * opened from).
156 *
157 * @return the name
158 */
159 public String getName() {
160 return name;
161 }
162
163 @Override
164 public String toString() {
165 return toString(Format.VCard21);
166 }
167
168 /**
169 * Load the given data from the given {@link Format} in this {@link Card}.
170 *
171 * @param serializedContent
172 * the data
173 * @param format
174 * the {@link Format}
175 */
176 protected void load(String serializedContent, Format format) {
177 // note: fixed size array
178 List<String> lines = Arrays.asList(serializedContent.split("\n"));
179 load(lines, format);
180 }
181
182 /**
183 * Load the given data from the given {@link Format} in this {@link Card}.
184 *
185 * @param lines
186 * the data
187 * @param format
188 * the {@link Format}
189 */
190 protected void load(List<String> lines, Format format) {
191 this.contacts = Parser.parse(lines, format);
192 setDirty();
193
194 for (Contact contact : contacts) {
195 contact.setParent(this);
196 }
197 }
198
199 /**
200 * Return the full list of {@link Contact}s. Please use responsibly (this is
201 * the original list).
202 *
203 * @return the list of {@link Contact}s
204 */
205 List<Contact> getContactsList() {
206 return contacts;
207 }
208
209 /**
210 * Notify that this element has unsaved changes.
211 */
212 void setDirty() {
213 dirty = true;
214 }
215
216 /**
217 * Notify this element <i>and all its descendants</i> that it is in pristine
218 * state (as opposed to dirty).
219 */
220 void setPristine() {
221 dirty = false;
222 for (Contact contact : contacts) {
223 contact.setPristine();
224 }
225 }
226 }