/*
* Copyright (c) 2014 - 2015 Ngewi Fet <ngewif@gmail.com>
* Copyright (c) 2014 Yongxin Wang <fefe.wyx@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gnucash.android.export.xml;
import org.gnucash.android.model.Commodity;
import org.gnucash.android.ui.transaction.TransactionFormFragment;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Collection of helper tags and methods for Gnc XML export
*
* @author Ngewi Fet <ngewif@gmail.com>
* @author Yongxin Wang <fefe.wyx@gmail.com>
*/
public abstract class GncXmlHelper {
public static final String TAG_GNC_PREFIX = "gnc:";
public static final String ATTR_KEY_CD_TYPE = "cd:type";
public static final String ATTR_KEY_TYPE = "type";
public static final String ATTR_KEY_VERSION = "version";
public static final String ATTR_VALUE_STRING = "string";
public static final String ATTR_VALUE_NUMERIC = "numeric";
public static final String ATTR_VALUE_GUID = "guid";
public static final String ATTR_VALUE_BOOK = "book";
public static final String ATTR_VALUE_FRAME = "frame";
public static final String TAG_GDATE = "gdate";
/*
Qualified GnuCash XML tag names
*/
public static final String TAG_ROOT = "gnc-v2";
public static final String TAG_BOOK = "gnc:book";
public static final String TAG_BOOK_ID = "book:id";
public static final String TAG_COUNT_DATA = "gnc:count-data";
public static final String TAG_COMMODITY = "gnc:commodity";
public static final String TAG_COMMODITY_ID = "cmdty:id";
public static final String TAG_COMMODITY_SPACE = "cmdty:space";
public static final String TAG_ACCOUNT = "gnc:account";
public static final String TAG_ACCT_NAME = "act:name";
public static final String TAG_ACCT_ID = "act:id";
public static final String TAG_ACCT_TYPE = "act:type";
public static final String TAG_ACCT_COMMODITY = "act:commodity";
public static final String TAG_COMMODITY_SCU = "act:commodity-scu";
public static final String TAG_PARENT_UID = "act:parent";
public static final String TAG_SLOT_KEY = "slot:key";
public static final String TAG_SLOT_VALUE = "slot:value";
public static final String TAG_ACCT_SLOTS = "act:slots";
public static final String TAG_SLOT = "slot";
public static final String TAG_ACCT_DESCRIPTION = "act:description";
public static final String TAG_TRANSACTION = "gnc:transaction";
public static final String TAG_TRX_ID = "trn:id";
public static final String TAG_TRX_CURRENCY = "trn:currency";
public static final String TAG_DATE_POSTED = "trn:date-posted";
public static final String TAG_TS_DATE = "ts:date";
public static final String TAG_DATE_ENTERED = "trn:date-entered";
public static final String TAG_TRN_DESCRIPTION = "trn:description";
public static final String TAG_TRN_SPLITS = "trn:splits";
public static final String TAG_TRN_SPLIT = "trn:split";
public static final String TAG_TRN_SLOTS = "trn:slots";
public static final String TAG_TEMPLATE_TRANSACTIONS = "gnc:template-transactions";
public static final String TAG_SPLIT_ID = "split:id";
public static final String TAG_SPLIT_MEMO = "split:memo";
public static final String TAG_RECONCILED_STATE = "split:reconciled-state";
public static final String TAG_RECONCILED_DATE = "split:recondiled-date";
public static final String TAG_SPLIT_ACCOUNT = "split:account";
public static final String TAG_SPLIT_VALUE = "split:value";
public static final String TAG_SPLIT_QUANTITY = "split:quantity";
public static final String TAG_SPLIT_SLOTS = "split:slots";
public static final String TAG_PRICEDB = "gnc:pricedb";
public static final String TAG_PRICE = "price";
public static final String TAG_PRICE_ID = "price:id";
public static final String TAG_PRICE_COMMODITY = "price:commodity";
public static final String TAG_PRICE_CURRENCY = "price:currency";
public static final String TAG_PRICE_TIME = "price:time";
public static final String TAG_PRICE_SOURCE = "price:source";
public static final String TAG_PRICE_TYPE = "price:type";
public static final String TAG_PRICE_VALUE = "price:value";
/**
* Periodicity of the recurrence.
* <p>Only currently used for reading old backup files. May be removed in the future. </p>
* @deprecated Use {@link #TAG_GNC_RECURRENCE} instead
*/
@Deprecated
public static final String TAG_RECURRENCE_PERIOD = "trn:recurrence_period";
public static final String TAG_SCHEDULED_ACTION = "gnc:schedxaction";
public static final String TAG_SX_ID = "sx:id";
public static final String TAG_SX_NAME = "sx:name";
public static final String TAG_SX_ENABLED = "sx:enabled";
public static final String TAG_SX_AUTO_CREATE = "sx:autoCreate";
public static final String TAG_SX_AUTO_CREATE_NOTIFY = "sx:autoCreateNotify";
public static final String TAG_SX_ADVANCE_CREATE_DAYS = "sx:advanceCreateDays";
public static final String TAG_SX_ADVANCE_REMIND_DAYS = "sx:advanceRemindDays";
public static final String TAG_SX_INSTANCE_COUNT = "sx:instanceCount";
public static final String TAG_SX_START = "sx:start";
public static final String TAG_SX_LAST = "sx:last";
public static final String TAG_SX_END = "sx:end";
public static final String TAG_SX_NUM_OCCUR = "sx:num-occur";
public static final String TAG_SX_REM_OCCUR = "sx:rem-occur";
public static final String TAG_SX_TAG = "sx:tag";
public static final String TAG_SX_TEMPL_ACCOUNT = "sx:templ-acct";
public static final String TAG_SX_SCHEDULE = "sx:schedule";
public static final String TAG_GNC_RECURRENCE = "gnc:recurrence";
public static final String TAG_RX_MULT = "recurrence:mult";
public static final String TAG_RX_PERIOD_TYPE = "recurrence:period_type";
public static final String TAG_RX_START = "recurrence:start";
public static final String TAG_BUDGET = "gnc:budget";
public static final String TAG_BUDGET_ID = "bgt:id";
public static final String TAG_BUDGET_NAME = "bgt:name";
public static final String TAG_BUDGET_DESCRIPTION = "bgt:description";
public static final String TAG_BUDGET_NUM_PERIODS = "bgt:num-periods";
public static final String TAG_BUDGET_RECURRENCE = "bgt:recurrence";
public static final String TAG_BUDGET_SLOTS = "bgt:slots";
public static final String RECURRENCE_VERSION = "1.0.0";
public static final String BOOK_VERSION = "2.0.0";
public static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US);
public static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
public static final String KEY_PLACEHOLDER = "placeholder";
public static final String KEY_COLOR = "color";
public static final String KEY_FAVORITE = "favorite";
public static final String KEY_NOTES = "notes";
public static final String KEY_EXPORTED = "exported";
public static final String KEY_SCHEDX_ACTION = "sched-xaction";
public static final String KEY_SPLIT_ACCOUNT_SLOT = "account";
public static final String KEY_DEBIT_FORMULA = "debit-formula";
public static final String KEY_CREDIT_FORMULA = "credit-formula";
public static final String KEY_DEBIT_NUMERIC = "debit-numeric";
public static final String KEY_CREDIT_NUMERIC = "credit-numeric";
public static final String KEY_FROM_SCHED_ACTION = "from-sched-xaction";
public static final String KEY_DEFAULT_TRANSFER_ACCOUNT = "default_transfer_account";
/**
* Formats dates for the GnuCash XML format
* @param milliseconds Milliseconds since epoch
*/
public static String formatDate(long milliseconds){
return TIME_FORMATTER.format(new Date(milliseconds));
}
/**
* Parses a date string formatted in the format "yyyy-MM-dd HH:mm:ss Z"
* @param dateString String date representation
* @return Time in milliseconds since epoch
* @throws ParseException if the date string could not be parsed e.g. because of different format
*/
public static long parseDate(String dateString) throws ParseException {
Date date = TIME_FORMATTER.parse(dateString);
return date.getTime();
}
/**
* Parses amount strings from GnuCash XML into {@link java.math.BigDecimal}s.
* The amounts are formatted as 12345/100
* @param amountString String containing the amount
* @return BigDecimal with numerical value
* @throws ParseException if the amount could not be parsed
*/
public static BigDecimal parseSplitAmount(String amountString) throws ParseException {
int pos = amountString.indexOf("/");
if (pos < 0)
{
throw new ParseException("Cannot parse money string : " + amountString, 0);
}
int scale = amountString.length() - pos - 2; //do this before, because we could modify the string
//String numerator = TransactionFormFragment.stripCurrencyFormatting(amountString.substring(0, pos));
String numerator = amountString.substring(0,pos);
numerator = TransactionFormFragment.stripCurrencyFormatting(numerator);
BigInteger numeratorInt = new BigInteger(numerator);
return new BigDecimal(numeratorInt, scale);
}
/**
* Formats money amounts for splits in the format 2550/100
* @param amount Split amount as BigDecimal
* @param commodity Commodity of the transaction
* @return Formatted split amount
* @deprecated Just use the values for numerator and denominator which are saved in the database
*/
public static String formatSplitAmount(BigDecimal amount, Commodity commodity){
int denomInt = commodity.getSmallestFraction();
BigDecimal denom = new BigDecimal(denomInt);
String denomString = Integer.toString(denomInt);
String numerator = TransactionFormFragment.stripCurrencyFormatting(amount.multiply(denom).stripTrailingZeros().toPlainString());
return numerator + "/" + denomString;
}
/**
* Format the amount in template transaction splits.
* <p>GnuCash desktop always formats with a locale dependent format, and that varies per user.<br>
* So we will use the device locale here and hope that the user has the same locale on the desktop GnuCash</p>
* @param amount Amount to be formatted
* @return String representation of amount
*/
public static String formatTemplateSplitAmount(BigDecimal amount){
//TODO: If we ever implement an application-specific locale setting, use it here as well
return NumberFormat.getNumberInstance().format(amount);
}
}