package gov.nasa.jpl.mbee.mdk.ocl.ui; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import gov.nasa.jpl.mbee.mdk.util.MDUtils; import gov.nasa.jpl.mbee.mdk.util.MoreToString; import gov.nasa.jpl.mbee.mdk.ocl.actions.OclQueryAction; import gov.nasa.jpl.mbee.mdk.ocl.actions.OclQueryAction.ProcessOclQuery; import org.eclipse.ocl.util.CollectionUtil; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.List; /** * */ public class OclQueryDialog extends JDialog implements ActionListener { private static final long serialVersionUID = -9114812582757129836L; private static OclQueryDialog instance = null; // members for tracking input history protected static String query = null; //protected static LinkedList<Object> inputHistory = new LinkedList<Object>(); //protected static HashSet<Object> pastInputs = new HashSet<Object>(); protected static LinkedList<String> choices = new LinkedList<String>(); protected static int maxChoices = 20; protected boolean isPressed = false; private volatile boolean isThreadRunning = false; /** * callback for processing input */ protected RepeatInputComboBoxDialog.Processor processor; protected RepeatInputComboBoxDialog.EditableListPanel editableListPanel = null; protected boolean cancelSelected = false; List<Component> lastClickedComponents = new ArrayList<Component>(); public JCheckBox diagramCB, browserCB; public JRadioButton objectRadioButton, eachRadioButton; public JToggleButton evalButton; private Thread queryThread; /** * @param owner * @param title */ public OclQueryDialog(Window owner, String title) { super(owner, title, ModalityType.MODELESS); init(owner); } protected void init(Window owner) { editableListPanel = new RepeatInputComboBoxDialog.EditableListPanel("Enter an OCL expression:", choices.toArray()); editableListPanel.setVisible(true); //Create and initialize the buttons. JButton closeButton = new JButton("Close"); closeButton.setActionCommand("Close"); closeButton.addActionListener(this); // String evaluateButtonText = "Evaluate (Shift+Enter)"; evalButton = new JToggleButton(evaluateButtonText); evalButton.setActionCommand("Evaluate"); evalButton.addActionListener(this); evalButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Evaluate"); // MDEV 1221 evalButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK), "Evaluate"); editableListPanel.queryTextArea.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK), new AbstractAction() { /** * */ private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { evalButton.doClick(); } } ); // getRootPane().setDefaultButton(evalButton); //Lay out the buttons from left to right. JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(closeButton); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(evalButton); // checkboxes for which selected components to include: those in diagram, those in browser. JPanel checkBoxPane = new JPanel(); //checkBoxPane.setLayout( new BorderLayout() ); checkBoxPane.setLayout(new GridBagLayout()); final GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 1; c.gridy = 0; c.weightx = 0.5; //c.weighty = 0d; diagramCB = new JCheckBox("Selection from diagram", true); checkBoxPane.add(diagramCB, c); c.gridy = 1; browserCB = new JCheckBox("Selection from browser", false); checkBoxPane.add(browserCB, c); c.gridx = 0; c.gridy = 0; final JLabel queryLabel = new JLabel("Apply query to"); queryLabel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); checkBoxPane.add(queryLabel, c); final ButtonGroup buttonGroup = new ButtonGroup(); c.gridy = 1; objectRadioButton = new JRadioButton("Selection as a single object"); objectRadioButton.setSelected(true); buttonGroup.add(objectRadioButton); checkBoxPane.add(objectRadioButton, c); c.gridy = 2; eachRadioButton = new JRadioButton("Each selected item"); buttonGroup.add(eachRadioButton); checkBoxPane.add(eachRadioButton, c); //iterateCB = new JCheckBox( "Iterate", false ); //checkBoxPane.add( iterateCB, BorderLayout.PAGE_END ); //Put everything together, using the content pane's BorderLayout. Container contentPane = getContentPane(); contentPane.add(editableListPanel, BorderLayout.CENTER); JPanel jp = new JPanel(); jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); jp.add(checkBoxPane, BorderLayout.CENTER); jp.add(buttonPane); contentPane.add(jp, BorderLayout.PAGE_END); setMinimumSize(new Dimension(400, 500)); //setSize( new Dimension( 400, 600 ) ); //Initialize values. pack(); if (owner != null) { setLocationRelativeTo(owner); } ItemListener itemListener = new ItemListener() { public void itemStateChanged(ItemEvent itemEvent) { int state = itemEvent.getStateChange(); if (state == ItemEvent.SELECTED) { evalButton.setText("Stop evaluation"); } else { evalButton.setText(evaluateButtonText); } } }; evalButton.addItemListener(itemListener); } @Override public void actionPerformed(ActionEvent e) { if ("Evaluate".equals(e.getActionCommand())) { if (isPressed) { //evalButton.setText("Stop evaluation!"); isPressed = false; if (isThreadRunning) { queryThread.stop(); } } else { isPressed = true; editableListPanel.queryTextArea.setEnabled(false); // evalButton.setText("Stop evaluation"); queryThread = new Thread() { public void run() { runQuery(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // evalButton.setText("Evaluate"); isThreadRunning = false; evalButton.doClick(); isPressed = false; } }); } }; isThreadRunning = true; queryThread.start(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { editableListPanel.queryTextArea.setEnabled(true); editableListPanel.queryTextArea.requestFocusInWindow(); } }); } evalButton.requestFocus(); } else if ("Close".equals(e.getActionCommand())) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { evalButton.requestFocusInWindow(); } }); setVisible(false); } else { // BAD } } protected void runQuery() { Collection<Element> selectedElements = CollectionUtil.createNewSequence(); if (diagramCB.isSelected()) { selectedElements.addAll(MDUtils.getSelectionInDiagram()); } if (browserCB.isSelected()) { selectedElements.addAll(MDUtils.getSelectionInContainmentBrowser()); } //selectedElements.add(null); //selectedElements = CollectionUtil.asSequence(selectedElements); //processor = new OclQueryAction.ProcessOclQuery(selectedElements); //processor = oclQueryProcessor; query = editableListPanel.getQuery(); if (query != null) { Object result = null; if (objectRadioButton.isSelected()) { Object context = selectedElements; if (selectedElements.isEmpty()) { context = null; } else if (selectedElements.size() == 1) { context = selectedElements.iterator().next(); } processor = new OclQueryAction.ProcessOclQuery(context); result = processor.process(query); String processedResult = processResults(result); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { editableListPanel.setResult(processedResult); editableListPanel.setCompletions(processor.getCompletionChoices(), ProcessOclQuery.toString(processor.getSourceOfCompletion()) + " : " + ProcessOclQuery.getTypeName(processor.getSourceOfCompletion())); } }); } else { final List<Object> resultList = new ArrayList<Object>(); final List<String> completionList = new ArrayList<String>(); final List<Class<?>> classList = new ArrayList<Class<?>>(); //editableListPanel.clearCompletions(); for (final Object context : selectedElements) { processor = new OclQueryAction.ProcessOclQuery(context); result = processor.process(query); String processedResult = processResults(result); resultList.add(processedResult); if (result != null && !classList.contains(result.getClass())) { // completionList.add(editableListPanel.getCompletionHeader(processor.getSourceOfCompletion())); completionList.addAll(processor.getCompletionChoices()); classList.add(result.getClass()); } } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { editableListPanel.setResult(MoreToString.Helper.toString(resultList, false, true, null, null, "<ol><li>", "<li>", "</ol>", false)); editableListPanel.setCompletions(completionList, ProcessOclQuery.toString(processor.getSourceOfCompletion()) + " : " + ProcessOclQuery.getTypeName(processor.getSourceOfCompletion())); } }); //System.out.println("Completion List: " + completionList); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { choices.push(query); while (choices.size() > maxChoices) { choices.pollLast(); } editableListPanel.setItems(choices.toArray()); } }); } /*inputHistory.push(query); if (pastInputs.contains(query)) { choices.remove(query); } else { pastInputs.add(query); } choices.push(query); while (choices.size() > maxChoices) { choices.pollLast(); } editableListPanel.setItems(choices.toArray());*/ } private String processResults(Object oclObject) { if (oclObject == null) { return "null"; } else if (oclObject instanceof org.eclipse.ocl.util.Bag<?>) { Object[] bag = ((org.eclipse.ocl.util.Bag<?>) oclObject).toArray(); Set<Object> bagContents = new HashSet<>(); List<String> bagStrings = new LinkedList<>(); String s = "{"; for (int i = 0; i < bag.length; i++) { if (bagContents.contains(bag[i])) { continue; } bagContents.add(bag[i]); bagStrings.add(processResults(bag[i]) + "=" + ((org.eclipse.ocl.util.Bag<?>) oclObject).count(bag[i])); } Iterator<String> iter = bagStrings.iterator(); while (iter.hasNext()) { String current = iter.next(); s += current; if (iter.hasNext()) { s += ", "; } } s += "}"; return s; } else if (oclObject instanceof List<?>) { String s = "["; Iterator<?> iter = ((List<?>) oclObject).iterator(); while (iter.hasNext()) { s += processResults(iter.next()); if (iter.hasNext()) { s += ", "; } } s += "]"; return s; } else if (oclObject instanceof Set<?>) { String s = "["; Iterator<?> iter = ((Set<?>) oclObject).iterator(); while (iter.hasNext()) { s += processResults(iter.next()); if (iter.hasNext()) { s += ", "; } } s += "]"; return s; } else if (oclObject instanceof Element) { return ((Element) oclObject).getHumanName(); } else if (oclObject instanceof String) { return (String) oclObject; } return oclObject.toString(); } public static OclQueryDialog getInstance() { return instance; } /** * @return the editableListPanel */ public RepeatInputComboBoxDialog.EditableListPanel getEditableListPanel() { return editableListPanel; } /** * @param args */ public static void main(String[] args) { OclQueryDialog dialog = new OclQueryDialog(null, "testing"); dialog.setVisible(true); } }