/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.integration.tool.enginedebugger; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.swing.ButtonGroup; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.apache.commons.lang.ObjectUtils; import org.jdesktop.swingx.JXDatePicker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.Instant; import org.threeten.bp.LocalDate; import org.threeten.bp.ZoneOffset; import com.opengamma.engine.marketdata.spec.FixedHistoricalMarketDataSpecification; import com.opengamma.engine.marketdata.spec.LatestHistoricalMarketDataSpecification; import com.opengamma.engine.marketdata.spec.MarketDataSpecification; import com.opengamma.engine.marketdata.spec.UserMarketDataSpecification; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; import com.opengamma.integration.swing.HistoricalMarketDataSpecificationListModel; import com.opengamma.integration.swing.LiveMarketDataSpecificationListModel; import com.opengamma.integration.swing.SnapshotMarketDataSpecificationListModel; import com.opengamma.integration.swing.SnapshotMarketDataSpecificationVersionListModel; import com.opengamma.master.config.ConfigMaster; import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotMaster; import com.opengamma.provider.livedata.LiveDataMetaDataProvider; import net.miginfocom.swing.MigLayout; /** * Component representing a market data specification */ public class MarketDataSpecificationComponent extends JPanel { /** * */ private static final long serialVersionUID = 1L; private static final Logger s_logger = LoggerFactory.getLogger(MarketDataSpecificationComponent.class); private static final String SNAPSHOT = "Snapshot"; private static final String HISTORICAL = "Historical"; private static final String LIVE = "Live"; private static final String DATA_SOURCE_TYPE_PROMPT = "select type..."; private static final String[] VALID_ITEMS = new String[] {DATA_SOURCE_TYPE_PROMPT, LIVE, HISTORICAL, SNAPSHOT}; private static final String DATA_SOURCE_PROMPT = "select data source..."; private static final String SNAPSHOT_VERSION_PROMPT = "select snapshot version..."; private static final String LATEST = "Latest"; private static final String FIXED = "Fixed"; private static final int HEIGHT = 24; private static final Dimension DATA_SOURCE_TYPE_PREFERRED_SIZE = new Dimension(150, HEIGHT); private static final Dimension SNAPSHOT_VERSION_PREFERRED_SIZE = new Dimension(250, HEIGHT); private static final Dimension DATA_SOURCE_PREFERRED_SIZE = new Dimension(350, HEIGHT); private static final Dimension COMPONENT_PREFERRED_SIZE = new Dimension(960, HEIGHT); // main controls private JComboBox<String> _dataSourceTypeCombo; private JComboBox<String> _dataSourceCombo; private JComboBox<String> _snapshotVersionCombo; private JXDatePicker _datePicker; // incidental controls private JRadioButton _latestRadio; private JRadioButton _fixedRadio; // models private LiveMarketDataSpecificationListModel _liveModel; private HistoricalMarketDataSpecificationListModel _historicalModel; private SnapshotMarketDataSpecificationListModel _snapshotModel; // externally injected sources/data private List<LiveDataMetaDataProvider> _metaDataProviders; private ConfigMaster _configMaster; private MarketDataSnapshotMaster _snapshotMaster; // state private MarketDataSpecification _currentState; private Set<ChangeListener> _listeners = new LinkedHashSet<ChangeListener>(); public MarketDataSpecificationComponent(List<LiveDataMetaDataProvider> metaDataProviders, ConfigMaster configMaster, MarketDataSnapshotMaster snapshotMaster) { super(); _configMaster = configMaster; _snapshotMaster = snapshotMaster; _metaDataProviders = metaDataProviders; _dataSourceTypeCombo = createDataSourceTypeCombo(); _dataSourceCombo = createDataSourceCombo(); _snapshotVersionCombo = createSnapshotVersionCombo(); _datePicker = new JXDatePicker(); _datePicker.setPreferredSize(SNAPSHOT_VERSION_PREFERRED_SIZE); _datePicker.setMinimumSize(SNAPSHOT_VERSION_PREFERRED_SIZE); _datePicker.setMaximumSize(SNAPSHOT_VERSION_PREFERRED_SIZE); createModels(); addComponents(); setPreferredSize(COMPONENT_PREFERRED_SIZE); } private void createModels() { _liveModel = new LiveMarketDataSpecificationListModel(_metaDataProviders); _historicalModel = new HistoricalMarketDataSpecificationListModel(_configMaster); _snapshotModel = new SnapshotMarketDataSpecificationListModel(_snapshotMaster); } public void addComponents() { setLayout(new MigLayout("insets 0")); _dataSourceTypeCombo.setVisible(true); add(_dataSourceTypeCombo, "align left"); _dataSourceCombo.setVisible(true); add(_dataSourceCombo, "align center, growx"); _latestRadio = new JRadioButton(LATEST); _latestRadio.setVisible(false); _latestRadio.setActionCommand(LATEST); _latestRadio.addActionListener(_radioActionListener); _latestRadio.setSelected(true); _fixedRadio = new JRadioButton(FIXED); _fixedRadio.setVisible(false); _fixedRadio.setActionCommand(FIXED); _fixedRadio.addActionListener(_radioActionListener); ButtonGroup group = new ButtonGroup(); group.add(_latestRadio); group.add(_fixedRadio); add(_latestRadio, "align right"); add(_fixedRadio, "align right"); _datePicker.setEnabled(false); _datePicker.addActionListener(_historicalActionListener); } @SuppressWarnings("unused") private void showSnapshotVersionPicker(ObjectId id) { _latestRadio.setVisible(true); _fixedRadio.setVisible(true); _snapshotVersionCombo.setModel(new SnapshotMarketDataSpecificationVersionListModel(_snapshotMaster, id)); _snapshotVersionCombo.setVisible(true); remove(_datePicker); add(_snapshotVersionCombo, "align right"); validate(); } @SuppressWarnings("unused") private void showSnapshotNamePicker() { _latestRadio.setVisible(false); _fixedRadio.setVisible(false); _dataSourceCombo.setModel(_snapshotModel); _dataSourceCombo.addActionListener(_snapshotActionListener); _dataSourceCombo.removeActionListener(_historicalActionListener); _dataSourceCombo.removeActionListener(_liveActionListener); _dataSourceCombo.setVisible(true); remove(_snapshotVersionCombo); remove(_datePicker); validate(); } @SuppressWarnings("unused") private void showHistoricalDatePicker() { _snapshotVersionCombo.setVisible(false); _snapshotVersionCombo.setModel(new DefaultComboBoxModel<String>(new String[] {SNAPSHOT_VERSION_PROMPT })); _dataSourceCombo.setModel(_historicalModel); _dataSourceCombo.removeActionListener(_liveActionListener); _dataSourceCombo.removeActionListener(_snapshotActionListener); _dataSourceCombo.addActionListener(_historicalActionListener); _dataSourceCombo.setVisible(true); _latestRadio.setVisible(true); _fixedRadio.setVisible(true); remove(_snapshotVersionCombo); add(_datePicker, "align right"); validate(); } @SuppressWarnings("unused") private void showLive() { _latestRadio.setVisible(false); _fixedRadio.setVisible(false); _dataSourceCombo.setModel(_liveModel); _dataSourceCombo.addActionListener(_liveActionListener); _dataSourceCombo.setVisible(true); _snapshotVersionCombo.setModel(new DefaultComboBoxModel<String>(new String[] {SNAPSHOT_VERSION_PROMPT })); remove(_datePicker); remove(_snapshotVersionCombo); validate(); } private void validSpecification(MarketDataSpecification marketDataSpec) { s_logger.warn("valid specification {}", marketDataSpec); if (!ObjectUtils.equals(_currentState, marketDataSpec)) { _currentState = marketDataSpec; fireStateChanged(); } } private void invalidSpecification() { s_logger.warn("invalid specification"); _currentState = null; fireStateChanged(); } private ActionListener _radioActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { s_logger.warn("radio action triggered"); switch (e.getActionCommand()) { case LATEST: _datePicker.setEnabled(false); _snapshotVersionCombo.setEnabled(false); break; case FIXED: _datePicker.setEnabled(true); _snapshotVersionCombo.setEnabled(true);; break; } switch ((String) _dataSourceTypeCombo.getSelectedItem()) { case HISTORICAL: historySelected(); break; case SNAPSHOT: switch (e.getActionCommand()) { case LATEST: snapshotSelected(); break; case FIXED: snapshotVersionSelected(); break; } break; case LIVE: liveSelected(); break; } } }; private ActionListener _liveActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { liveSelected(); } }; private void liveSelected() { s_logger.warn("live selected"); JComboBox<String> source = _dataSourceCombo; String item = (String) source.getSelectedItem(); MarketDataSpecification marketDataSpec = MarketDataSpecificationComponent.this._liveModel.getMarketDataSpec(item); validSpecification(marketDataSpec); } private ActionListener _historicalActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { historySelected(); } }; private void historySelected() { s_logger.warn("history selected"); MarketDataSpecificationComponent outer = MarketDataSpecificationComponent.this; @SuppressWarnings("unchecked") JComboBox<String> source = _dataSourceCombo; String item = (String) source.getSelectedItem(); if (item != null) { MarketDataSpecification marketDataSpec; if (_latestRadio.isSelected()) { marketDataSpec = new LatestHistoricalMarketDataSpecification(item); validSpecification(marketDataSpec); return; } else { Date datePickerDate = outer._datePicker.getDate(); if (item != null && item.length() > 0 && datePickerDate != null) { LocalDate localDate = Instant.ofEpochMilli(datePickerDate.getTime()).atZone(ZoneOffset.UTC).toLocalDate(); marketDataSpec = new FixedHistoricalMarketDataSpecification(item, localDate); validSpecification(marketDataSpec); return; } } } invalidSpecification(); } private ActionListener _snapshotActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { snapshotSelected(); } }; private void snapshotSelected() { s_logger.warn("snapshot selected"); JComboBox<String> source = _dataSourceCombo; int index = source.getSelectedIndex(); if (index >= 0) { ObjectId oid = MarketDataSpecificationComponent.this._snapshotModel.getObjectIdAt(index); if (oid != null) { MarketDataSpecification marketDataSpec = UserMarketDataSpecification.of(oid.atLatestVersion()); showSnapshotVersionPicker(oid); if (_latestRadio.isSelected()) { validSpecification(marketDataSpec); return; } } } invalidSpecification(); } private ActionListener _snapshotVersionActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { snapshotVersionSelected(); } }; private void snapshotVersionSelected() { s_logger.warn("snapshot version selected"); int index = _snapshotVersionCombo.getSelectedIndex(); if (index >= 0) { ObjectId oid = MarketDataSpecificationComponent.this._snapshotModel.getObjectIdAt(index); if (_latestRadio.isSelected()) { MarketDataSpecification marketDataSpec = UserMarketDataSpecification.of(oid.atLatestVersion()); MarketDataSpecificationComponent.this._currentState = marketDataSpec; validSpecification(marketDataSpec); return; } else { int selectedIndex = _snapshotVersionCombo.getSelectedIndex(); if (selectedIndex >= 0 && _snapshotVersionCombo.getModel() instanceof SnapshotMarketDataSpecificationVersionListModel) { SnapshotMarketDataSpecificationVersionListModel model = (SnapshotMarketDataSpecificationVersionListModel) _snapshotVersionCombo.getModel(); UniqueId uid = model.getUniqueIdAt(selectedIndex); MarketDataSpecification marketDataSpec = UserMarketDataSpecification.of(uid); validSpecification(marketDataSpec); return; } } } invalidSpecification(); } public JComboBox<String> createDataSourceCombo() { JComboBox<String> comboBox = new JComboBox<String>(); comboBox.setModel(new DefaultComboBoxModel<String>(new String[] {DATA_SOURCE_PROMPT })); comboBox.setPreferredSize(DATA_SOURCE_PREFERRED_SIZE); comboBox.setMaximumSize(DATA_SOURCE_PREFERRED_SIZE); comboBox.setMinimumSize(DATA_SOURCE_PREFERRED_SIZE); return comboBox; } public JComboBox<String> createSnapshotVersionCombo() { JComboBox<String> comboBox = new JComboBox<String>(); comboBox.setModel(new DefaultComboBoxModel<String>(new String[] {SNAPSHOT_VERSION_PROMPT })); comboBox.addActionListener(_snapshotVersionActionListener); comboBox.setPreferredSize(SNAPSHOT_VERSION_PREFERRED_SIZE); comboBox.setMaximumSize(SNAPSHOT_VERSION_PREFERRED_SIZE); comboBox.setMinimumSize(SNAPSHOT_VERSION_PREFERRED_SIZE); return comboBox; } public JComboBox<String> createDataSourceTypeCombo() { final JComboBox<String> comboBox = new JComboBox<String>(); comboBox.setModel(new DefaultComboBoxModel<String>(VALID_ITEMS)); comboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @SuppressWarnings("unchecked") JComboBox<String> source = (JComboBox<String>) e.getSource(); String item = (String) source.getSelectedItem(); switch (item) { case LIVE: showLive(); liveSelected(); break; case HISTORICAL: showHistoricalDatePicker(); historySelected(); break; case SNAPSHOT: showSnapshotNamePicker(); snapshotSelected(); break; } } }); comboBox.setPreferredSize(DATA_SOURCE_TYPE_PREFERRED_SIZE); comboBox.setMinimumSize(DATA_SOURCE_TYPE_PREFERRED_SIZE); comboBox.setMaximumSize(DATA_SOURCE_TYPE_PREFERRED_SIZE); return comboBox; } public void addChangeListener(ChangeListener listener) { _listeners.add(listener); } public void removeChangeListener(ChangeListener listener) { _listeners.remove(listener); } protected void fireStateChanged() { s_logger.warn("state changed"); for (ChangeListener listener : _listeners) { listener.stateChanged(new ChangeEvent(this)); } } public MarketDataSpecification getCurrentState() { return _currentState; } }