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.
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.
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/>.
18 package net.ktnx.mobileledger.async;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.util.JsonReader;
23 import android.util.JsonToken;
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;
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;
45 public class ConfigReader extends ConfigIO {
46 private final OnDoneListener onDoneListener;
48 public ConfigReader(Context context, Uri uri, OnErrorListener onErrorListener,
49 OnDoneListener onDoneListener) throws FileNotFoundException {
50 super(context, uri, onErrorListener);
52 this.onDoneListener = onDoneListener;
55 protected String getStreamMode() {
59 protected void initStream() {
60 r = new JsonReader(new BufferedReader(
61 new InputStreamReader(new FileInputStream(pfd.getFileDescriptor()))));
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;
71 String item = r.nextName();
72 if (r.peek() == JsonToken.NULL) {
77 case Keys.COMMODITIES:
78 commodities = readCommodities(r);
81 profiles = readProfiles(r);
84 templates = readTemplates(r);
86 case Keys.CURRENT_PROFILE:
87 currentProfile = r.nextString();
90 throw new RuntimeException("unexpected top-level item " + item);
95 restoreCommodities(commodities);
96 restoreProfiles(profiles);
97 restoreTemplates(templates);
99 if (Data.getProfile() == null) {
101 final ProfileDAO dao = DB.get()
103 if (currentProfile != null)
104 p = dao.getByUuidSync(currentProfile);
110 Data.postCurrentProfile(p);
113 if (onDoneListener != null)
114 Misc.onMainThread(onDoneListener::done);
116 private void restoreTemplates(List<TemplateWithAccounts> list) {
120 TemplateHeaderDAO dao = DB.get()
123 for (TemplateWithAccounts t : list) {
124 if (dao.getTemplateWithAccountsByUuidSync(t.header.getUuid()) == null)
128 private void restoreProfiles(List<Profile> list) {
132 ProfileDAO dao = DB.get()
135 for (Profile p : list) {
136 if (dao.getByUuidSync(p.getUuid()) == null)
140 private void restoreCommodities(List<Currency> list) {
144 CurrencyDAO dao = DB.get()
147 for (Currency c : list) {
148 if (dao.getByNameSync(c.getName()) == null)
152 private TemplateAccount readTemplateAccount(JsonReader r) throws IOException {
154 TemplateAccount result = new TemplateAccount(0L, 0L, 0L);
155 while (r.peek() != JsonToken.END_OBJECT) {
156 String item = r.nextName();
157 if (r.peek() == JsonToken.NULL) {
163 result.setAccountName(r.nextString());
165 case Keys.NAME_GROUP:
166 result.setAccountNameMatchGroup(r.nextInt());
169 result.setAccountComment(r.nextString());
171 case Keys.COMMENT_GROUP:
172 result.setAccountCommentMatchGroup(r.nextInt());
175 result.setAmount((float) r.nextDouble());
177 case Keys.AMOUNT_GROUP:
178 result.setAmountMatchGroup(r.nextInt());
180 case Keys.NEGATE_AMOUNT:
181 result.setNegateAmount(r.nextBoolean());
184 result.setCurrency(r.nextLong());
186 case Keys.CURRENCY_GROUP:
187 result.setCurrencyMatchGroup(r.nextInt());
191 throw new IllegalStateException("Unexpected template account item: " + item);
198 private TemplateWithAccounts readTemplate(JsonReader r) throws IOException {
201 TemplateHeader t = new TemplateHeader(0L, "", "");
202 List<TemplateAccount> accounts = new ArrayList<>();
204 while (r.peek() != JsonToken.END_OBJECT) {
205 String item = r.nextName();
206 if (r.peek() == JsonToken.NULL) {
212 t.setUuid(r.nextString());
215 t.setName(r.nextString());
218 t.setRegularExpression(r.nextString());
221 t.setTestText(r.nextString());
224 t.setDateYear(r.nextInt());
226 case Keys.DATE_YEAR_GROUP:
227 t.setDateYearMatchGroup(r.nextInt());
229 case Keys.DATE_MONTH:
230 t.setDateMonth(r.nextInt());
232 case Keys.DATE_MONTH_GROUP:
233 t.setDateMonthMatchGroup(r.nextInt());
236 t.setDateDay(r.nextInt());
238 case Keys.DATE_DAY_GROUP:
239 t.setDateDayMatchGroup(r.nextInt());
241 case Keys.TRANSACTION:
242 t.setTransactionDescription(r.nextString());
244 case Keys.TRANSACTION_GROUP:
245 t.setTransactionDescriptionMatchGroup(r.nextInt());
248 t.setTransactionComment(r.nextString());
250 case Keys.COMMENT_GROUP:
251 t.setTransactionCommentMatchGroup(r.nextInt());
253 case Keys.IS_FALLBACK:
254 t.setFallback(r.nextBoolean());
258 while (r.peek() == JsonToken.BEGIN_OBJECT) {
259 accounts.add(readTemplateAccount(r));
264 throw new RuntimeException("Unknown template header item: " + item);
269 TemplateWithAccounts result = new TemplateWithAccounts();
271 result.accounts = accounts;
274 private List<TemplateWithAccounts> readTemplates(JsonReader r) throws IOException {
275 List<TemplateWithAccounts> list = new ArrayList<>();
278 while (r.peek() == JsonToken.BEGIN_OBJECT) {
279 list.add(readTemplate(r));
285 private List<Currency> readCommodities(JsonReader r) throws IOException {
286 List<Currency> list = new ArrayList<>();
289 while (r.peek() == JsonToken.BEGIN_OBJECT) {
290 Currency c = new Currency();
293 while (r.peek() != JsonToken.END_OBJECT) {
294 final String item = r.nextName();
295 if (r.peek() == JsonToken.NULL) {
301 c.setName(r.nextString());
304 c.setPosition(r.nextString());
307 c.setHasGap(r.nextBoolean());
310 throw new RuntimeException("Unknown commodity key: " + item);
317 throw new RuntimeException("Missing commodity name");
325 private List<Profile> readProfiles(JsonReader r) throws IOException {
326 List<Profile> list = new ArrayList<>();
328 while (r.peek() == JsonToken.BEGIN_OBJECT) {
329 Profile p = new Profile();
331 while (r.peek() != JsonToken.END_OBJECT) {
332 String item = r.nextName();
333 if (r.peek() == JsonToken.NULL) {
340 p.setUuid(r.nextString());
343 p.setName(r.nextString());
346 p.setUrl(r.nextString());
349 p.setUseAuthentication(r.nextBoolean());
352 p.setAuthUser(r.nextString());
355 p.setAuthPassword(r.nextString());
358 p.setApiVersion(r.nextInt());
361 p.setPermitPosting(r.nextBoolean());
363 case Keys.DEFAULT_COMMODITY:
364 p.setDefaultCommodity(r.nextString());
366 case Keys.SHOW_COMMODITY:
367 p.setShowCommodityByDefault(r.nextBoolean());
369 case Keys.SHOW_COMMENTS:
370 p.setShowCommentsByDefault(r.nextBoolean());
372 case Keys.FUTURE_DATES:
373 p.setFutureDates(r.nextInt());
375 case Keys.PREF_ACCOUNT:
376 p.setPreferredAccountsFilter(r.nextString());
379 p.setTheme(r.nextInt());
384 throw new IllegalStateException("Unexpected profile item: " + item);
395 abstract static public class OnDoneListener {
396 public abstract void done();