// AutoCompleteHandler
package org.javamoney.examples.ez.money.gui.view.register;
import static org.javamoney.examples.ez.money.ApplicationThread.getFrame;
import static org.javamoney.examples.ez.money.KeywordKeys.NOT_CATEGORIZED;
import static org.javamoney.examples.ez.money.model.DataManager.getExpenses;
import static org.javamoney.examples.ez.money.model.DataManager.getIncome;
import static org.javamoney.examples.ez.money.model.dynamic.transaction.TransactionTypeKeys.INCOME;
import static org.javamoney.examples.ez.money.utility.TransactionHelper.isIncome;
import static org.javamoney.examples.ez.money.utility.TransactionHelper.isSplit;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import org.javamoney.examples.ez.money.gui.view.RegisterView;
import org.javamoney.examples.ez.money.gui.view.ViewKeys;
import org.javamoney.examples.ez.money.model.DataElement;
import org.javamoney.examples.ez.money.model.dynamic.transaction.TransactionTypeKeys;
import org.javamoney.examples.ez.money.model.persisted.category.Category;
import org.javamoney.examples.ez.money.model.persisted.transaction.Transaction;
import org.javamoney.examples.ez.common.gui.ComboBox;
import org.javamoney.examples.ez.common.utility.ComboBoxCompleter;
/**
* This class facilitates auto-completing payees as they are being typed, and
* selecting categories for those payees based on frequency.
*/
final
class
AutoCompleteHandler
{
/**
* Constructs a new handler that will reference the specified form.
*
* @param form The form to reference.
*/
protected
AutoCompleteHandler(Form form)
{
setForm(form);
ComboBox comboBox = form.getPayFromChooser();
// Add listeners.
comboBox.addPopupMenuListener(new MenuHandler());
comboBox.getTextField().addKeyListener(new KeyHandler());
comboBox.getTextField().addFocusListener(new FocusHandler());
new ComboBoxCompleter(comboBox);
}
//////////////////////////////////////////////////////////////////////////////
// Start of private methods.
//////////////////////////////////////////////////////////////////////////////
private
void
buildFrequencyMap(Map<String, Integer> map, Collection<DataElement> collection)
{
for(DataElement element : collection)
{
Category category = (Category)element;
map.put(category.getQIFName(), new Integer(0));
if(category.isGroup() == true)
{
buildFrequencyMap(map, category.getSubcategories());
}
}
}
private
boolean
canAutoComplete()
{
String category = getForm().getPayToChooser().getSelectedItem();
String payee = getForm().getPayFrom();
boolean result = false;
if(payee.length() != 0 && category.equals(NOT_CATEGORIZED.toString()) == true)
{
result = true;
}
return result;
}
private
Map<String, Integer>
createFrequencyMap()
{
Map<String, Integer> frequencyMap = new HashMap<String, Integer>();
String payee = getForm().getPayFrom();
boolean isIncome = getForm().getType() == TransactionTypeKeys.INCOME;
// Build the map.
buildFrequencyMap(frequencyMap, getCategoryCollection(getForm().getType()));
// Find the frequencies.
for(Transaction trans : getRegisterView().getAccount().getTransactions())
{
if(trans.getPayee().equals(payee) == true && isIncome == isIncome(trans))
{
if(trans.getCategory().length() != 0 && isSplit(trans) == false)
{
Integer count = frequencyMap.get(trans.getCategory());
if(count == null)
{
frequencyMap.put(trans.getCategory(), new Integer(0));
}
else
{
frequencyMap.put(trans.getCategory(), new Integer(count.intValue() + 1));
}
}
}
}
return frequencyMap;
}
private
void
doAutoComplete()
{
Map<String, Integer> frequencies = createFrequencyMap();
String mostFrequent = null;
int max = 0;
for(Map.Entry<String, Integer> entry : frequencies.entrySet())
{
if(max < entry.getValue().intValue())
{
max = entry.getValue().intValue();
mostFrequent = entry.getKey();
}
}
if(max != 0 && mostFrequent != null)
{
getForm().getPayToChooser().setSelectedItem(mostFrequent);
}
}
private
Collection<DataElement>
getCategoryCollection(TransactionTypeKeys key)
{
Collection<DataElement> collection = null;
if(key == INCOME)
{
collection = getIncome().getCollection();
}
else
{
collection = getExpenses().getCollection();
}
return collection;
}
private
Form
getForm()
{
return itsForm;
}
private
RegisterView
getRegisterView()
{
return (RegisterView)getFrame().getViews().getView(ViewKeys.REGISTER);
}
private
void
setForm(Form panel)
{
itsForm = panel;
}
//////////////////////////////////////////////////////////////////////////////
// Start of inner classes.
//////////////////////////////////////////////////////////////////////////////
private
class
FocusHandler
extends FocusAdapter
{
@Override
public
void
focusLost(FocusEvent event)
{
if(canAutoComplete() == true)
{
doAutoComplete();
}
}
}
private
class
KeyHandler
extends KeyAdapter
{
@Override
public
void
keyReleased(KeyEvent event)
{
if(event.getKeyChar() == KeyEvent.VK_ENTER && canAutoComplete() == true)
{
doAutoComplete();
}
}
}
private
class
MenuHandler
implements PopupMenuListener
{
public
void
popupMenuCanceled(PopupMenuEvent event)
{
// Ignored.
}
public
void
popupMenuWillBecomeInvisible(PopupMenuEvent event)
{
if(canAutoComplete() == true)
{
doAutoComplete();
}
}
public
void
popupMenuWillBecomeVisible(PopupMenuEvent event)
{
// Ignored.
}
}
//////////////////////////////////////////////////////////////////////////////
// Start of class members.
//////////////////////////////////////////////////////////////////////////////
private Form itsForm;
}