1 package com.leonarduk.clearcheckbook.file;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import java.io.PrintWriter;
9 import java.io.UnsupportedEncodingException;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.Map;
15
16 import org.apache.log4j.Logger;
17
18 import com.google.common.base.Joiner;
19 import com.google.common.base.Splitter;
20 import com.leonarduk.clearcheckbook.ClearcheckbookException;
21 import com.leonarduk.clearcheckbook.dto.AbstractDataType;
22 import com.leonarduk.clearcheckbook.dto.AccountDataType;
23 import com.leonarduk.clearcheckbook.dto.CategoryDataType;
24 import com.leonarduk.clearcheckbook.dto.LimitDataType;
25 import com.leonarduk.clearcheckbook.dto.ReminderDataType;
26 import com.leonarduk.clearcheckbook.dto.TransactionDataType;
27
28 public class ClearCheckBookFileHandler {
29
30 private static final Logger _logger = Logger
31 .getLogger(ClearCheckBookFileHandler.class);
32
33 public ClearCheckBookFileHandler() {
34
35 }
36
37 /***
38 *
39 * @param fileName
40 * @param accounts
41 * @return
42 * @throws ClearcheckbookException
43 */
44 public File exportAccounts(String fileName, List<AccountDataType> accounts)
45 throws ClearcheckbookException {
46 _logger.debug("exportAccounts: " + fileName + " " + accounts);
47 Enum<?>[] headers = AccountDataType.Fields.values();
48 return exportToFile(fileName, headers, accounts);
49 }
50
51 /***
52 *
53 * @param fileName
54 * @param categories
55 * @return
56 * @throws ClearcheckbookException
57 */
58 public File exportCategories(String fileName,
59 List<CategoryDataType> categories) throws ClearcheckbookException {
60 _logger.debug("exportCategories: " + fileName + " " + categories);
61 Enum<?>[] headers = CategoryDataType.Fields.values();
62 return exportToFile(fileName, headers, categories);
63 }
64
65 /***
66 *
67 * @param fileName
68 * @param limits
69 * @return
70 * @throws ClearcheckbookException
71 */
72 public File exportLimits(String fileName, List<LimitDataType> limits)
73 throws ClearcheckbookException {
74 _logger.debug("exportLimits: " + fileName + " " + limits);
75 Enum<?>[] headers = LimitDataType.Fields.values();
76 return exportToFile(fileName, headers, limits);
77 }
78
79 /***
80 *
81 * @param fileName
82 * @param reminders
83 * @return
84 * @throws ClearcheckbookException
85 */
86 public File exportReminders(String fileName,
87 List<ReminderDataType> reminders) throws ClearcheckbookException {
88 _logger.debug("exportReminders: " + fileName + " " + reminders);
89 Enum<?>[] headers = ReminderDataType.Fields.values();
90 return exportToFile(fileName, headers, reminders);
91 }
92
93 /***
94 *
95 * @param fileName
96 * @param headers
97 * @param dataTypes
98 * @return
99 * @throws ClearcheckbookException
100 */
101 private File exportToFile(String fileName, Enum<?>[] headers,
102 List<? extends AbstractDataType> dataTypes)
103 throws ClearcheckbookException {
104 PrintWriter writer;
105 try {
106 File file = new File(fileName);
107 writer = new PrintWriter(file, "UTF-8");
108 String separator = "\",\"";
109 writer.println("\"" + Joiner.on(separator).join(headers) + "\"");
110 for (Iterator<? extends AbstractDataType> iterator = dataTypes
111 .iterator(); iterator.hasNext();) {
112 AbstractDataType<?> dataType = iterator.next();
113 writer.println("\""
114 + Joiner.on(separator).join(dataType.getValues())
115 + "\"");
116 }
117 writer.close();
118 return file;
119 } catch (FileNotFoundException | UnsupportedEncodingException e) {
120 throw new ClearcheckbookException(
121 "Failed to export to " + fileName, e);
122 }
123
124 }
125
126 /***
127 *
128 * @param fileName
129 * @param transactions
130 * @return
131 * @throws ClearcheckbookException
132 */
133 public File exportTransactions(String fileName,
134 List<TransactionDataType> transactions)
135 throws ClearcheckbookException {
136 _logger.debug("exportTransactions: " + fileName + " " + transactions);
137 Enum<?>[] headers = TransactionDataType.getFileFields();
138 return exportToFile(fileName, headers, transactions);
139 }
140
141 public List<AccountDataType> importAccounts(String fileName)
142 throws ClearcheckbookException {
143 _logger.debug("importTransactions: " + fileName);
144 return importFromFile(fileName, AccountDataType.class);
145 }
146
147 public List<CategoryDataType> importCategories(String fileName)
148 throws ClearcheckbookException {
149 _logger.debug("importTransactions: " + fileName);
150 return importFromFile(fileName, CategoryDataType.class);
151 }
152
153 /***
154 *
155 * @param fileName
156 * @return
157 * @throws ClearcheckbookException
158 */
159 public <D extends AbstractDataType<?>> List<D> importFromFile(
160 String fileName, Class<D> c) throws ClearcheckbookException {
161 return importFromFile(fileName, c, new TransactionFilePreprocessor());
162 }
163
164 public <D extends AbstractDataType<?>> List<D> importFromFile(
165 String fileName, Class<D> class1, FilePreProcessor processor)
166 throws ClearcheckbookException {
167
168 String separator = ",";
169 List<D> dataItems = new LinkedList<>();
170
171 try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
172
173
174 for (int i = 0; i < processor.getRowsToSkip(); i++) {
175 br.readLine();
176 }
177 String line = br.readLine();
178 List<String> headerFields = processor.processHeaderRow(separator, line);
179
180
181 line = br.readLine();
182
183 while (line != null) {
184 Map<String, String> fieldsMap = new HashMap<>();
185 Iterable<String> fields = Splitter.on(separator).trimResults()
186 .split(line);
187 Iterator<String> headerIter = headerFields.iterator();
188 for (String field : fields) {
189 String headerName = headerIter.next();
190 _logger.debug(headerName + "=" + field.replace("\"", ""));
191 fieldsMap.put(headerName.toLowerCase(),
192 field.replace("\"", ""));
193 }
194 Map<String, String> processedMap = processor
195 .processRow(fieldsMap);
196 try {
197 D newElem = class1.getDeclaredConstructor(Map.class)
198 .newInstance(processedMap);
199 dataItems.add(newElem);
200 } catch (Exception e) {
201 throw new ClearcheckbookException("Failed to import file",
202 e);
203 }
204
205 line = br.readLine();
206 }
207 return dataItems;
208 } catch (IOException e) {
209 throw new ClearcheckbookException("Failed to import file", e);
210 }
211 }
212
213 public List<LimitDataType> importLimits(String fileName)
214 throws ClearcheckbookException {
215 _logger.debug("importTransactions: " + fileName);
216 return importFromFile(fileName, LimitDataType.class);
217 }
218
219 public List<ReminderDataType> importReminders(String fileName)
220 throws ClearcheckbookException {
221 _logger.debug("importTransactions: " + fileName);
222 return importFromFile(fileName, ReminderDataType.class);
223 }
224
225 public List<TransactionDataType> importTransactions(String fileName,
226 FilePreProcessor processor) throws ClearcheckbookException {
227 _logger.debug("importTransactions: " + fileName);
228 return importFromFile(fileName, TransactionDataType.class, processor);
229 }
230
231 }