package edu.brown.oltpgenerator.gui.common.RandomDistribution;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.voltdb.VoltType;
import org.voltdb.catalog.CatalogType;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.ProcParameter;
import edu.brown.oltpgenerator.env.RandomDistribution.DateDistribution;
import edu.brown.oltpgenerator.env.RandomDistribution.NumericDistributionFactory;
import edu.brown.oltpgenerator.env.RandomDistribution.RandomDistribution;
import edu.brown.oltpgenerator.env.RandomDistribution.RandomDistributionEnv;
import edu.brown.oltpgenerator.env.RandomDistribution.StringDistribution;
import edu.brown.oltpgenerator.exception.ColumnEditParsingException;
import edu.brown.oltpgenerator.gui.common.Notifier;
public enum RandomDistributionEditor {
NUMBER_EDITOR(new RandomDistributionEditorRenderer()
{
private JPanel m_paneDistributionParams = new JPanel();
@Override
protected JPanel createEditor()
{
JPanel ret = new JPanel();
ret.setLayout(new BoxLayout(ret, BoxLayout.PAGE_AXIS));
JButton button = new JButton("Confirm");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
NumberDistribution nd = NumberDistribution.getSelectedDistribution();
if (nd == null)
{
return;
}
try
{
Map<String, Object> map = parseEditor();
RandomDistribution property = NumericDistributionFactory
.createNumberColumnEditProperty(nd, map);
RandomDistributionEnv.put(s_valSelected, property);
}
catch (Exception e1)
{
showMsg(e1.getMessage(), false);
}
}
});
ret.add(button);
ret.add(createDistributionArea());
ret.add(m_paneDistributionParams);
return ret;
}
private JPanel createDistributionArea()
{
NumberDistribution.groupSelectors();
NumberDistribution.listenForSelection(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
NumberDistribution distr = NumberDistribution.dispatch(e.getActionCommand());
distr.m_renderer.updateEditor(RandomDistributionEnv.get(s_valSelected));
JPanel paneParams = distr.m_renderer.getEditor();
paneParams.setBorder(BorderFactory.createTitledBorder("Distribution Parameters"));
paneParams.updateUI();
if (m_paneDistributionParams.getComponentCount() > 0)
{
assert (m_paneDistributionParams.getComponentCount() == 1);
m_paneDistributionParams.remove(0);
}
m_paneDistributionParams.add(paneParams);
m_paneDistributionParams.updateUI();
}
});
return NumberDistribution.createButtonPane();
}
@Override
public void updateEditor(RandomDistribution property)
{
if (null == property)
{
NumberDistribution.selectNone();
// removing distribution parameter pane
if (m_paneDistributionParams.getComponentCount() == 1)
{
m_paneDistributionParams.remove(0);
m_paneDistributionParams.updateUI();
}
}
else
{
Map<String, Object> propertyMap = property.getUserInputMap();
String sSelected = (String) propertyMap.get(RandomDistributionKey.SELECTED_DISTRIBUTION.name());
NumberDistribution dist = NumberDistribution.dispatch(sSelected);
dist.m_btSelecter.setSelected(true);
// update and add distribution parameter pane
dist.m_renderer.updateEditor(property);
// remove existing distribution parameter pane
if (m_paneDistributionParams.getComponentCount() == 1)
{
m_paneDistributionParams.remove(0);
m_paneDistributionParams.updateUI();
}
m_paneDistributionParams.add(dist.m_renderer.getEditor());
m_paneDistributionParams.updateUI();
}
}
@Override
public Map<String, Object> parseEditor() throws Exception
{
NumberDistribution selected = NumberDistribution.getSelectedDistribution();
if (selected == null)
{
return null;
}
Map<String, Object> ret = selected.m_renderer.parseEditor();
ret.put(RandomDistributionKey.SELECTED_DISTRIBUTION.name(), selected.m_sName);
return ret;
}
}),
STRING_EDITOR(new RandomDistributionEditorRenderer()
{
private JTextField m_txtMin = new JTextField(5);
private JTextField m_txtMax = new JTextField(5);
@Override
protected JPanel createEditor()
{
JPanel ret = new JPanel();
ret.setLayout(new BoxLayout(ret, BoxLayout.PAGE_AXIS));
ret.add(createDataRangeArea());
JButton button = new JButton("Confirm");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
Map<String, Object> map = parseEditor();
RandomDistribution property = new StringDistribution(map);
RandomDistributionEnv.put(s_valSelected, property);
}
catch (Exception e1)
{
showMsg(e1.getMessage(), false);
}
}
});
ret.add(button);
return ret;
}
private JPanel createDataRangeArea()
{
JPanel ret = new JPanel(new FlowLayout());
ret.add(new JLabel("Min: "));
ret.add(m_txtMin);
ret.add(new JLabel("Max: "));
ret.add(m_txtMax);
ret.setBorder(BorderFactory.createTitledBorder("String length range"));
return ret;
}
@Override
public void updateEditor(RandomDistribution property)
{
if (property == null)
{
m_txtMin.setText(null);
m_txtMax.setText(null);
}
else
{
m_txtMin.setText(property.getUserInput(RandomDistributionKey.MIN.name()).toString());
m_txtMax.setText(property.getUserInput(RandomDistributionKey.MAX.name()).toString());
}
}
@Override
public Map<String, Object> parseEditor() throws Exception
{
Map<String, Object> ret = new HashMap<String, Object>();
Integer nMin = Double.valueOf(m_txtMin.getText()).intValue();
Integer nMax = Double.valueOf(m_txtMax.getText()).intValue();
if (nMin >= nMax)
{
throw new ColumnEditParsingException("Min value should be less than Max value");
}
ret.put(RandomDistributionKey.MIN.name(), nMin);
ret.put(RandomDistributionKey.MAX.name(), nMax);
return ret;
}
}),
DATE_EDITOR(new RandomDistributionEditorRenderer()
{
private JTextField m_txtMin = new JTextField(10);
private JTextField m_txtMax = new JTextField(10);
private DateFormat m_format = new SimpleDateFormat("MM/dd/yyyy");
@Override
protected JPanel createEditor()
{
JPanel ret = new JPanel();
ret.setLayout(new BoxLayout(ret, BoxLayout.PAGE_AXIS));
ret.add(createDataRangeArea());
JButton button = new JButton("Confirm");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
Map<String, Object> map = parseEditor();
RandomDistribution property = new DateDistribution(map);
RandomDistributionEnv.put(s_valSelected, property);
}
catch (Exception e1)
{
showMsg(e1.getMessage(), false);
}
}
});
ret.add(button);
return ret;
}
private Component createDataRangeArea()
{
JPanel ret = new JPanel(new FlowLayout());
ret.add(new JLabel("Min: "));
ret.add(m_txtMin);
ret.add(new JLabel("Max: "));
ret.add(m_txtMax);
ret.setBorder(BorderFactory.createTitledBorder("Date range (format: MM/DD/YYYY)"));
return ret;
}
@Override
public void updateEditor(RandomDistribution property)
{
if (property == null)
{
m_txtMin.setText(null);
m_txtMax.setText(null);
}
else
{
Date dMin = (Date) property.getUserInput(RandomDistributionKey.MIN.name());
Date dMax = (Date) property.getUserInput(RandomDistributionKey.MAX.name());
m_txtMin.setText(formatDate(dMin));
m_txtMax.setText(formatDate(dMax));
}
}
private String formatDate(Date time)
{
Calendar cal = Calendar.getInstance();
cal.setTime(time);
int nDay = cal.get(Calendar.DATE);
int nMon = cal.get(Calendar.MONTH) + 1;
int nYear = cal.get(Calendar.YEAR);
return (nMon < 10 ? "0" + nMon : nMon) + "/" + (nDay < 10 ? "0" + nDay : nDay) + "/" + nYear;
}
@Override
public Map<String, Object> parseEditor() throws Exception
{
Map<String, Object> ret = new HashMap<String, Object>();
Date dMin = m_format.parse(m_txtMin.getText());
Date dMax = m_format.parse(m_txtMax.getText());
if (!(dMax.after(dMin)))
{
throw new ColumnEditParsingException("Min value should be less than Max value");
}
ret.put(RandomDistributionKey.MIN.name(), dMin);
ret.put(RandomDistributionKey.MAX.name(), dMax);
return ret;
}
});
public RandomDistributionEditorRenderer m_lambdaEditorRenderer;
private static Notifier s_notifier;
private RandomDistributionEditor(RandomDistributionEditorRenderer ec)
{
m_lambdaEditorRenderer = ec;
}
private static CatalogType s_valSelected = null;
private static RandomDistributionEditor dispatch(VoltType voltType)
{
switch (voltType)
{
case TINYINT:
case SMALLINT:
case INTEGER:
case BIGINT:
case FLOAT:
case DECIMAL:
return NUMBER_EDITOR;
case STRING:
return STRING_EDITOR;
case TIMESTAMP:
return DATE_EDITOR;
}
throw new RuntimeException("Invalid column type");
}
public static void setSelectedCatalogVal(CatalogType catalogVal)
{
s_valSelected = catalogVal;
}
public static void setNotifier(Notifier notifier)
{
s_notifier = notifier;
}
public static void showMsg(final String msg, boolean alwaysDisplay)
{
s_notifier.showMsg(msg, alwaysDisplay);
}
public static void addEditor(JPanel paneColEdit, CatalogType catalogVal)
{
setSelectedCatalogVal(catalogVal);
RandomDistributionEditor dispatchee = dispatch(typeOf(catalogVal));
paneColEdit.remove(0);
dispatchee.m_lambdaEditorRenderer.updateEditor(null);
paneColEdit.add(dispatchee.m_lambdaEditorRenderer.getEditor(), 0);
}
public static void addEditor(JPanel paneColEdit, CatalogType catalogVal, RandomDistribution property)
{
setSelectedCatalogVal(catalogVal);
RandomDistributionEditor dispatchee = dispatch(typeOf(catalogVal));
paneColEdit.remove(0);
dispatchee.m_lambdaEditorRenderer.updateEditor(property);
paneColEdit.add(dispatchee.m_lambdaEditorRenderer.getEditor(), 0);
}
private static VoltType typeOf(CatalogType catalogVal)
{
if (catalogVal instanceof Column)
{
return VoltType.get(((Column) catalogVal).getType());
}
if (catalogVal instanceof ProcParameter)
{
return VoltType.get(((ProcParameter) catalogVal).getType());
}
throw new RuntimeException("This CatalogType doesn't have getType() method");
}
}