/**
* Copyright Plugtree LLC
*
* 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.plugtree.solrmeter.view;
import com.google.inject.Inject;
import com.plugtree.solrmeter.controller.QueryPanelController;
import com.plugtree.solrmeter.model.exception.QueryException;
import com.plugtree.solrmeter.view.component.IntegerField;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
/**
* Panel to query Solr
* @author tflobbe
*
*/
public class QueryPanel extends StatisticPanel {
private static final long serialVersionUID = 2354841710137826515L;
private final static int INPUT_PANEL_WIDTH = 250;
private final static int OUTPUT_SPLIT_LOCATION = 90;
private JTextField jTextFieldQ;
private JTextField jTextFieldFQ;
private JTextField jTextFieldFacetFields;
private JTextField jTextFieldQT;
private JTextField jTextFieldSort;
private JTextField jTextFieldOtherParams;
private JComboBox jComboSortOrder;
private IntegerField integerFieldRows;
private IntegerField integerFieldStart;
private JCheckBox jCheckBoxHighlight;
private QueryPanelController controller;
private JLabel jLabelQueryTime;
private JLabel jLabelResultsFound;
private JList jListFacets;
private JTable jTableResults;
private QueryResultsTableModel resultsTableModel;
private JSplitPane outputPanel;
private JButton jButtonSearch;
private JTextArea jTextAreaError;
private JScrollPane jScrollPaneError;
@Inject
public QueryPanel(QueryPanelController controller) {
super();
this.initGUI();
this.controller = controller;
controller.setView(this);
}
private void initGUI() {
this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
this.add(this.createPanel());
}
private Component createPanel(){
return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.createInputPanel(), this.createRightOutputPanel());
}
private Component createRightOutputPanel(){
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(this.createOutputPanel());
panel.add(this.createErrorLabel());
return panel;
}
private Component createErrorLabel() {
jTextAreaError = new JTextArea();
jTextAreaError.setEditable(false);
jTextAreaError.setOpaque(false);
jTextAreaError.setBorder(null);
jTextAreaError.setFont(new Font(jTextAreaError.getFont().getName(), jTextAreaError.getFont().getStyle(), 12));
jScrollPaneError = new JScrollPane(jTextAreaError);
jScrollPaneError.setVisible(false);
return jScrollPaneError;
}
private Component createInputPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
panel.setMaximumSize(new Dimension(INPUT_PANEL_WIDTH, Integer.MAX_VALUE));
panel.setMinimumSize(new Dimension(INPUT_PANEL_WIDTH, 1));
panel.setPreferredSize(new Dimension(INPUT_PANEL_WIDTH, 100));
GridBagConstraints constraintsLabels = createConstraints();
GridBagConstraints constraintsInputs = createConstraints();
constraintsInputs.gridx = 1;
constraintsInputs.weightx = 1.5;
panel.add(createLabel("query"),constraintsLabels);
jTextFieldQ = createTextField();
panel.add(jTextFieldQ, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("filterQuery"), constraintsLabels);
jTextFieldFQ = createTextField();
panel.add(jTextFieldFQ, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("facetFields"), constraintsLabels);
jTextFieldFacetFields = createTextField();
panel.add(jTextFieldFacetFields, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("queryType"), constraintsLabels);
jTextFieldQT = createTextField();
panel.add(jTextFieldQT, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("sort"), constraintsLabels);
panel.add(this.createSortInputPanel(), constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("otherParams"), constraintsLabels);
jTextFieldOtherParams = createTextField();
panel.add(jTextFieldOtherParams, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("rows"), constraintsLabels);
integerFieldRows = createIntegerField();
panel.add(integerFieldRows, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
panel.add(createLabel("start"), constraintsLabels);
integerFieldStart = createIntegerField();
panel.add(integerFieldStart, constraintsInputs);
incrementConstraints(constraintsLabels,constraintsInputs);
constraintsLabels.gridwidth = 2;
jCheckBoxHighlight = new JCheckBox(I18n.get("queryPanel.highlight"));
panel.add(jCheckBoxHighlight, constraintsLabels);
incrementConstraints(constraintsLabels,constraintsInputs);
jButtonSearch = new JButton(I18n.get("queryPanel.search"));
jButtonSearch.addActionListener(new ExecuteQueryActionListener());
constraintsLabels.fill = GridBagConstraints.NONE;
panel.add(jButtonSearch, constraintsLabels);
incrementConstraints(constraintsLabels,constraintsInputs);
constraintsLabels.weighty = 2.0;
panel.add(Box.createGlue(), constraintsLabels);
return panel;
}
private IntegerField createIntegerField() {
IntegerField integerField = new IntegerField();
integerField.addActionListener(new ExecuteQueryActionListener());
return integerField;
}
private JTextField createTextField() {
JTextField textField = new JTextField();
textField.addActionListener(new ExecuteQueryActionListener());
return textField;
}
private void incrementConstraints(GridBagConstraints constraints1,
GridBagConstraints constraints2) {
constraints1.gridy = constraints2.gridy = constraints2.gridy+1;
}
private GridBagConstraints createConstraints() {
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(2, 2, 2, 2);
constraints.gridx = 0;
constraints.gridy = 0;
return constraints;
}
private Component createSortInputPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
jTextFieldSort = createTextField();
panel.add(jTextFieldSort);
jComboSortOrder = new JComboBox(this.createSortOrderListModel());
jComboSortOrder.setEditable(false);
panel.add(jComboSortOrder);
return panel;
}
private ComboBoxModel createSortOrderListModel() {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(ORDER.asc);
model.addElement(ORDER.desc);
return model;
}
private Component createOutputPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
panel.add(this.createQueryInfoPanel(), constraints);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 2.0;
constraints.weighty = 2.0;
panel.add(this.createFacetPanel(), constraints);
outputPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, panel, this.createResultsPanel());
outputPanel.setDividerLocation(OUTPUT_SPLIT_LOCATION);
return outputPanel;
}
private Component createResultsPanel() {
jTableResults = new JTable();
resultsTableModel = new QueryResultsTableModel();
jTableResults.setModel(resultsTableModel);
return new JScrollPane(jTableResults);
}
private Component createFacetPanel() {
jListFacets = new JList();
jListFacets.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2) {
String text = jTextFieldFQ.getText();
if(!text.equals("")) {
jTextFieldFQ.setText(text + ", " + getFq());
}else {
jTextFieldFQ.setText(getFq());
}
}
}
private String getFq() {
return ((String)jListFacets.getSelectedValue()).substring(0, ((String)jListFacets.getSelectedValue()).lastIndexOf("("));
}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
});
return new JScrollPane(jListFacets);
}
private Component createQueryInfoPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
jLabelQueryTime = createLabel("queryTime");
panel.add(jLabelQueryTime);
jLabelResultsFound = createLabel("resultsFound");
panel.add(jLabelResultsFound);
return panel;
}
@Override
public String getStatisticName() {
return I18n.get("queryPanel.title");
}
@Override
public void refreshView() {
//nothing
}
private JLabel createLabel(String key) {
return new JLabel(I18n.get("queryPanel." + key));
}
public void showResults(QueryResponse response) {
jScrollPaneError.setVisible(false);
outputPanel.setVisible(true);
jLabelQueryTime.setText(I18n.get("queryPanel.queryTime") + " " + response.getQTime() + " ms");
jLabelResultsFound.setText(I18n.get("queryPanel.resultsFound") + " " + response.getResults().getNumFound());
this.setFacets(response.getFacetFields());
resultsTableModel.setResponse(response);
jTableResults.setModel(resultsTableModel);
jTableResults.doLayout();
jTableResults.requestFocusInWindow();
resultsTableModel.fireTableStructureChanged();
resultsTableModel.fireTableDataChanged();
this.revalidate();
}
private void setFacets(List<FacetField> facetFields) {
if(facetFields == null) {
return;
}
DefaultListModel model = new DefaultListModel();
int i = 0;
for(FacetField facet:facetFields) {
for(Count count:facet.getValues()) {
model.add(i++, facet.getName() + ":" + count.getName() + "(" + count.getCount() + ")");
}
}
jListFacets.setModel(model);
}
public String getQ() {
return jTextFieldQ.getText();
}
public String getFQ() {
return jTextFieldFQ.getText();
}
public String getFacetFields() {
return jTextFieldFacetFields.getText();
}
public String getQT() {
return jTextFieldQT.getText();
}
public String getSort() {
return jTextFieldSort.getText();
}
public ORDER getSortOrder() {
return (ORDER) jComboSortOrder.getSelectedItem();
}
public String getOtherParams() {
return jTextFieldOtherParams.getText();
}
public boolean getHighlight() {
return jCheckBoxHighlight.isSelected();
}
public Integer getRows() {
return integerFieldRows.getInteger();
}
public void showError(QueryException exception) {
jTextAreaError.setText(SwingUtils.getStackTraceString(exception));
jScrollPaneError.setVisible(true);
outputPanel.setVisible(false);
this.revalidate();
}
public Integer getStart() {
return integerFieldStart.getInteger();
}
private class ExecuteQueryActionListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
controller.executeQuery();
}
}
}