All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cayenne.modeler.editor.EjbqlQueryScriptsTab Maven / Gradle / Ivy

There is a newer version: 5.0-M1
Show newest version
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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
 *
 *    https://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 org.apache.cayenne.modeler.editor;

import java.awt.BorderLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

import org.apache.cayenne.configuration.event.QueryEvent;
import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.util.JUndoableCayenneTextPane;
import org.apache.cayenne.project.validation.EJBQLStatementValidator;
import org.apache.cayenne.project.validation.EJBQLStatementValidator.PositionException;
import org.apache.cayenne.map.EJBQLQueryDescriptor;
import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.swing.components.textpane.JCayenneTextPane;
import org.apache.cayenne.swing.components.textpane.syntax.EJBQLSyntaxConstant;
import org.apache.cayenne.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EjbqlQueryScriptsTab extends JPanel implements DocumentListener {

    private static final Logger logger = LoggerFactory.getLogger(EjbqlQueryScriptsTab.class);

    protected ProjectController mediator;
    protected JCayenneTextPane scriptArea;
    private boolean updateDisabled;
    protected EJBQLStatementValidator ejbqlQueryValidator = new EJBQLStatementValidator();

    public EjbqlQueryScriptsTab(ProjectController mediator) {
        this.mediator = mediator;
        initView();
    }

    void displayScript() {
        scriptArea.setDocumentTextDirect(getQuery().getEjbql());
        updateDisabled = false;
    }

    private void initView() {

        scriptArea = new JUndoableCayenneTextPane(new EJBQLSyntaxConstant());
        scriptArea.getDocument().addDocumentListener(this);
        scriptArea.getDocument().addDocumentListener(new DocumentListener() {

            public void changedUpdate(DocumentEvent e) {
            }

            public void insertUpdate(DocumentEvent e) {
                try {
                    String text = scriptArea.getDocument().getText(e.getOffset(), 1);
                    if (text.equals(" ") || text.equals("\n") || text.equals("\t")) {
                        getQuery().setEjbql(scriptArea.getDocumentTextDirect());
                        validateEJBQL();
                    }
                } catch (BadLocationException ex) {
                    logger.warn("Error reading document", ex);
                }
            }

            public void removeUpdate(DocumentEvent e) {
                getQuery().setEjbql(scriptArea.getDocumentTextDirect());
                validateEJBQL();
            }
        });

        scriptArea.getPane().addFocusListener(new FocusListener() {

            EJBQLValidationThread thread;

            public void focusGained(FocusEvent e) {
                thread = new EJBQLValidationThread();
                thread.start();
            }

            public void focusLost(FocusEvent e) {
                thread.terminate();
            }
        });

        scriptArea.getPane().addKeyListener(new KeyListener() {

            boolean pasteOrCut;

            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_END || e.getKeyCode() == KeyEvent.VK_HOME
                        || e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_RIGHT
                        || e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_UNDO) {
                    getQuery().setEjbql(scriptArea.getText());
                    validateEJBQL();
                }
                if ((e.getKeyCode() == KeyEvent.VK_V || e.getKeyCode() == KeyEvent.VK_X) && e.isControlDown()) {
                    pasteOrCut = true;
                }
            }

            public void keyReleased(KeyEvent e) {
                if ((pasteOrCut && e.getKeyCode() == KeyEvent.VK_CONTROL) || e.getKeyCode() == KeyEvent.VK_DELETE) {
                    scriptArea.removeHighlightText();
                    getQuery().setEjbql(scriptArea.getText());
                    validateEJBQL();
                    pasteOrCut = false;
                }
            }

            public void keyTyped(KeyEvent e) {
            }
        });

        setLayout(new BorderLayout());
        add(scriptArea, BorderLayout.WEST);
        add(scriptArea.getScrollPane(), BorderLayout.CENTER);
        setVisible(true);
    }

    public void initFromModel() {
        QueryDescriptor query = mediator.getCurrentQuery();

        if (query == null || !QueryDescriptor.EJBQL_QUERY.equals(query.getType())) {
            setVisible(false);
            return;
        }
        scriptArea.setEnabled(true);
        displayScript();
        validateEJBQL();
        setVisible(true);
    }

    EJBQLQueryDescriptor getQuery() {
        QueryDescriptor query = mediator.getCurrentQuery();
        return (query != null && QueryDescriptor.EJBQL_QUERY.equals(query.getType())) ?
                (EJBQLQueryDescriptor) query : null;
    }

    void setEJBQL(DocumentEvent e) {
        Document doc = e.getDocument();
        try {
            setEJBQL(doc.getText(0, doc.getLength()));
        } catch (BadLocationException ex) {
            logger.warn("Error reading document", ex);
        }
    }

    void setEJBQL(String text) {
        EJBQLQueryDescriptor query = getQuery();
        if (query == null) {
            return;
        }

        if (text != null && text.trim().isEmpty()) {
            text = null;
        }

        // Compare the value before modifying the query - text area
        // will call "verify" even if no changes have occured....
        if (!Util.nullSafeEquals(text, query.getEjbql())) {
            query.setEjbql(text);
            mediator.fireQueryEvent(new QueryEvent(this, query));
        }

    }

    public void insertUpdate(DocumentEvent e) {
        changedUpdate(e);
    }

    public void removeUpdate(DocumentEvent e) {
        changedUpdate(e);
    }

    public void changedUpdate(DocumentEvent e) {
        if (!updateDisabled) {
            setEJBQL(e);
        }
    }

    void validateEJBQL() {
        final PositionException positionException = ejbqlQueryValidator.validateEJBQL(getQuery());
        if (positionException != null) {

            if (!SwingUtilities.isEventDispatchThread()) {
                SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        if (positionException.getBeginLine() != null || positionException.getBeginColumn() != null
                                || positionException.getLength() != null) {
                            scriptArea.setHighlightText(positionException.getBeginLine(),
                                    positionException.getBeginColumn(), positionException.getLength(),
                                    positionException.getMessage());
                        } else {
                            scriptArea.removeHighlightText();
                        }
                    }
                });
            }
        }
    }

    class EJBQLValidationThread extends Thread {

        volatile boolean running;
        final Object timer = new Object();
        int previousCaretPosition;
        int validateCaretPosition;

        static final int DELAY = 500;

        EJBQLValidationThread() {
            super("ejbql-validation-thread");
            setDaemon(true);
        }

        public void run() {
            running = true;
            while (running) {
                int caretPosition = scriptArea.getCaretPosition();
                if (previousCaretPosition != 0 && previousCaretPosition == caretPosition
                        && validateCaretPosition != previousCaretPosition) {
                    validateEJBQL();
                    validateCaretPosition = caretPosition;
                }
                previousCaretPosition = caretPosition;
                synchronized (timer) {
                    try {
                        timer.wait(DELAY);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        }

        void terminate() {
            synchronized (timer) {
                running = false;
                timer.notify();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy