/*
* Copyright (C) 2011 4th Line GmbH, Switzerland
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fourthline.konto.server.importer.moneydance;
import org.fourthline.konto.server.dao.AccountDAO;
import org.fourthline.konto.server.dao.CurrencyDAO;
import org.fourthline.konto.server.dao.EntryDAO;
import org.fourthline.konto.shared.entity.Account;
import org.fourthline.konto.shared.entity.Entry;
import org.fourthline.konto.shared.entity.MonetaryUnit;
import org.fourthline.konto.shared.entity.Split;
import org.seamless.gwt.validation.shared.Validatable;
import org.seamless.gwt.validation.shared.ValidationError;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Christian Bauer
*/
public class MoneyDanceImporter {
final protected CurrencyDAO currencyDAO;
final protected AccountDAO accountDAO;
final protected EntryDAO entryDAO;
public MoneyDanceImporter(CurrencyDAO currencyDAO, AccountDAO accountDAO, EntryDAO entryDAO) {
this.currencyDAO = currencyDAO;
this.accountDAO = accountDAO;
this.entryDAO = entryDAO;
}
public CurrencyDAO getCurrencyDAO() {
return currencyDAO;
}
public AccountDAO getAccountDAO() {
return accountDAO;
}
public EntryDAO getEntryDAO() {
return entryDAO;
}
public List<ValidationError> importXML(String xml) throws Exception {
List<ValidationError> errors = new ArrayList();
MoneyDanceParser parser = new MoneyDanceParser();
MoneyDanceData data = parser.parse(xml);
List<MonetaryUnit> currencies = data.getCurrencies();
Map<Long, Long> currencyIdMap = storeCurrencies(currencies);
Map<Long, Long> accountIdMap = storeAccounts(errors, currencyIdMap, data.getAccountTree().createAccounts());
if (errors.size() > 0) return errors;
storeEntries(errors, accountIdMap, data.getEntries());
return errors;
}
protected Map<Long, Long> storeCurrencies(List<MonetaryUnit> currencies) {
Map<Long, Long> idMap = new HashMap();
for (MonetaryUnit currency : currencies) {
Long oldId = currency.getId();
MonetaryUnit existing = getCurrencyDAO().getMonetaryUnit(currency.getCurrencyCode());
if (existing != null) {
idMap.put(oldId, existing.getId());
} else {
currency.setId(null);
getCurrencyDAO().persist(currency);
idMap.put(oldId, currency.getId());
}
}
return idMap;
}
protected Map<Long, Long> storeAccounts(List<ValidationError> errors,
Map<Long, Long> currencyIdMap,
List<Account> accounts) {
Map<Long, Long> idMap = new HashMap();
for (Account account : accounts) {
Long newCurrencyId;
if ((newCurrencyId = currencyIdMap.get(account.getMonetaryUnitId())) == null) {
errors.add(new ValidationError(
account.getId().toString(),
Account.class.getName(),
Account.Property.monetaryUnitId,
"Account references missing currency: " + account.getMonetaryUnitId()
));
continue;
}
account.setMonetaryUnitId(newCurrencyId);
if (errors.addAll(account.validate(Validatable.GROUP_SERVER))) break;
Long oldId = account.getId();
account.setId(null);
getAccountDAO().persist(account);
idMap.put(oldId, account.getId());
}
return idMap;
}
protected void storeEntries(List<ValidationError> errors,
Map<Long, Long> accountIdMap,
List<Entry> entries) {
for (Entry entry : entries) {
Long newAccountId;
if ((newAccountId = accountIdMap.get(entry.getAccountId())) == null) {
errors.add(new ValidationError(
entry.getId().toString(),
Entry.class.getName(),
Entry.Property.accountId,
"Entry references missing account: " + entry
));
continue;
}
entry.setAccountId(newAccountId);
for (Split split : entry.getSplits()) {
if ((newAccountId = accountIdMap.get(split.getAccountId())) == null) {
errors.add(new ValidationError(
split.getId().toString(),
Split.class.getName(),
Split.Property.accountId,
"Split references missing account: " + split
));
continue;
}
split.setId(null);
split.setAccountId(newAccountId);
}
if (errors.addAll(entry.validate(Validatable.GROUP_SERVER))) {
break;
}
entry.setId(null);
getEntryDAO().persist(entry);
}
}
}