]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/backup/RawConfigReader.java
more pronounced day/month delimiters in the transaction list
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / backup / RawConfigReader.java
1 /*
2  * Copyright © 2021 Damyan Ivanov.
3  * This file is part of MoLe.
4  * MoLe is free software: you can distribute it and/or modify it
5  * under the term of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your opinion), any later version.
8  *
9  * MoLe is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License terms for details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
16  */
17
18 package net.ktnx.mobileledger.backup;
19
20 import android.util.JsonReader;
21 import android.util.JsonToken;
22
23 import net.ktnx.mobileledger.App;
24 import net.ktnx.mobileledger.backup.ConfigIO.Keys;
25 import net.ktnx.mobileledger.dao.CurrencyDAO;
26 import net.ktnx.mobileledger.dao.ProfileDAO;
27 import net.ktnx.mobileledger.dao.TemplateHeaderDAO;
28 import net.ktnx.mobileledger.db.Currency;
29 import net.ktnx.mobileledger.db.DB;
30 import net.ktnx.mobileledger.db.Profile;
31 import net.ktnx.mobileledger.db.TemplateAccount;
32 import net.ktnx.mobileledger.db.TemplateHeader;
33 import net.ktnx.mobileledger.db.TemplateWithAccounts;
34 import net.ktnx.mobileledger.model.Data;
35 import net.ktnx.mobileledger.utils.Logger;
36
37 import java.io.BufferedReader;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
41 import java.util.ArrayList;
42 import java.util.List;
43
44 public class RawConfigReader {
45     private final JsonReader r;
46     private List<Currency> commodities;
47     private List<Profile> profiles;
48     private List<TemplateWithAccounts> templates;
49     private String currentProfile;
50     public RawConfigReader(InputStream inputStream) {
51         r = new JsonReader(new BufferedReader(new InputStreamReader(inputStream)));
52     }
53     public List<Currency> getCommodities() {
54         return commodities;
55     }
56     public List<Profile> getProfiles() {
57         return profiles;
58     }
59     public List<TemplateWithAccounts> getTemplates() {
60         return templates;
61     }
62     public String getCurrentProfile() {
63         return currentProfile;
64     }
65     public void readConfig() throws IOException {
66         commodities = null;
67         profiles = null;
68         templates = null;
69         currentProfile = null;
70         r.beginObject();
71         while (r.hasNext()) {
72             String item = r.nextName();
73             if (r.peek() == JsonToken.NULL) {
74                 r.nextNull();
75                 continue;
76             }
77             switch (item) {
78                 case Keys.COMMODITIES:
79                     commodities = readCommodities();
80                     break;
81                 case Keys.PROFILES:
82                     profiles = readProfiles();
83                     break;
84                 case Keys.TEMPLATES:
85                     templates = readTemplates();
86                     break;
87                 case Keys.CURRENT_PROFILE:
88                     currentProfile = r.nextString();
89                     break;
90                 default:
91                     throw new RuntimeException("unexpected top-level item " + item);
92             }
93         }
94         r.endObject();
95     }
96     private TemplateAccount readTemplateAccount() throws IOException {
97         r.beginObject();
98         TemplateAccount result = new TemplateAccount(0L, 0L, 0L);
99         while (r.peek() != JsonToken.END_OBJECT) {
100             String item = r.nextName();
101             if (r.peek() == JsonToken.NULL) {
102                 r.nextNull();
103                 continue;
104             }
105             switch (item) {
106                 case Keys.NAME:
107                     result.setAccountName(r.nextString());
108                     break;
109                 case Keys.NAME_GROUP:
110                     result.setAccountNameMatchGroup(r.nextInt());
111                     break;
112                 case Keys.COMMENT:
113                     result.setAccountComment(r.nextString());
114                     break;
115                 case Keys.COMMENT_GROUP:
116                     result.setAccountCommentMatchGroup(r.nextInt());
117                     break;
118                 case Keys.AMOUNT:
119                     result.setAmount((float) r.nextDouble());
120                     break;
121                 case Keys.AMOUNT_GROUP:
122                     result.setAmountMatchGroup(r.nextInt());
123                     break;
124                 case Keys.NEGATE_AMOUNT:
125                     result.setNegateAmount(r.nextBoolean());
126                     break;
127                 case Keys.CURRENCY:
128                     result.setCurrency(r.nextLong());
129                     break;
130                 case Keys.CURRENCY_GROUP:
131                     result.setCurrencyMatchGroup(r.nextInt());
132                     break;
133
134                 default:
135                     throw new IllegalStateException("Unexpected template account item: " + item);
136             }
137         }
138         r.endObject();
139
140         return result;
141     }
142     private TemplateWithAccounts readTemplate(JsonReader r) throws IOException {
143         r.beginObject();
144         String name = null;
145         TemplateHeader t = new TemplateHeader(0L, "", "");
146         List<TemplateAccount> accounts = new ArrayList<>();
147
148         while (r.peek() != JsonToken.END_OBJECT) {
149             String item = r.nextName();
150             if (r.peek() == JsonToken.NULL) {
151                 r.nextNull();
152                 continue;
153             }
154             switch (item) {
155                 case Keys.UUID:
156                     t.setUuid(r.nextString());
157                     break;
158                 case Keys.NAME:
159                     t.setName(r.nextString());
160                     break;
161                 case Keys.REGEX:
162                     t.setRegularExpression(r.nextString());
163                     break;
164                 case Keys.TEST_TEXT:
165                     t.setTestText(r.nextString());
166                     break;
167                 case Keys.DATE_YEAR:
168                     t.setDateYear(r.nextInt());
169                     break;
170                 case Keys.DATE_YEAR_GROUP:
171                     t.setDateYearMatchGroup(r.nextInt());
172                     break;
173                 case Keys.DATE_MONTH:
174                     t.setDateMonth(r.nextInt());
175                     break;
176                 case Keys.DATE_MONTH_GROUP:
177                     t.setDateMonthMatchGroup(r.nextInt());
178                     break;
179                 case Keys.DATE_DAY:
180                     t.setDateDay(r.nextInt());
181                     break;
182                 case Keys.DATE_DAY_GROUP:
183                     t.setDateDayMatchGroup(r.nextInt());
184                     break;
185                 case Keys.TRANSACTION:
186                     t.setTransactionDescription(r.nextString());
187                     break;
188                 case Keys.TRANSACTION_GROUP:
189                     t.setTransactionDescriptionMatchGroup(r.nextInt());
190                     break;
191                 case Keys.COMMENT:
192                     t.setTransactionComment(r.nextString());
193                     break;
194                 case Keys.COMMENT_GROUP:
195                     t.setTransactionCommentMatchGroup(r.nextInt());
196                     break;
197                 case Keys.IS_FALLBACK:
198                     t.setFallback(r.nextBoolean());
199                     break;
200                 case Keys.ACCOUNTS:
201                     r.beginArray();
202                     while (r.peek() == JsonToken.BEGIN_OBJECT) {
203                         accounts.add(readTemplateAccount());
204                     }
205                     r.endArray();
206                     break;
207                 default:
208                     throw new RuntimeException("Unknown template header item: " + item);
209             }
210         }
211         r.endObject();
212
213         TemplateWithAccounts result = new TemplateWithAccounts();
214         result.header = t;
215         result.accounts = accounts;
216         return result;
217     }
218     private List<TemplateWithAccounts> readTemplates() throws IOException {
219         List<TemplateWithAccounts> list = new ArrayList<>();
220
221         r.beginArray();
222         while (r.peek() == JsonToken.BEGIN_OBJECT) {
223             list.add(readTemplate(r));
224         }
225         r.endArray();
226
227         return list;
228     }
229     private List<Currency> readCommodities() throws IOException {
230         List<Currency> list = new ArrayList<>();
231
232         r.beginArray();
233         while (r.peek() == JsonToken.BEGIN_OBJECT) {
234             Currency c = new Currency();
235
236             r.beginObject();
237             while (r.peek() != JsonToken.END_OBJECT) {
238                 final String item = r.nextName();
239                 if (r.peek() == JsonToken.NULL) {
240                     r.nextNull();
241                     continue;
242                 }
243                 switch (item) {
244                     case Keys.NAME:
245                         c.setName(r.nextString());
246                         break;
247                     case Keys.POSITION:
248                         c.setPosition(r.nextString());
249                         break;
250                     case Keys.HAS_GAP:
251                         c.setHasGap(r.nextBoolean());
252                         break;
253                     default:
254                         throw new RuntimeException("Unknown commodity key: " + item);
255                 }
256             }
257             r.endObject();
258
259             if (c.getName()
260                  .isEmpty())
261                 throw new RuntimeException("Missing commodity name");
262
263             list.add(c);
264         }
265         r.endArray();
266
267         return list;
268     }
269     private List<Profile> readProfiles() throws IOException {
270         List<Profile> list = new ArrayList<>();
271         r.beginArray();
272         while (r.peek() == JsonToken.BEGIN_OBJECT) {
273             Profile p = new Profile();
274             r.beginObject();
275             while (r.peek() != JsonToken.END_OBJECT) {
276                 String item = r.nextName();
277                 if (r.peek() == JsonToken.NULL) {
278                     r.nextNull();
279                     continue;
280                 }
281
282                 switch (item) {
283                     case Keys.UUID:
284                         p.setUuid(r.nextString());
285                         break;
286                     case Keys.NAME:
287                         p.setName(r.nextString());
288                         break;
289                     case Keys.URL:
290                         p.setUrl(r.nextString());
291                         break;
292                     case Keys.USE_AUTH:
293                         p.setUseAuthentication(r.nextBoolean());
294                         break;
295                     case Keys.AUTH_USER:
296                         p.setAuthUser(r.nextString());
297                         break;
298                     case Keys.AUTH_PASS:
299                         p.setAuthPassword(r.nextString());
300                         break;
301                     case Keys.API_VER:
302                         p.setApiVersion(r.nextInt());
303                         break;
304                     case Keys.CAN_POST:
305                         p.setPermitPosting(r.nextBoolean());
306                         break;
307                     case Keys.DEFAULT_COMMODITY:
308                         p.setDefaultCommodity(r.nextString());
309                         break;
310                     case Keys.SHOW_COMMODITY:
311                         p.setShowCommodityByDefault(r.nextBoolean());
312                         break;
313                     case Keys.SHOW_COMMENTS:
314                         p.setShowCommentsByDefault(r.nextBoolean());
315                         break;
316                     case Keys.FUTURE_DATES:
317                         p.setFutureDates(r.nextInt());
318                         break;
319                     case Keys.PREF_ACCOUNT:
320                         p.setPreferredAccountsFilter(r.nextString());
321                         break;
322                     case Keys.COLOUR:
323                         p.setTheme(r.nextInt());
324                         break;
325
326
327                     default:
328                         throw new IllegalStateException("Unexpected profile item: " + item);
329                 }
330             }
331             r.endObject();
332
333             list.add(p);
334         }
335         r.endArray();
336
337         return list;
338     }
339     public void restoreAll() {
340         restoreCommodities();
341         restoreProfiles();
342         restoreTemplates();
343         restoreCurrentProfile();
344     }
345     private void restoreTemplates() {
346         if (templates == null)
347             return;
348
349         TemplateHeaderDAO dao = DB.get()
350                                   .getTemplateDAO();
351
352         for (TemplateWithAccounts t : templates) {
353             if (dao.getTemplateWithAccountsByUuidSync(t.header.getUuid()) == null)
354                 dao.insertSync(t);
355         }
356     }
357     private void restoreProfiles() {
358         if (profiles == null)
359             return;
360
361         ProfileDAO dao = DB.get()
362                            .getProfileDAO();
363
364         for (Profile p : profiles) {
365             if (dao.getByUuidSync(p.getUuid()) == null)
366                 dao.insert(p);
367         }
368     }
369     private void restoreCommodities() {
370         if (commodities == null)
371             return;
372
373         CurrencyDAO dao = DB.get()
374                             .getCurrencyDAO();
375
376         for (Currency c : commodities) {
377             if (dao.getByNameSync(c.getName()) == null)
378                 dao.insert(c);
379         }
380     }
381     private void restoreCurrentProfile() {
382         if (currentProfile == null) {
383             Logger.debug("backup", "Not restoring current profile (not present in backup)");
384             return;
385         }
386
387         ProfileDAO dao = DB.get()
388                            .getProfileDAO();
389
390         Profile p = dao.getByUuidSync(currentProfile);
391
392         if (p != null) {
393             Logger.debug("backup", "Restoring current profile "+p.getName());
394             Data.postCurrentProfile(p);
395             App.storeStartupProfileAndTheme(p.getId(), p.getTheme());
396         }
397         else {
398             Logger.debug("backup", "Not restoring profile "+currentProfile+": not found in DB");
399         }
400     }
401 }