]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/async/ConfigReader.java
fall back to any profile when restoring config
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / async / ConfigReader.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.async;
19
20 import android.content.Context;
21 import android.net.Uri;
22 import android.util.JsonReader;
23 import android.util.JsonToken;
24
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.Misc;
36
37 import java.io.BufferedReader;
38 import java.io.FileInputStream;
39 import java.io.FileNotFoundException;
40 import java.io.IOException;
41 import java.io.InputStreamReader;
42 import java.util.ArrayList;
43 import java.util.List;
44
45 public class ConfigReader extends ConfigIO {
46     private final OnDoneListener onDoneListener;
47     private JsonReader r;
48     public ConfigReader(Context context, Uri uri, OnErrorListener onErrorListener,
49                         OnDoneListener onDoneListener) throws FileNotFoundException {
50         super(context, uri, onErrorListener);
51
52         this.onDoneListener = onDoneListener;
53     }
54     @Override
55     protected String getStreamMode() {
56         return "r";
57     }
58     @Override
59     protected void initStream() {
60         r = new JsonReader(new BufferedReader(
61                 new InputStreamReader(new FileInputStream(pfd.getFileDescriptor()))));
62     }
63     @Override
64     protected void processStream() throws IOException {
65         List<Currency> commodities = null;
66         List<Profile> profiles = null;
67         List<TemplateWithAccounts> templates = null;
68         String currentProfile = null;
69         r.beginObject();
70         while (r.hasNext()) {
71             String item = r.nextName();
72             switch (item) {
73                 case Keys.COMMODITIES:
74                     commodities = readCommodities(r);
75                     break;
76                 case Keys.PROFILES:
77                     profiles = readProfiles(r);
78                     break;
79                 case Keys.TEMPLATES:
80                     templates = readTemplates(r);
81                     break;
82                 case Keys.CURRENT_PROFILE:
83                     currentProfile = r.nextString();
84                     break;
85                 default:
86                     throw new RuntimeException("unexpected top-level item " + item);
87             }
88         }
89         r.endObject();
90
91         restoreCommodities(commodities);
92         restoreProfiles(profiles);
93         restoreTemplates(templates);
94
95         if (Data.getProfile() == null) {
96             Profile p = null;
97             final ProfileDAO dao = DB.get()
98                                      .getProfileDAO();
99             if (currentProfile != null)
100                 p = dao.getByUuidSync(currentProfile);
101
102             if (p == null)
103                 dao.getAnySync();
104
105             if (p != null)
106                 Data.postCurrentProfile(p);
107         }
108
109         if (onDoneListener != null)
110             Misc.onMainThread(onDoneListener::done);
111     }
112     private void restoreTemplates(List<TemplateWithAccounts> list) {
113         if (list == null)
114             return;
115
116         TemplateHeaderDAO dao = DB.get()
117                                   .getTemplateDAO();
118
119         for (TemplateWithAccounts t : list) {
120             if (dao.getTemplateWithAccountsByUuidSync(t.header.getUuid()) == null)
121                 dao.insertSync(t);
122         }
123     }
124     private void restoreProfiles(List<Profile> list) {
125         if (list == null)
126             return;
127
128         ProfileDAO dao = DB.get()
129                            .getProfileDAO();
130
131         for (Profile p : list) {
132             if (dao.getByUuidSync(p.getUuid()) == null)
133                 dao.insert(p);
134         }
135     }
136     private void restoreCommodities(List<Currency> list) {
137         if (list == null)
138             return;
139
140         CurrencyDAO dao = DB.get()
141                             .getCurrencyDAO();
142
143         for (Currency c : list) {
144             if (dao.getByNameSync(c.getName()) == null)
145                 dao.insert(c);
146         }
147     }
148     private TemplateAccount readTemplateAccount(JsonReader r) throws IOException {
149         r.beginObject();
150         TemplateAccount result = new TemplateAccount(0L, 0L, 0L);
151         while (r.peek() != JsonToken.END_OBJECT) {
152             String item = r.nextName();
153             switch (item) {
154                 case Keys.NAME:
155                     result.setAccountName(r.nextString());
156                     break;
157                 case Keys.NAME_GROUP:
158                     result.setAccountNameMatchGroup(r.nextInt());
159                     break;
160                 case Keys.COMMENT:
161                     result.setAccountComment(r.nextString());
162                     break;
163                 case Keys.COMMENT_GROUP:
164                     result.setAccountCommentMatchGroup(r.nextInt());
165                     break;
166                 case Keys.AMOUNT:
167                     result.setAmount((float) r.nextDouble());
168                     break;
169                 case Keys.AMOUNT_GROUP:
170                     result.setAmountMatchGroup(r.nextInt());
171                     break;
172                 case Keys.NEGATE_AMOUNT:
173                     result.setNegateAmount(r.nextBoolean());
174                     break;
175                 case Keys.CURRENCY:
176                     result.setCurrency(r.nextLong());
177                     break;
178                 case Keys.CURRENCY_GROUP:
179                     result.setCurrencyMatchGroup(r.nextInt());
180                     break;
181
182                 default:
183                     throw new IllegalStateException("Unexpected template account item: " + item);
184             }
185         }
186         r.endObject();
187
188         return result;
189     }
190     private TemplateWithAccounts readTemplate(JsonReader r) throws IOException {
191         r.beginObject();
192         String name = null;
193         TemplateHeader t = new TemplateHeader(0L, "", "");
194         List<TemplateAccount> accounts = new ArrayList<>();
195
196         while (r.peek() != JsonToken.END_OBJECT) {
197             String item = r.nextName();
198             switch (item) {
199                 case Keys.UUID:
200                     t.setUuid(r.nextString());
201                     break;
202                 case Keys.NAME:
203                     t.setName(r.nextString());
204                     break;
205                 case Keys.REGEX:
206                     t.setRegularExpression(r.nextString());
207                     break;
208                 case Keys.TEST_TEXT:
209                     t.setTestText(r.nextString());
210                     break;
211                 case Keys.DATE_YEAR:
212                     t.setDateYear(r.nextInt());
213                     break;
214                 case Keys.DATE_YEAR_GROUP:
215                     t.setDateYearMatchGroup(r.nextInt());
216                     break;
217                 case Keys.DATE_MONTH:
218                     t.setDateMonth(r.nextInt());
219                     break;
220                 case Keys.DATE_MONTH_GROUP:
221                     t.setDateMonthMatchGroup(r.nextInt());
222                     break;
223                 case Keys.DATE_DAY:
224                     t.setDateDay(r.nextInt());
225                     break;
226                 case Keys.DATE_DAY_GROUP:
227                     t.setDateDayMatchGroup(r.nextInt());
228                     break;
229                 case Keys.TRANSACTION:
230                     t.setTransactionDescription(r.nextString());
231                     break;
232                 case Keys.TRANSACTION_GROUP:
233                     t.setTransactionDescriptionMatchGroup(r.nextInt());
234                     break;
235                 case Keys.COMMENT:
236                     t.setTransactionComment(r.nextString());
237                     break;
238                 case Keys.COMMENT_GROUP:
239                     t.setTransactionCommentMatchGroup(r.nextInt());
240                     break;
241                 case Keys.IS_FALLBACK:
242                     t.setFallback(r.nextBoolean());
243                     break;
244                 case Keys.ACCOUNTS:
245                     r.beginArray();
246                     while (r.peek() == JsonToken.BEGIN_OBJECT) {
247                         accounts.add(readTemplateAccount(r));
248                     }
249                     r.endArray();
250                     break;
251                 default:
252                     throw new RuntimeException("Unknown template header item: " + item);
253             }
254         }
255         r.endObject();
256
257         TemplateWithAccounts result = new TemplateWithAccounts();
258         result.header = t;
259         result.accounts = accounts;
260         return result;
261     }
262     private List<TemplateWithAccounts> readTemplates(JsonReader r) throws IOException {
263         List<TemplateWithAccounts> list = new ArrayList<>();
264
265         r.beginArray();
266         while (r.peek() == JsonToken.BEGIN_OBJECT) {
267             list.add(readTemplate(r));
268         }
269         r.endArray();
270
271         return list;
272     }
273     private List<Currency> readCommodities(JsonReader r) throws IOException {
274         List<Currency> list = new ArrayList<>();
275
276         r.beginArray();
277         while (r.peek() == JsonToken.BEGIN_OBJECT) {
278             Currency c = new Currency();
279
280             r.beginObject();
281             while (r.peek() != JsonToken.END_OBJECT) {
282                 final String item = r.nextName();
283                 switch (item) {
284                     case Keys.NAME:
285                         c.setName(r.nextString());
286                         break;
287                     case Keys.POSITION:
288                         c.setPosition(r.nextString());
289                         break;
290                     case Keys.HAS_GAP:
291                         c.setHasGap(r.nextBoolean());
292                         break;
293                     default:
294                         throw new RuntimeException("Unknown commodity key: " + item);
295                 }
296             }
297             r.endObject();
298
299             if (c.getName()
300                  .isEmpty())
301                 throw new RuntimeException("Missing commodity name");
302
303             list.add(c);
304         }
305         r.endArray();
306
307         return list;
308     }
309     private List<Profile> readProfiles(JsonReader r) throws IOException {
310         List<Profile> list = new ArrayList<>();
311         r.beginArray();
312         while (r.peek() == JsonToken.BEGIN_OBJECT) {
313             Profile p = new Profile();
314             r.beginObject();
315             while (r.peek() != JsonToken.END_OBJECT) {
316                 String item = r.nextName();
317
318                 switch (item) {
319                     case Keys.UUID:
320                         p.setUuid(r.nextString());
321                         break;
322                     case Keys.NAME:
323                         p.setName(r.nextString());
324                         break;
325                     case Keys.URL:
326                         p.setUrl(r.nextString());
327                         break;
328                     case Keys.USE_AUTH:
329                         p.setUseAuthentication(r.nextBoolean());
330                         break;
331                     case Keys.AUTH_USER:
332                         p.setAuthUser(r.nextString());
333                         break;
334                     case Keys.AUTH_PASS:
335                         p.setAuthPassword(r.nextString());
336                         break;
337                     case Keys.API_VER:
338                         p.setApiVersion(r.nextInt());
339                         break;
340                     case Keys.CAN_POST:
341                         p.setPermitPosting(r.nextBoolean());
342                         break;
343                     case Keys.DEFAULT_COMMODITY:
344                         p.setDefaultCommodity(r.nextString());
345                         break;
346                     case Keys.SHOW_COMMODITY:
347                         p.setShowCommodityByDefault(r.nextBoolean());
348                         break;
349                     case Keys.SHOW_COMMENTS:
350                         p.setShowCommentsByDefault(r.nextBoolean());
351                         break;
352                     case Keys.FUTURE_DATES:
353                         p.setFutureDates(r.nextInt());
354                         break;
355                     case Keys.PREF_ACCOUNT:
356                         p.setPreferredAccountsFilter(r.nextString());
357                         break;
358                     case Keys.COLOUR:
359                         p.setTheme(r.nextInt());
360                         break;
361
362
363                     default:
364                         throw new IllegalStateException("Unexpected profile item: " + item);
365                 }
366             }
367             r.endObject();
368
369             list.add(p);
370         }
371         r.endArray();
372
373         return list;
374     }
375     abstract static public class OnDoneListener {
376         public abstract void done();
377     }
378 }