/* * Copyright 2014 Qianqian Zhu <zhuqianqian.299@gmail.com> All rights reserved. * * 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 com.z299studio.pb; import java.text.Collator; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Hashtable; import java.util.Locale; public class AccountManager { class EntryType { public static final int SINGLETEXT = 1; public static final int PASSWORD = 2; public static final int WEBADDR = 3; public static final int EMAILADDR = 4; public static final int PIN = 5; } private static final String FIELD_DELIMITER = "\t"; private static final String ITEM_DELIMITER = "\0"; private static final String ENTRY_DELIMITER = "\0\0"; public static final int DEFAULT_CATEGORY_ID = 0; public static final int ALL_CATEGORY_ID = -1; public class Category { int mId; int mImgCode; String mName; public Category(int id, int imgCode, String name) { mId = id; mImgCode = imgCode; mName = name; } } public class Account { class Entry { int mType; String mName; String mValue; Entry(int type, String name, String value) { mType = type; mName = name; mValue = value; } } private int mCategoryId; public String mProfile; private ArrayList<Entry> mEntries; public int mId; public Account(int categoryId) { mCategoryId = categoryId; mEntries = new ArrayList<> (); } public Account(String accountData) { mEntries = new ArrayList<>(); setAccountData(accountData); } String getAccountName() { return mProfile; } public int getCategoryId() { return mCategoryId; } public Account clone() { Account account = new Account(this.mCategoryId); account.mProfile = this.mProfile; account.mId = this.mId; for(Entry entry : this.mEntries) { account.mEntries.add(new Entry(entry.mType, entry.mName, entry.mValue)); } return account; } void setAccountData(String accountData) { String[] entrylist = accountData.split(ITEM_DELIMITER); String[] items; items = entrylist[0].split(FIELD_DELIMITER, 2); mCategoryId = Integer.parseInt(items[0]); mProfile = items[1]; for(int i = 1; i < entrylist.length; ++i) { items = entrylist[i].split(FIELD_DELIMITER, 3); Entry entry = new Entry(Integer.parseInt(items[0]), items[1], items[2]); mEntries.add(entry); } } ArrayList<Entry> getEntryList() { return mEntries; } public void setAccount(Account account) { mEntries.clear(); this.mProfile = account.mProfile; for(Entry e : account.mEntries) { this.mEntries.add(new Entry(e.mType, e.mName, e.mValue)); } } int addEntry(Entry entry) { if(mEntries == null) { mEntries = new ArrayList<> (); } mEntries.add(entry); return 0; } int addEntry(int type, String name, String value) { Entry entry = new Entry(type, name, value); mEntries.add(entry); return 0; } public ArrayList<Entry> getAccount() { return mEntries; } public void setCategory(int newCategoryId) { mCategoryId = newCategoryId; } public void setName(String name) { mProfile = name; } void clearEntries() { mEntries.clear(); } byte[] getBytes() { String ret; ret = String.format(Locale.ENGLISH, "%d%s%s\0", mCategoryId, FIELD_DELIMITER, mProfile); for(Entry e : mEntries) { ret += String.format(Locale.ENGLISH,"%d%s%s%s%s\0", e.mType, FIELD_DELIMITER, e.mName, FIELD_DELIMITER, e.mValue); } ret += "\0"; return ret.getBytes(); } Entry newEntry(String name, String value, int type) { return new Entry(type, name, value); } String[] getStringList(AccountManager am) { String[] result = new String[mEntries.size()+1]; int i = 1; result[0] = String.format("%s\t%s", am.getCategory(this.mCategoryId).mName, mProfile); for(Entry e : mEntries) { result[i++] = String.format(Locale.ENGLISH,"%d\t%s\t%s", e.mType, e.mName, e.mValue); } return result; } } private Hashtable<Integer, Category> mCategories; private ArrayList<Account> mAccounts; private Hashtable<Integer, ArrayList<Integer>> mMap; private boolean mChanged = false; private int mNullCount = 0; private static final Collator COLLATOR = Collator.getInstance(Locale.getDefault()); private static final Comparator<Account> ACC_COMPARATOR = new Comparator<Account>() { @Override public int compare(Account arg0, Account arg1) { return COLLATOR.compare(arg0.mProfile, arg1.mProfile); } }; public AccountManager(String data) { mCategories = new Hashtable<> (); mMap = new Hashtable<>(); mAccounts = new ArrayList<>(); if(data!=null) { setData(data); } } void setDefaultCategory(int imgCode, String name) { if(mCategories!=null) { mCategories.put(DEFAULT_CATEGORY_ID, new Category(DEFAULT_CATEGORY_ID, imgCode, name)); ArrayList<Integer> intList = mMap.get(0); if(intList==null) { intList = new ArrayList<>(); mMap.put(0, intList); } } } public void setData(String data) { String [] accountList = data.split(ENTRY_DELIMITER); String [] tmp = accountList[0].split(ITEM_DELIMITER); String [] details; Integer key; ArrayList<Integer> intList; int i, pos, begin = 1; for(i = 0; i < tmp.length; ++i) { details = tmp[i].split(FIELD_DELIMITER, 3); if(details.length < 3) { begin = 0; break; } mCategories.put(Integer.valueOf(details[0]), new Category(Integer.parseInt(details[0]), Integer.parseInt(details[1]), details[2])); } Account account; for(i = begin, pos = 0; i < accountList.length; ++i, ++pos) { tmp = accountList[i].split(FIELD_DELIMITER, 2); if(tmp.length < 2) { break; } key = Integer.parseInt(tmp[0]); intList = mMap.get(key); if(intList == null) { intList = new ArrayList<> (); intList.add(pos); mMap.put(key, intList); } else { intList.add(pos); } account = new Account(accountList[i]); account.mId = pos; mAccounts.add(account); } } ArrayList<Category> getCategoryList(boolean includeDefault, boolean sort) { @SuppressWarnings("unchecked") Hashtable<Integer, Category> categories = (Hashtable<Integer, Category>) mCategories.clone(); if(!includeDefault) { categories.remove(0); } ArrayList<Category> result = new ArrayList<>(categories.values()); if(sort) { Collections.sort(result, new Comparator<Category>() { @Override public int compare(Category arg0, Category arg1) { return COLLATOR.compare(arg0.mName, arg1.mName); } }); } return result; } int getAccountsCountByCategory(int id) { int size=0; if(id == ALL_CATEGORY_ID) { return (mAccounts.size() - mNullCount); } ArrayList<Integer> intList = mMap.get(id); if(intList==null) { return 0; } if(mNullCount > 0) { Account a; for(Integer i : intList) { a = mAccounts.get(i); if(a!=null) { size++; } } } else { size = intList.size(); } return size; } ArrayList<Account> getAccountsByCategory(int categoryId) { if(categoryId == ALL_CATEGORY_ID) { return getAllAccounts(true); } ArrayList<Integer> intList = mMap.get(categoryId); ArrayList<Account> accounts = new ArrayList<>(); Account a; if(intList == null) { return null; } for(Integer i : intList) { a = mAccounts.get(i); if(a!=null) { accounts.add(a); } } Collections.sort(accounts, ACC_COMPARATOR); return accounts; } ArrayList<Account> getAllAccounts(boolean sort) { ArrayList<Account> copyOfAccounts = new ArrayList<>(); for(Account account : mAccounts) { if(account!=null) { copyOfAccounts.add(account); } } if(sort) { Collections.sort(copyOfAccounts, ACC_COMPARATOR); } return copyOfAccounts; } private byte[] getCategoryBytes() { ArrayList<Category> categories = getCategoryList(false, false); String ret = ""; if(categories.size() > 0) { for(Category c : categories) { ret += String.format(Locale.ENGLISH, "%d%s%d%s%s\0", c.mId, FIELD_DELIMITER,c.mImgCode, FIELD_DELIMITER, c.mName); } ret += ITEM_DELIMITER; } return ret.getBytes(); } private ArrayList<byte[]> getAccountBytesList() { ArrayList<byte[]> bytesList = new ArrayList<>(); ArrayList<Account> accounts = getAllAccounts(false); for(Account a : accounts) { if(a!=null) { bytesList.add(a.getBytes()); } } return bytesList; } byte[] getBytes() { byte[] categoryBytes = getCategoryBytes(); ArrayList<byte[]> accountsBytes = getAccountBytesList(); byte[] retBytes; int size = categoryBytes.length; for(byte[] b : accountsBytes) { size += b.length; } retBytes = new byte[size]; System.arraycopy(categoryBytes, 0, retBytes, 0, categoryBytes.length); size = categoryBytes.length; for(byte[] b : accountsBytes) { System.arraycopy(b, 0, retBytes, size, b.length); size += b.length; } return retBytes; } Category getCategory(int categoryId) { return mCategories.get(categoryId); } void addAccount(int categoryId, Account account) { account.mId = mAccounts.size(); account.mCategoryId = categoryId; mAccounts.add(account); ArrayList<Integer> intList = mMap.get(categoryId); if(intList==null) { intList = new ArrayList<>(); intList.add(account.mId); mMap.put(categoryId, intList); } else { intList.add(account.mId); } mChanged = true; } Account getAccountById(int id) { return mAccounts.get(id); } int addCategory(int imgCode, String name) { int id = mCategories.size(); if(id == 0) { id = 1; } while(mCategories.get(id)!=null) { id++; } mCategories.put(id, new Category(id, imgCode, name)); mChanged = true; return id; } void removeCategory(int id, boolean removeAccounts) { if(id < 1) { return; } mCategories.remove(id); Account account; ArrayList<Integer> intListi = mMap.get(id); if(intListi!=null) { if(removeAccounts) { for(Integer i : intListi) { mAccounts.set(i, null); mNullCount++; } } else { ArrayList<Integer> intList0 = mMap.get(0); for(Integer i : intListi) { account = mAccounts.get(i); account.mCategoryId = 0; intList0.add(i); } } } mMap.remove(id); mChanged = true; } Account getTemplate(int categoryId) { Account result = null; Account template; ArrayList<Integer> intList = mMap.get(categoryId); if(intList!=null && intList.size() > 0) { template = mAccounts.get(intList.get(0)); result = new Account(template.mCategoryId); result.mProfile = template.mProfile; for(Account.Entry entry : template.mEntries) { result.addEntry(entry.mType, entry.mName, ""); } } return result; } void removeAccount(Account account) { mAccounts.set(account.mId, null); ArrayList<Integer> intList = mMap.get(account.mCategoryId); intList.remove(Integer.valueOf(account.mId)); mChanged = true; mNullCount += 1; } public void setAccount(Account account) { Account previous = getAccountById(account.mId); if(previous.mCategoryId != account.mCategoryId) { ArrayList<Integer> intList = mMap.get(previous.mCategoryId); intList.remove(Integer.valueOf(account.mId)); ArrayList<Integer> target = mMap.get(account.mCategoryId); if(target == null) { target = new ArrayList<>(); mMap.put(account.mCategoryId, target); } target.add(account.mId); } mAccounts.set(account.mId, account); mChanged = true; } void moveAccount(int destCategory, Account account) { ArrayList<Integer> intList = mMap.get(account.mCategoryId); intList.remove(Integer.valueOf(account.mId)); account.setCategory(destCategory); ArrayList<Integer> target = mMap.get(destCategory); if(target == null) { target = new ArrayList<>(); mMap.put(destCategory, target); } target.add(account.mId); mChanged = true; } boolean setCategory(int id, String name, int imgCode) { Category category = getCategory(id); if(category.mName.equals(name) && category.mImgCode == imgCode) { return false; } category.mName = name; category.mImgCode = imgCode; mChanged = true; return true; } Account newAccount(int categoryId) { return new Account(categoryId); } boolean saveRequired() { return mChanged; } void onSaved() { mChanged = false; } String[] getCategoryNames() { Collection<Category> categories = mCategories.values(); String[] result = new String[categories.size()]; int i = 0; for(Category c : categories) { result[i++] = c.mName; } return result; } }