Commit | Line | Data |
---|---|---|
a3b510ab NR |
1 | package be.nikiroo.jvcard; |
2 | ||
3 | import java.io.BufferedReader; | |
4 | import java.io.BufferedWriter; | |
5 | import java.io.File; | |
296a0b75 | 6 | import java.io.FileInputStream; |
a3b510ab NR |
7 | import java.io.FileWriter; |
8 | import java.io.IOException; | |
296a0b75 | 9 | import java.io.InputStreamReader; |
78e4af97 | 10 | import java.security.InvalidParameterException; |
a3b510ab NR |
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; | |
0b0b2b0f | 29 | private String name; |
bcb54330 | 30 | private Format format; |
a3b510ab | 31 | |
78e4af97 NR |
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 | */ | |
a3b510ab NR |
47 | public Card(File file, Format format) throws IOException { |
48 | this.file = file; | |
bcb54330 | 49 | this.format = format; |
78e4af97 | 50 | this.name = file.getName(); |
0b0b2b0f | 51 | |
296a0b75 NR |
52 | BufferedReader buffer = new BufferedReader(new InputStreamReader( |
53 | new FileInputStream(file), "UTF-8")); | |
a3b510ab NR |
54 | List<String> lines = new LinkedList<String>(); |
55 | for (String line = buffer.readLine(); line != null; line = buffer | |
56 | .readLine()) { | |
57 | lines.add(line); | |
58 | } | |
bcb54330 | 59 | buffer.close(); |
a3b510ab NR |
60 | |
61 | load(lines, format); | |
bcb54330 NR |
62 | dirty = false; // initial load, so no change yet, so no need to call |
63 | // setPristine() | |
a3b510ab NR |
64 | } |
65 | ||
bcb54330 | 66 | /** |
78e4af97 | 67 | * Return the number of {@link Contact} present in this {@link Card}. |
bcb54330 | 68 | * |
78e4af97 | 69 | * @return the number of {@link Contact}s |
bcb54330 | 70 | */ |
78e4af97 NR |
71 | public int size() { |
72 | return contacts.size(); | |
a3b510ab NR |
73 | } |
74 | ||
bcb54330 | 75 | /** |
78e4af97 | 76 | * Return the {@link Contact} at index <i>index</i>. |
bcb54330 | 77 | * |
78e4af97 NR |
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()} | |
bcb54330 | 85 | */ |
bcb54330 NR |
86 | public Contact get(int index) { |
87 | return contacts.get(index); | |
88 | } | |
176a8327 NR |
89 | |
90 | /** | |
91 | * Add a new {@link Contact} in this {@link Card}. | |
92 | * | |
93 | * @param contact | |
94 | * the new contact | |
95 | */ | |
96 | public void add(Contact contact) { | |
97 | contact.setParent(this); | |
98 | contact.setDirty(); | |
99 | contacts.add(contact); | |
100 | } | |
101 | ||
102 | /** | |
103 | * Remove the given {@link Contact} from its this {@link Card} if it is in. | |
104 | * | |
105 | * @return TRUE in case of success | |
106 | */ | |
107 | public boolean remove(Contact contact) { | |
108 | if (contacts.remove(contact)) { | |
109 | setDirty(); | |
110 | } | |
111 | ||
112 | return false; | |
113 | } | |
bcb54330 | 114 | |
78e4af97 NR |
115 | /** |
116 | * Save the {@link Card} to the given {@link File} with the given | |
117 | * {@link Format}. | |
118 | * | |
119 | * @param file | |
120 | * the {@link File} to save to | |
121 | * @param format | |
122 | * the {@link Format} to use | |
123 | * | |
124 | * @return TRUE if it was saved | |
125 | * | |
126 | * @throws IOException | |
127 | * in case of IO errors | |
128 | */ | |
a3b510ab NR |
129 | public boolean saveAs(File file, Format format) throws IOException { |
130 | if (file == null) | |
131 | return false; | |
132 | ||
133 | BufferedWriter writer = new BufferedWriter(new FileWriter(file)); | |
134 | writer.append(toString(format)); | |
135 | writer.close(); | |
136 | ||
137 | if (file.equals(this.file)) { | |
bcb54330 | 138 | setPristine(); |
a3b510ab NR |
139 | } |
140 | ||
141 | return true; | |
142 | } | |
143 | ||
78e4af97 NR |
144 | /** |
145 | * Save the {@link Card} to the original {@link File} it was open from. | |
146 | * | |
147 | * @return TRUE if it was saved | |
148 | * | |
149 | * @throws IOException | |
150 | * in case of IO errors | |
151 | */ | |
bcb54330 | 152 | public boolean save() throws IOException { |
a3b510ab NR |
153 | return saveAs(file, format); |
154 | } | |
155 | ||
78e4af97 NR |
156 | /** |
157 | * Return a {@link String} representation of this {@link Card} in the given | |
158 | * {@link Format}. | |
159 | * | |
160 | * @param format | |
161 | * the {@link Format} to use | |
162 | * | |
163 | * @return the {@link String} | |
164 | */ | |
a3b510ab NR |
165 | public String toString(Format format) { |
166 | return Parser.toString(this, format); | |
167 | } | |
168 | ||
78e4af97 NR |
169 | /** |
170 | * Check if this {@link Card} has unsaved changes. | |
171 | * | |
172 | * @return TRUE if it has | |
173 | */ | |
174 | public boolean isDirty() { | |
175 | return dirty; | |
176 | } | |
177 | ||
178 | /** | |
179 | * Return the name of this card (the name of the {@link File} which it was | |
180 | * opened from). | |
181 | * | |
182 | * @return the name | |
183 | */ | |
184 | public String getName() { | |
185 | return name; | |
186 | } | |
187 | ||
188 | @Override | |
a3b510ab NR |
189 | public String toString() { |
190 | return toString(Format.VCard21); | |
191 | } | |
192 | ||
78e4af97 NR |
193 | /** |
194 | * Load the given data from the given {@link Format} in this {@link Card}. | |
195 | * | |
196 | * @param serializedContent | |
197 | * the data | |
198 | * @param format | |
199 | * the {@link Format} | |
200 | */ | |
a3b510ab NR |
201 | protected void load(String serializedContent, Format format) { |
202 | // note: fixed size array | |
203 | List<String> lines = Arrays.asList(serializedContent.split("\n")); | |
204 | load(lines, format); | |
205 | } | |
206 | ||
78e4af97 NR |
207 | /** |
208 | * Load the given data from the given {@link Format} in this {@link Card}. | |
209 | * | |
210 | * @param lines | |
211 | * the data | |
212 | * @param format | |
213 | * the {@link Format} | |
214 | */ | |
a3b510ab NR |
215 | protected void load(List<String> lines, Format format) { |
216 | this.contacts = Parser.parse(lines, format); | |
217 | setDirty(); | |
218 | ||
219 | for (Contact contact : contacts) { | |
220 | contact.setParent(this); | |
221 | } | |
222 | } | |
223 | ||
a3b510ab NR |
224 | /** |
225 | * Notify that this element has unsaved changes. | |
226 | */ | |
227 | void setDirty() { | |
228 | dirty = true; | |
229 | } | |
bcb54330 NR |
230 | |
231 | /** | |
232 | * Notify this element <i>and all its descendants</i> that it is in pristine | |
233 | * state (as opposed to dirty). | |
234 | */ | |
235 | void setPristine() { | |
236 | dirty = false; | |
237 | for (Contact contact : contacts) { | |
238 | contact.setPristine(); | |
239 | } | |
240 | } | |
a3b510ab | 241 | } |