001/*
002 * The Kuali Financial System, a comprehensive financial management system for higher education.
003 * 
004 * Copyright 2005-2014 The Kuali Foundation
005 * 
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Affero General Public License as
008 * published by the Free Software Foundation, either version 3 of the
009 * License, or (at your option) any later version.
010 * 
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU Affero General Public License for more details.
015 * 
016 * You should have received a copy of the GNU Affero General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.kuali.kfs.sys;
020
021import java.text.Collator;
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import junit.framework.TestCase;
028
029import org.apache.commons.beanutils.PropertyUtils;
030import org.kuali.kfs.coa.businessobject.Account;
031import org.kuali.kfs.sys.DynamicCollectionComparator.SortOrder;
032import org.kuali.kfs.sys.fixture.AccountFixture;
033
034public class DynamicCollectionComparatorTest extends TestCase {
035
036    // the default sort order is ascending
037    public void testSort_DefaultOrder() throws Exception {
038        List<Account> accounts = this.getAccounts();
039        String[] fieldNames = { KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE };
040
041        DynamicCollectionComparator.sort(accounts, fieldNames);
042        assertTrue(this.isSortedByAscendingOrder(accounts, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE));
043    }
044
045    // test if the given list of objects can be sorted by ascending order
046    public void testSort_Ascending() throws Exception {
047        List<Account> accounts = this.getAccounts();
048        String[] fieldNames = { KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE };
049
050        DynamicCollectionComparator.sort(accounts, SortOrder.ASC, fieldNames);
051        assertTrue(this.isSortedByAscendingOrder(accounts, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE));
052    }
053
054    // test if the given list of objects can be sorted by descending order
055    public void testSort_Descending() throws Exception {
056        List<Account> accounts = this.getAccounts();
057        String[] fieldNames = { KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE };
058
059        DynamicCollectionComparator.sort(accounts, SortOrder.DESC, fieldNames);
060        assertTrue(this.isSortedByDescendingOrder(accounts, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE));
061    }
062
063    // test if the given list of objects can be sorted by ascending order
064    public void testSort_ByMultipleFields_Ascending() throws Exception {
065        List<Account> accounts = this.getAccounts();
066        String[] fieldNames = { KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, KFSPropertyConstants.ACCOUNT_NUMBER };
067
068        DynamicCollectionComparator.sort(accounts, SortOrder.ASC, fieldNames);
069
070        Map<String, List<Account>> accountMap = this.groupAccounts(accounts);
071        for (String key : accountMap.keySet()) {
072            assertTrue(this.isSortedByAscendingOrder(accountMap.get(key), KFSPropertyConstants.ACCOUNT_NUMBER));
073        }
074    }
075
076    // test if the given list of objects can be sorted by descending order
077    public void testSort_ByMultipleFields_Descending() throws Exception {
078        List<Account> accounts = this.getAccounts();
079        String[] fieldNames = { KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, KFSPropertyConstants.ACCOUNT_NUMBER };
080
081        DynamicCollectionComparator.sort(accounts, SortOrder.DESC, fieldNames);
082
083        Map<String, List<Account>> accountMap = this.groupAccounts(accounts);
084        for (String key : accountMap.keySet()) {
085            assertTrue(this.isSortedByDescendingOrder(accountMap.get(key), KFSPropertyConstants.ACCOUNT_NUMBER));
086        }
087    }
088
089    // create a list of accounts that will be posted in report
090    private List<Account> getAccounts() {
091        List<Account> accounts = new ArrayList<Account>();
092        for (AccountFixture account : AccountFixture.values()) {
093            accounts.add(account.createAccount());
094        }
095        return accounts;
096    }
097
098    // group the given accounts with chart accounts code
099    private Map<String, List<Account>> groupAccounts(List<Account> accounts) {
100        Map<String, List<Account>> accountMap = new HashMap<String, List<Account>>();
101        for (Account account : accounts) {
102            String chartOfAccountsCode = account.getChartOfAccountsCode();
103            if (accountMap.containsKey(chartOfAccountsCode)) {
104                List<Account> accountList = accountMap.get(chartOfAccountsCode);
105                accountList.add(account);
106            }
107            else {
108                List<Account> accountList = new ArrayList<Account>();
109                accountList.add(account);
110                accountMap.put(chartOfAccountsCode, accountList);
111            }
112        }
113        return accountMap;
114    }
115
116    // determine whether the given object list has been sorted by the specified field by ascending order
117    private <T> boolean isSortedByAscendingOrder(List<T> objectList, String fieldName) throws Exception {
118        Collator collator = Collator.getInstance();
119        Object tempValue = null;
120        for (T object : objectList) {
121            Object fieldValue = PropertyUtils.getProperty(object, fieldName);
122
123            if (tempValue == null || collator.compare(tempValue, fieldValue) <= 0) {
124                tempValue = fieldValue;
125            }
126            else {
127                return false;
128            }
129        }
130        return true;
131    }
132
133    // determine whether the given object list has been sorted by the specified field by ascending order
134    private <T> boolean isSortedByDescendingOrder(List<T> objectList, String fieldName) throws Exception {
135        Collator collator = Collator.getInstance();
136        Object tempValue = null;
137
138        int count = 0;
139        for (T object : objectList) {
140            Object fieldValue = PropertyUtils.getProperty(object, fieldName);
141
142            if (count == 0) {
143                tempValue = fieldValue;
144                count++;
145            }
146            else if (tempValue == null && fieldValue == null) {
147                tempValue = fieldValue;
148            }
149            else if (tempValue == null) {
150                return false;
151            }
152            else if (fieldValue == null) {
153                tempValue = fieldValue;
154            }
155            else if (collator.compare(tempValue, fieldValue) >= 0) {
156                tempValue = fieldValue;
157            }
158            else {
159                return false;
160            }
161        }
162
163        return true;
164    }
165    
166}