diff --git a/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java index 2c5423f51d..5a3cde522c 100644 --- a/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java +++ b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java @@ -39,135 +39,69 @@ package org.jooq.debug; import java.io.Serializable; import java.util.EnumSet; import java.util.Set; -import java.util.regex.Pattern; + +import org.jooq.debug.console.misc.TextMatcher; @SuppressWarnings("serial") public class StatementMatcher implements Serializable { - public static enum TextMatchingType { - STARTS_WITH, - CONTAINS, - EQUALS, - MATCHES_REG_EXP, - } - - private String threadName; - private TextMatchingType textMatchingType; - private String text; - private boolean isTextMatchingCaseSensitive; + private boolean isActive; + private TextMatcher threadNameTextMatcher; + private TextMatcher statementTextMatcher; private Set queryTypeSet; - private Pattern pattern; - /** - * @param threadName a name or null for no matching on thread name. - * @param textMatchingType a type or null for no text matching. + * @param threadNameTextMatcher a text matcher for thread name or null for no text matching. + * @param statementTextMatcher a text matcher for statement or null for no text matching. * @param queryTypeSet some types or null for all types. */ - public StatementMatcher(String threadName, TextMatchingType textMatchingType, String text, boolean isTextMatchingCaseSensitive, Set queryTypeSet) { - this.threadName = threadName; - this.textMatchingType = textMatchingType; - this.text = text; - this.isTextMatchingCaseSensitive = isTextMatchingCaseSensitive; + public StatementMatcher(TextMatcher threadNameTextMatcher, TextMatcher statementTextMatcher, Set queryTypeSet, boolean isActive) { + this.threadNameTextMatcher = threadNameTextMatcher; + this.statementTextMatcher = statementTextMatcher; this.queryTypeSet = queryTypeSet == null? null: EnumSet.copyOf(queryTypeSet); - switch (textMatchingType) { - case CONTAINS: { - String patternText = ".*\\Q" + text.replace("\\E", "\\\\E").replace("\\Q", "\\\\Q") + "\\E.*\\Q"; - pattern = Pattern.compile(patternText, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); - break; - } - case MATCHES_REG_EXP: { - pattern = Pattern.compile(text, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); - break; - } - } + this.isActive = isActive; } public boolean matches(StatementInfo statementInfo) { - if(threadName != null) { - if(!threadName.equals(statementInfo.getThreadName())) { - return false; - } + if(!isActive) { + return false; } - if(textMatchingType != null) { - if(text == null) { + boolean hasMatcher = false; + if(threadNameTextMatcher != null) { + if(!threadNameTextMatcher.matches(statementInfo.getThreadName())) { return false; } - switch(textMatchingType) { - case STARTS_WITH: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(isTextMatchingCaseSensitive) { - if(sql.startsWith(text)) { - isMatching = true; - break; - } - } else if(sql.length() >= text.length()) { - // Let's avoid creating new String instance. - if(sql.substring(0, text.length()).equalsIgnoreCase(text)) { - isMatching = true; - break; - } - } - } - if(!isMatching) { - return false; - } - break; - } - case EQUALS: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(isTextMatchingCaseSensitive) { - if(sql.equals(text)) { - isMatching = true; - break; - } - } else { - if(sql.equalsIgnoreCase(text)) { - isMatching = true; - break; - } - } - } - if(!isMatching) { - return false; - } - break; - } - case CONTAINS: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(pattern.matcher(sql).matches()) { - isMatching = true; - break; - } - } - if(!isMatching) { - return false; - } - } - case MATCHES_REG_EXP: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(pattern.matcher(sql).matches()) { - isMatching = true; - break; - } - } - if(!isMatching) { - return false; - } - } + hasMatcher = true; + } + if(statementTextMatcher != null) { + if(!statementTextMatcher.matches(statementInfo.getQueries())) { + return false; } + hasMatcher = true; } if(queryTypeSet != null) { if(!queryTypeSet.contains(statementInfo.getQueryType())) { return false; } + hasMatcher = true; } - return true; + return hasMatcher; } + public TextMatcher getThreadNameTextMatcher() { + return threadNameTextMatcher; + } + + public TextMatcher getStatementTextMatcher() { + return statementTextMatcher; + } + + public Set getQueryTypeSet() { + return queryTypeSet; + } + + public boolean isActive() { + return isActive; + } } diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java index 5845e1d048..1875cd2289 100644 --- a/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java @@ -101,6 +101,7 @@ import org.jooq.debug.LoggingListener; import org.jooq.debug.QueryLoggingData; import org.jooq.debug.ResultSetLoggingData; import org.jooq.debug.SqlQueryType; +import org.jooq.debug.StatementMatcher; import org.jooq.debug.console.misc.JTableX; import org.jooq.debug.console.misc.RichTextTransferable; import org.jooq.debug.console.misc.Utils; @@ -141,6 +142,7 @@ public class LoggerPane extends JPanel { private JLabel loggerStatusLabel; private JButton loggerOnButton; private JButton loggerOffButton; + private JButton statementMatcherButton; private boolean isLogging; private boolean isReadQueryTypeDisplayed = true; private boolean isWriteQueryTypeDisplayed = true; @@ -180,6 +182,19 @@ public class LoggerPane extends JPanel { } }); loggerHeaderWestPanel.add(loggerOffButton); + statementMatcherButton = new JButton(); + statementMatcherButton.setOpaque(false); + statementMatcherButton.setFocusable(false); + statementMatcherButton.setToolTipText("Filter incoming statements"); + adjustStatementMatcherButton(); + statementMatcherButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new StatementMatcherDialogBox(LoggerPane.this, LoggerPane.this.debugger).setVisible(true); + adjustStatementMatcherButton(); + } + }); + loggerHeaderWestPanel.add(statementMatcherButton); loggerHeaderPanel.add(loggerHeaderWestPanel, BorderLayout.WEST); JPanel loggerHeaderCenterPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2)); loggerHeaderCenterPanel.setOpaque(false); @@ -637,6 +652,15 @@ public class LoggerPane extends JPanel { loggerThreadCheckBox.setSelected(false); } + private void adjustStatementMatcherButton() { + StatementMatcher[] loggingStatementMatchers = LoggerPane.this.debugger.getLoggingStatementMatchers(); + if(loggingStatementMatchers != null) { + statementMatcherButton.setIcon(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/FilterOn16.png"))); + } else { + statementMatcherButton.setIcon(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/FilterOff16.png"))); + } + } + private List queryDebuggingInfoList = new ArrayList(); private List displayedQueryDebuggingInfoList = new ArrayList(); private Map, Integer> queriesToCountMap = new HashMap, Integer>(); diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java new file mode 100644 index 0000000000..d3656795d2 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug.console; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.jooq.debug.Debugger; +import org.jooq.debug.StatementMatcher; + +@SuppressWarnings("serial") +public class StatementMatcherDialogBox extends JDialog { + + public StatementMatcherDialogBox(Component parent, final Debugger debugger) { + super(SwingUtilities.getWindowAncestor(parent), "Statement filters", ModalityType.DOCUMENT_MODAL); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + Container contentPane = getContentPane(); + final StatementMatchersPane statementMatchersPane = new StatementMatchersPane(debugger.getLoggingStatementMatchers()); + contentPane.add(statementMatchersPane, BorderLayout.CENTER); + JPanel buttonBar = new JPanel(new BorderLayout()); + buttonBar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + JPanel filterButtonsPane = new JPanel(new GridLayout(1, 2, 2, 0)); + JButton addFilterButton = new JButton("Add filter"); + addFilterButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.addStatementMatcherPane(new StatementMatcherPane(statementMatchersPane, null)); + } + }); + filterButtonsPane.add(addFilterButton); + JButton removeAllFiltersButton = new JButton("Remove all"); + removeAllFiltersButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.removeAllStatementMatcherPanes(); + } + }); + filterButtonsPane.add(removeAllFiltersButton); + buttonBar.add(filterButtonsPane, BorderLayout.WEST); + JPanel rightButtonsPane = new JPanel(new GridLayout(1, 2, 2, 0)); + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + StatementMatcher[] statementMatchers = statementMatchersPane.getStatementMatchers(); + debugger.setLoggingStatementMatchers(statementMatchers.length == 0? null: statementMatchers); + dispose(); + } + }); + rightButtonsPane.add(okButton); + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + rightButtonsPane.add(cancelButton); + buttonBar.add(rightButtonsPane, BorderLayout.EAST); + contentPane.add(buttonBar, BorderLayout.SOUTH); + setSize(600, 400); + setLocationRelativeTo(SwingUtilities.getWindowAncestor(parent)); + } + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java new file mode 100644 index 0000000000..0858846489 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug.console; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JToolBar; + +import org.jooq.debug.SqlQueryType; +import org.jooq.debug.StatementMatcher; +import org.jooq.debug.console.misc.TextMatcher; + +@SuppressWarnings("serial") +public class StatementMatcherPane extends JPanel { + + private JCheckBox activeCheckBox; + private JCheckBox threadNameTextMatcherCheckBox; + private TextMatcherPane threadNameTextMatcherPane; + private JCheckBox statementTextMatcherCheckBox; + private TextMatcherPane statementTextMatcherPane; + private JCheckBox statementTypeCheckBox; + private JCheckBox statementTypeSelectCheckBox; + private JCheckBox statementTypeUpdateCheckBox; + private JCheckBox statementTypeInsertCheckBox; + private JCheckBox statementTypeDeleteCheckBox; + private JCheckBox statementTypeOtherCheckBox; + + public StatementMatcherPane(final StatementMatchersPane statementMatchersPane, StatementMatcher statementMatcher) { + super(new GridBagLayout()); + setBorder(BorderFactory.createLineBorder(getBackground().darker())); + if(statementMatcher == null) { + statementMatcher = new StatementMatcher(null, null, null, true); + } + int y = 0; + JPanel northPane = new JPanel(new GridBagLayout()); + activeCheckBox = new JCheckBox("Active", statementMatcher.isActive()); + northPane.add(activeCheckBox, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + JToolBar closeButtonPane = new JToolBar(); + closeButtonPane.setFloatable(false); + JButton closeButton = new JButton(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/TabCloseActive14.png"))); + closeButton.setFocusable(false); + closeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.removeStatementMatcherPane(StatementMatcherPane.this); + } + }); + closeButtonPane.add(closeButton); + northPane.add(closeButtonPane, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + add(northPane, new GridBagConstraints(0, y, 2, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + y++; + TextMatcher statementTextMatcher = statementMatcher.getStatementTextMatcher(); + statementTextMatcherCheckBox = new JCheckBox("Statement", statementTextMatcher != null); + add(statementTextMatcherCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + statementTextMatcherPane = new TextMatcherPane(statementTextMatcher); + add(statementTextMatcherPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + y++; + Set queryTypeSet = statementMatcher.getQueryTypeSet(); + statementTypeCheckBox = new JCheckBox("Type", queryTypeSet != null); + add(statementTypeCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + JPanel typesPane = new JPanel(new GridBagLayout()); + statementTypeSelectCheckBox = new JCheckBox("SELECT", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.SELECT)); + typesPane.add(statementTypeSelectCheckBox, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + statementTypeUpdateCheckBox = new JCheckBox("UPDATE", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.UPDATE)); + typesPane.add(statementTypeUpdateCheckBox, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeInsertCheckBox = new JCheckBox("INSERT", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.INSERT)); + typesPane.add(statementTypeInsertCheckBox, new GridBagConstraints(2, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeDeleteCheckBox = new JCheckBox("DELETE", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.DELETE)); + typesPane.add(statementTypeDeleteCheckBox, new GridBagConstraints(3, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeOtherCheckBox = new JCheckBox("OTHER", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.OTHER)); + typesPane.add(statementTypeOtherCheckBox, new GridBagConstraints(4, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + add(typesPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + y++; + TextMatcher threadNameTextMatcher = statementMatcher.getThreadNameTextMatcher(); + threadNameTextMatcherCheckBox = new JCheckBox("Thread name", threadNameTextMatcher != null); + add(threadNameTextMatcherCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + threadNameTextMatcherPane = new TextMatcherPane(threadNameTextMatcher); + add(threadNameTextMatcherPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + } + + public StatementMatcher getStatementMatcher() { + boolean isActive = activeCheckBox.isSelected(); + TextMatcher threadNameTextMatcher = threadNameTextMatcherCheckBox.isSelected()? threadNameTextMatcherPane.getTextMatcher(): null; + TextMatcher statementTextMatcher = statementTextMatcherCheckBox.isSelected()? statementTextMatcherPane.getTextMatcher(): null; + Set queryTypeSet; + if(statementTypeCheckBox.isSelected()) { + List typeList = new ArrayList(); + if(statementTypeSelectCheckBox.isSelected()) { + typeList.add(SqlQueryType.SELECT); + } + if(statementTypeUpdateCheckBox.isSelected()) { + typeList.add(SqlQueryType.UPDATE); + } + if(statementTypeInsertCheckBox.isSelected()) { + typeList.add(SqlQueryType.INSERT); + } + if(statementTypeDeleteCheckBox.isSelected()) { + typeList.add(SqlQueryType.DELETE); + } + if(statementTypeOtherCheckBox.isSelected()) { + typeList.add(SqlQueryType.OTHER); + } + queryTypeSet = EnumSet.copyOf(typeList); + } else { + queryTypeSet = null; + } + return new StatementMatcher(threadNameTextMatcher, statementTextMatcher, queryTypeSet, isActive); + } + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java new file mode 100644 index 0000000000..b764037aa1 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug.console; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.Scrollable; + +import org.jooq.debug.StatementMatcher; + +@SuppressWarnings("serial") +public class StatementMatchersPane extends JPanel { + + private static class ScrollablePane extends JPanel implements Scrollable { + + public ScrollablePane() { + super(new GridLayout(0, 1, 1, 1)); + } + + @Override + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + @Override + public boolean getScrollableTracksViewportHeight() { + return false; + } + + @Override + public boolean getScrollableTracksViewportWidth() { + return true; + } + + @Override + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return 100; + } + + @Override + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 10; + } + + } + + private JPanel statementMatcherPanesContainer; + + public StatementMatchersPane(StatementMatcher[] statementMatchers) { + super(new BorderLayout()); + statementMatcherPanesContainer = new ScrollablePane(); + add(new JScrollPane(statementMatcherPanesContainer), BorderLayout.CENTER); + if(statementMatchers != null) { + for(StatementMatcher statementMatcher: statementMatchers) { + addStatementMatcherPane(new StatementMatcherPane(this, statementMatcher)); + } + } + } + + public void addStatementMatcherPane(StatementMatcherPane statementMatcherPane) { + statementMatcherPanesContainer.add(statementMatcherPane); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + statementMatcherPanesContainer.scrollRectToVisible(new Rectangle(0, Short.MAX_VALUE, 1, 1)); + } + + void removeAllStatementMatcherPanes() { + statementMatcherPanesContainer.removeAll(); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + } + + void removeStatementMatcherPane(StatementMatcherPane statementMatcherPane) { + statementMatcherPanesContainer.remove(statementMatcherPane); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + } + + public StatementMatcher[] getStatementMatchers() { + Component[] components = statementMatcherPanesContainer.getComponents(); + StatementMatcher[] statementMatchers = new StatementMatcher[components.length]; + for(int i=0; i= text.length()) { + // Let's avoid creating new String instance. + if(sql.substring(0, text.length()).equalsIgnoreCase(text)) { + return true; + } + } + } + return false; + } + case EQUALS: { + for(String sql: texts) { + if(isCaseSensitive) { + if(sql.equals(text)) { + return true; + } + } else { + if(sql.equalsIgnoreCase(text)) { + return true; + } + } + } + return false; + } + case CONTAINS: { + for(String sql: texts) { + if(pattern.matcher(sql).matches()) { + return true; + } + } + return false; + } + case MATCHES_REG_EXP: { + for(String sql: texts) { + if(pattern.matcher(sql).matches()) { + return true; + } + } + return false; + } + } + return false; + } + + public TextMatchingType getType() { + return type; + } + + public String getText() { + return text; + } + + public boolean isCaseSensitive() { + return isCaseSensitive; + } + +} diff --git a/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png b/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png new file mode 100644 index 0000000000..ca5d9a1e1c Binary files /dev/null and b/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png differ diff --git a/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOn16.png b/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOn16.png new file mode 100644 index 0000000000..3f6d29ecb3 Binary files /dev/null and b/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOn16.png differ