]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsViewModel.java
template details model: method for creating a copy of the data list
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / templates / TemplateDetailsViewModel.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.ui.templates;
19
20 import android.os.AsyncTask;
21
22 import androidx.lifecycle.LiveData;
23 import androidx.lifecycle.MutableLiveData;
24 import androidx.lifecycle.Observer;
25 import androidx.lifecycle.ViewModel;
26
27 import net.ktnx.mobileledger.dao.TemplateAccountDAO;
28 import net.ktnx.mobileledger.dao.TemplateHeaderDAO;
29 import net.ktnx.mobileledger.db.DB;
30 import net.ktnx.mobileledger.db.TemplateAccount;
31 import net.ktnx.mobileledger.db.TemplateHeader;
32 import net.ktnx.mobileledger.db.TemplateWithAccounts;
33 import net.ktnx.mobileledger.model.TemplateDetailsItem;
34 import net.ktnx.mobileledger.utils.Logger;
35
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Objects;
41 import java.util.concurrent.atomic.AtomicInteger;
42
43 public class TemplateDetailsViewModel extends ViewModel {
44     private final MutableLiveData<List<TemplateDetailsItem>> items =
45             new MutableLiveData<>(Collections.emptyList());
46     private Long mPatternId;
47     private String mDefaultPatternName;
48     private boolean itemsLoaded = false;
49     private final AtomicInteger syntheticItemId = new AtomicInteger(0);
50
51     public String getDefaultPatternName() {
52         return mDefaultPatternName;
53     }
54     public void setDefaultPatternName(String name) {
55         mDefaultPatternName = name;
56     }
57
58     public void resetItems() {
59         checkItemConsistency(new ArrayList<>());
60     }
61     public void checkItemConsistency(List<TemplateDetailsItem> list) {
62         if (list == null)
63             list = new ArrayList<>(items.getValue());
64
65         boolean changes = false;
66         if (list.size() < 1) {
67             final TemplateDetailsItem.Header header = TemplateDetailsItem.createHeader();
68             header.setName(mDefaultPatternName);
69             header.setId(0);
70             list.add(header);
71             changes = true;
72         }
73
74         while (list.size() < 3) {
75             final TemplateDetailsItem.AccountRow accountRow =
76                     TemplateDetailsItem.createAccountRow();
77             accountRow.setId(genItemId());
78             list.add(accountRow);
79             changes = true;
80         }
81
82         if (changes)
83             items.setValue(list);
84     }
85     public int genItemId() {
86         return syntheticItemId.decrementAndGet();
87     }
88     public LiveData<List<TemplateDetailsItem>> getItems(Long patternId) {
89         if (itemsLoaded && Objects.equals(patternId, this.mPatternId))
90             return items;
91
92         if (patternId != null && patternId <= 0)
93             throw new IllegalArgumentException("Pattern ID " + patternId + " is invalid");
94
95         mPatternId = patternId;
96
97         if (mPatternId == null) {
98             resetItems();
99             itemsLoaded = true;
100             return items;
101         }
102
103         DB db = DB.get();
104         LiveData<TemplateWithAccounts> dbList = db.getTemplateDAO()
105                                                   .getTemplateWithAccounts(mPatternId);
106         Observer<TemplateWithAccounts> observer = new Observer<TemplateWithAccounts>() {
107             @Override
108             public void onChanged(TemplateWithAccounts src) {
109                 ArrayList<TemplateDetailsItem> l = new ArrayList<>();
110
111                 TemplateDetailsItem header = TemplateDetailsItem.fromRoomObject(src.header);
112                 l.add(header);
113                 for (TemplateAccount acc : src.accounts) {
114                     l.add(TemplateDetailsItem.fromRoomObject(acc));
115                 }
116
117                 for (TemplateDetailsItem i : l) {
118                     Logger.debug("patterns-db", "Loaded pattern item " + i);
119                 }
120                 items.postValue(l);
121                 itemsLoaded = true;
122
123                 dbList.removeObserver(this);
124             }
125         };
126         dbList.observeForever(observer);
127
128         return items;
129     }
130     public void setTestText(String text) {
131         List<TemplateDetailsItem> list = new ArrayList<>(items.getValue());
132         TemplateDetailsItem.Header header = new TemplateDetailsItem.Header(list.get(0)
133                                                                                .asHeaderItem());
134         header.setTestText(text);
135         list.set(0, header);
136
137         items.setValue(list);
138     }
139     public void onSaveTemplate() {
140         Logger.debug("flow", "PatternDetailsViewModel.onSavePattern(); model=" + this);
141         final List<TemplateDetailsItem> list = Objects.requireNonNull(items.getValue());
142
143         AsyncTask.execute(() -> {
144             boolean newPattern = mPatternId == null || mPatternId <= 0;
145
146             TemplateDetailsItem.Header modelHeader = list.get(0)
147                                                          .asHeaderItem();
148             TemplateHeaderDAO headerDAO = DB.get()
149                                             .getTemplateDAO();
150             TemplateHeader dbHeader = modelHeader.toDBO();
151             if (newPattern) {
152                 dbHeader.setId(null);
153                 dbHeader.setId(mPatternId = headerDAO.insertSync(dbHeader));
154             }
155             else
156                 headerDAO.updateSync(dbHeader);
157
158             Logger.debug("pattern-db",
159                     String.format(Locale.US, "Stored pattern header %d, item=%s", dbHeader.getId(),
160                             modelHeader));
161
162
163             TemplateAccountDAO taDAO = DB.get()
164                                          .getTemplateAccountDAO();
165             taDAO.prepareForSave(mPatternId);
166             for (int i = 1; i < list.size(); i++) {
167                 final TemplateDetailsItem.AccountRow accRowItem = list.get(i)
168                                                                       .asAccountRowItem();
169                 TemplateAccount dbAccount = accRowItem.toDBO(dbHeader.getId());
170                 dbAccount.setTemplateId(mPatternId);
171                 dbAccount.setPosition(i);
172                 if (dbAccount.getId() < 0) {
173                     dbAccount.setId(null);
174                     dbAccount.setId(taDAO.insertSync(dbAccount));
175                 }
176                 else
177                     taDAO.updateSync(dbAccount);
178
179                 Logger.debug("pattern-db", String.format(Locale.US,
180                         "Stored pattern account %d, account=%s, comment=%s, neg=%s, item=%s",
181                         dbAccount.getId(), dbAccount.getAccountName(),
182                         dbAccount.getAccountComment(), dbAccount.getNegateAmount(), accRowItem));
183             }
184             taDAO.finishSave(mPatternId);
185         });
186     }
187     private ArrayList<TemplateDetailsItem> copyItems() {
188         List<TemplateDetailsItem> oldList = items.getValue();
189         ArrayList<TemplateDetailsItem> result = new ArrayList<>(oldList.size());
190
191         for (TemplateDetailsItem item : oldList) {
192             if (item instanceof TemplateDetailsItem.Header)
193                 result.add(new TemplateDetailsItem.Header(item.asHeaderItem()));
194             else if (item instanceof TemplateDetailsItem.AccountRow)
195                 result.add(new TemplateDetailsItem.AccountRow(item.asAccountRowItem()));
196             else
197                 throw new RuntimeException("Unexpected item " + item);
198         }
199
200         return result;
201     }
202     public void moveItem(int sourcePos, int targetPos) {
203         ArrayList<TemplateDetailsItem> newList = new ArrayList<>(items.getValue());
204         TemplateDetailsItem item = newList.remove(sourcePos);
205         newList.add(targetPos, item);
206         items.setValue(newList);
207     }
208     public void removeItem(int position) {
209         ArrayList<TemplateDetailsItem> newList = new ArrayList<>(items.getValue());
210         newList.remove(position);
211         checkItemConsistency(newList);
212         items.setValue(newList);
213     }
214 }