You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/03/05 07:47:32 UTC
[1/4] cayenne git commit: CAY-2407
Repository: cayenne
Updated Branches:
refs/heads/master fd0d06ec9 -> 7758dbf42
CAY-2407
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/8b48c7c6
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/8b48c7c6
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/8b48c7c6
Branch: refs/heads/master
Commit: 8b48c7c6f327e22877a8ddf9b547dea6179fba8f
Parents: 1525bc7
Author: Arseni Bulatski <an...@gmail.com>
Authored: Mon Feb 19 10:48:28 2018 +0300
Committer: Arseni Bulatski <an...@gmail.com>
Committed: Mon Feb 19 10:48:28 2018 +0300
----------------------------------------------------------------------
.../cayenne/map/SQLTemplateDescriptor.java | 41 +++-
.../modeler/editor/SQLTemplateMainTab.java | 116 ++++++++-
.../modeler/editor/SQLTemplateOrderingTab.java | 237 +++++++++++++++++++
.../modeler/editor/SQLTemplatePrefetchTab.java | 236 ++++++++++++++++++
.../modeler/editor/SQLTemplateTabbedView.java | 7 +
.../AddPrefetchUndoableEditForSqlTemplate.java | 35 +++
6 files changed, 666 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
index e1c3afe..7e449ca 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
@@ -22,9 +22,7 @@ import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.util.XMLEncoder;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeSet;
+import java.util.*;
/**
* @since 4.0
@@ -32,6 +30,7 @@ import java.util.TreeSet;
public class SQLTemplateDescriptor extends QueryDescriptor {
protected String sql;
+ protected List<String> prefetches = new ArrayList<>();
protected Map<String, String> adapterSql = new HashMap<>();
@@ -67,6 +66,34 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
this.adapterSql = adapterSql;
}
+ /**
+ * Returns list of prefetch paths for this query.
+ */
+ public List<String> getPrefetches() {
+ return prefetches;
+ }
+
+ /**
+ * Sets list of prefetch paths for this query.
+ */
+ public void setPrefetches(List<String> prefetches) {
+ this.prefetches = prefetches;
+ }
+
+ /**
+ * Adds single prefetch path to this query.
+ */
+ public void addPrefetch(String prefetchPath) {
+ this.prefetches.add(prefetchPath);
+ }
+
+ /**
+ * Removes single prefetch path from this query.
+ */
+ public void removePrefetch(String prefetchPath) {
+ this.prefetches.remove(prefetchPath);
+ }
+
@Override
public SQLTemplate buildQuery() {
SQLTemplate template = new SQLTemplate();
@@ -77,6 +104,14 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
template.initWithProperties(this.getProperties());
+ List<String> prefetches = this.getPrefetches();
+
+ if (prefetches != null && !prefetches.isEmpty()) {
+ for (String prefetch : prefetches) {
+ template.addPrefetch(prefetch);
+ }
+ }
+
// init SQL
template.setDefaultTemplate(this.getSql());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
index 387391c..78ef8d0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
@@ -25,22 +25,35 @@ import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import org.apache.cayenne.configuration.event.QueryEvent;
import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.util.CellRenderers;
+import org.apache.cayenne.modeler.util.Comparators;
import org.apache.cayenne.modeler.util.ProjectUtil;
import org.apache.cayenne.modeler.util.TextAdapter;
+import org.apache.cayenne.modeler.util.combo.AutoCompletion;
import org.apache.cayenne.project.extension.info.ObjectInfo;
import org.apache.cayenne.query.CapsStrategy;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.util.Util;
import org.apache.cayenne.validation.ValidationException;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import java.awt.BorderLayout;
+import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -69,12 +82,14 @@ public class SQLTemplateMainTab extends JPanel {
protected ProjectController mediator;
protected TextAdapter name;
protected TextAdapter comment;
+ protected JComboBox<ObjEntity> queryRoot;
protected SelectPropertiesPanel properties;
public SQLTemplateMainTab(ProjectController mediator) {
this.mediator = mediator;
initView();
+ initController();
}
private void initView() {
@@ -93,13 +108,17 @@ public class SQLTemplateMainTab extends JPanel {
}
};
+ queryRoot = Application.getWidgetFactory().createComboBox();
+ AutoCompletion.enable(queryRoot);
+ queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
+
properties = new SQLTemplateQueryPropertiesPanel(mediator);
// assemble
CellConstraints cc = new CellConstraints();
FormLayout layout = new FormLayout(
"right:max(80dlu;pref), 3dlu, fill:max(200dlu;pref)",
- "p, 3dlu, p, 3dlu, p");
+ "p, 3dlu, p, 3dlu, p, 3dlu, p");
PanelBuilder builder = new PanelBuilder(layout);
builder.setDefaultDialogBorder();
@@ -108,12 +127,22 @@ public class SQLTemplateMainTab extends JPanel {
builder.add(name.getComponent(), cc.xy(3, 3));
builder.addLabel("Comment:", cc.xy(1, 5));
builder.add(comment.getComponent(), cc.xy(3, 5));
+ builder.addLabel("Query Root:", cc.xy(1, 7));
+ builder.add(queryRoot, cc.xy(3, 7));
this.setLayout(new BorderLayout());
this.add(builder.getPanel(), BorderLayout.NORTH);
this.add(properties, BorderLayout.CENTER);
}
+ private void initController() {
+ RootSelectionHandler rootHandler = new RootSelectionHandler();
+
+ queryRoot.addActionListener(rootHandler);
+ queryRoot.addFocusListener(rootHandler);
+ queryRoot.getEditor().getEditorComponent().addFocusListener(rootHandler);
+ }
+
/**
* Updates the view from the current model state. Invoked when a currently displayed
* query is changed.
@@ -130,6 +159,17 @@ public class SQLTemplateMainTab extends JPanel {
properties.initFromModel(query);
comment.setText(getQueryComment(query));
+ DataMap map = mediator.getCurrentDataMap();
+ ObjEntity[] roots = map.getObjEntities().toArray(new ObjEntity[0]);
+
+ if (roots.length > 1) {
+ Arrays.sort(roots, Comparators.getDataMapChildrenComparator());
+ }
+
+ DefaultComboBoxModel<ObjEntity> model = new DefaultComboBoxModel<>(roots);
+ model.setSelectedItem(query.getRoot());
+ queryRoot.setModel(model);
+
setVisible(true);
}
@@ -177,6 +217,76 @@ public class SQLTemplateMainTab extends JPanel {
}
/**
+ * Handler to user's actions with root selection combobox
+ */
+ class RootSelectionHandler implements FocusListener, ActionListener {
+ String newName = null;
+ boolean needChangeName;
+
+ public void actionPerformed(ActionEvent ae) {
+ QueryDescriptor query = getQuery();
+ if (query != null) {
+ Entity root = (Entity) queryRoot.getModel().getSelectedItem();
+
+ if (root != null) {
+ query.setRoot(root);
+
+ if (needChangeName) { //not changed by user
+ /*
+ * Doing auto name change, following CAY-888 #2
+ */
+ String newPrefix = root.getName() + "Query";
+ newName = newPrefix;
+
+ DataMap map = mediator.getCurrentDataMap();
+ long postfix = 1;
+
+ while (map.getQueryDescriptor(newName) != null) {
+ newName = newPrefix + (postfix++);
+ }
+
+ name.setText(newName);
+ }
+ }
+ }
+ }
+
+ public void focusGained(FocusEvent e) {
+ //reset new name tracking
+ newName = null;
+
+ QueryDescriptor query = getQuery();
+ if (query != null) {
+ needChangeName = hasDefaultName(query);
+ } else {
+ needChangeName = false;
+ }
+ }
+
+ public void focusLost(FocusEvent e) {
+ if (newName != null) {
+ setQueryName(newName);
+ }
+
+ newName = null;
+ needChangeName = false;
+ }
+
+ /**
+ * @return whether specified's query name is 'default' i.e. Cayenne generated
+ * A query's name is 'default' if it starts with 'UntitledQuery' or with root name.
+ *
+ * We cannot follow user input because tab might be opened many times
+ */
+ boolean hasDefaultName(QueryDescriptor query) {
+ String prefix = query.getRoot() == null ? "UntitledQuery" :
+ CellRenderers.asString(query.getRoot()) + "Query";
+
+ return name.getComponent().getText().startsWith(prefix);
+ }
+ }
+
+ /**
* Returns an entity that maps to a procedure query result class.
*/
ObjEntity getEntity(QueryDescriptor query) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
new file mode 100644
index 0000000..c21841d
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
@@ -0,0 +1,237 @@
+/*****************************************************************
+ * 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
+ *
+ * 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 org.apache.cayenne.modeler.editor;
+
+import org.apache.cayenne.configuration.event.QueryEvent;
+import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.map.SQLTemplateDescriptor;
+import org.apache.cayenne.map.SelectQueryDescriptor;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.util.EntityTreeModel;
+import org.apache.cayenne.modeler.util.MultiColumnBrowser;
+import org.apache.cayenne.modeler.util.UIUtil;
+import org.apache.cayenne.query.Ordering;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SortOrder;
+import org.apache.cayenne.swing.components.image.FilteredIconFactory;
+import org.apache.cayenne.util.CayenneMapEntry;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.tree.TreeModel;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.prefs.Preferences;
+
+/**
+ * A panel for picking SQLTemplate orderings.
+ *
+ */
+public class SQLTemplateOrderingTab extends JPanel implements PropertyChangeListener {
+ // property for split pane divider size
+ private static final String SPLIT_DIVIDER_LOCATION_PROPERTY = "query.orderings.divider.location";
+
+ static final Dimension BROWSER_CELL_DIM = new Dimension(150, 100);
+ static final Dimension TABLE_DIM = new Dimension(460, 60);
+
+ static final String PATH_HEADER = "Path";
+ static final String ASCENDING_HEADER = "Ascending";
+ static final String IGNORE_CASE_HEADER = "Ignore Case";
+
+ static final String REAL_PANEL = "real";
+ static final String PLACEHOLDER_PANEL = "placeholder";
+
+ protected ProjectController mediator;
+ protected SQLTemplateDescriptor sqlTemplate;
+
+ protected MultiColumnBrowser browser;
+ protected JTable table;
+
+ protected CardLayout cardLayout;
+ protected JPanel messagePanel;
+
+ public SQLTemplateOrderingTab(ProjectController mediator) {
+ this.mediator = mediator;
+
+ initView();
+ initController();
+ }
+
+ protected void initView() {
+
+ messagePanel = new JPanel(new BorderLayout());
+ cardLayout = new CardLayout();
+
+ Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
+
+ int defLocation = Application.getFrame().getHeight() / 2;
+ int location = detail != null ? detail.getInt(
+ getDividerLocationProperty(),
+ defLocation) : defLocation;
+
+ //As of CAY-888 #3 main pane is now a JSplitPane. Top component is a bit larger.
+ JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+ mainPanel.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, this);
+ mainPanel.setDividerLocation(location);
+
+ mainPanel.setTopComponent(createEditorPanel());
+ mainPanel.setBottomComponent(createSelectorPanel());
+
+ setLayout(cardLayout);
+ add(mainPanel, REAL_PANEL);
+ add(messagePanel, PLACEHOLDER_PANEL);
+ }
+
+ protected void initController() {
+
+ // scroll to selected row whenever a selection even occurs
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+
+ public void valueChanged(ListSelectionEvent e) {
+ if (!e.getValueIsAdjusting()) {
+ UIUtil.scrollToSelectedRow(table);
+ }
+ }
+ });
+ }
+
+ protected void initFromModel() {
+ QueryDescriptor query = mediator.getCurrentQuery();
+
+ if (query == null || !QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) {
+ processInvalidModel("Unknown query.");
+ return;
+ }
+
+ if (!(query.getRoot() instanceof Entity)) {
+ processInvalidModel("SQLTemplate has no root set.");
+ return;
+ }
+
+ this.sqlTemplate = (SQLTemplateDescriptor) query;
+ browser.setModel(createBrowserModel((Entity) sqlTemplate.getRoot()));
+
+ // init column sizes
+ // table.getColumnModel().getColumn(0).setPreferredWidth(250);
+
+ cardLayout.show(this, REAL_PANEL);
+ }
+
+ protected void processInvalidModel(String message) {
+ JLabel messageLabel = new JLabel(message, JLabel.CENTER);
+
+ messagePanel.removeAll();
+ messagePanel.add(messageLabel, BorderLayout.CENTER);
+ cardLayout.show(this, PLACEHOLDER_PANEL);
+ }
+
+ protected JPanel createEditorPanel() {
+
+ table = new JTable();
+ table.setRowHeight(25);
+ table.setRowMargin(3);
+ table.setPreferredScrollableViewportSize(TABLE_DIM);
+ table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(new JScrollPane(table), BorderLayout.CENTER);
+
+ return panel;
+ }
+
+ protected JPanel createSelectorPanel() {
+ browser = new MultiColumnBrowser();
+ browser.setPreferredColumnSize(BROWSER_CELL_DIM);
+ browser.setDefaultRenderer();
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(new JScrollPane(
+ browser,
+ JScrollPane.VERTICAL_SCROLLBAR_NEVER,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
+
+ // setting minimal size, otherwise scrolling looks awful, because of
+ // VERTICAL_SCROLLBAR_NEVER strategy
+ panel.setMinimumSize(panel.getPreferredSize());
+
+ return panel;
+ }
+
+ protected TreeModel createBrowserModel(Entity entity) {
+ return new EntityTreeModel(entity);
+ }
+
+ protected String getSelectedPath() {
+ Object[] path = browser.getSelectionPath().getPath();
+
+ // first item in the path is Entity, so we must have
+ // at least two elements to constitute a valid ordering path
+ if (path.length < 2) {
+ return null;
+ }
+
+ StringBuilder buffer = new StringBuilder();
+
+ // attribute or relationships
+ CayenneMapEntry first = (CayenneMapEntry) path[1];
+ buffer.append(first.getName());
+
+ for (int i = 2; i < path.length; i++) {
+ CayenneMapEntry pathEntry = (CayenneMapEntry) path[i];
+ buffer.append(".").append(pathEntry.getName());
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Updates split pane divider location in properties
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (JSplitPane.DIVIDER_LOCATION_PROPERTY.equals(evt.getPropertyName())) {
+ int value = (Integer) evt.getNewValue();
+
+ Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
+ detail.putInt(getDividerLocationProperty(), value);
+ }
+ }
+
+ /**
+ * Returns name of a property for divider location.
+ */
+ protected String getDividerLocationProperty() {
+ return SPLIT_DIVIDER_LOCATION_PROPERTY;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
new file mode 100644
index 0000000..b9e7147
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
@@ -0,0 +1,236 @@
+/*****************************************************************
+ * 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
+ *
+ * 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 org.apache.cayenne.modeler.editor;
+
+import org.apache.cayenne.configuration.event.QueryEvent;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionException;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.Attribute;
+import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEdit;
+import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEditForSqlTemplate;
+import org.apache.cayenne.modeler.util.CayenneAction;
+import org.apache.cayenne.modeler.util.EntityTreeFilter;
+import org.apache.cayenne.modeler.util.EntityTreeModel;
+import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.swing.components.image.FilteredIconFactory;
+
+import javax.swing.BorderFactory;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JToolBar;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.tree.TreeModel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class SQLTemplatePrefetchTab extends SQLTemplateOrderingTab{
+
+ public SQLTemplatePrefetchTab(ProjectController mediator) {
+ super(mediator);
+ }
+
+ protected JComponent createToolbar() {
+
+ JButton add = new CayenneAction.CayenneToolbarButton(null, 1);
+ add.setText("Add Prefetch");
+ Icon addIcon = ModelerUtil.buildIcon("icon-plus.png");
+ add.setIcon(addIcon);
+ add.setDisabledIcon(FilteredIconFactory.createDisabledIcon(addIcon));
+
+ add.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String prefetch = getSelectedPath();
+
+ if (prefetch == null) {
+ return;
+ }
+
+ addPrefetch(prefetch);
+
+ Application.getInstance().getUndoManager().addEdit(new AddPrefetchUndoableEditForSqlTemplate(prefetch, SQLTemplatePrefetchTab.this));
+ }
+
+ });
+
+ JButton remove = new CayenneAction.CayenneToolbarButton(null, 3);
+ remove.setText("Remove Prefetch");
+ Icon removeIcon = ModelerUtil.buildIcon("icon-trash.png");
+ remove.setIcon(removeIcon);
+ remove.setDisabledIcon(FilteredIconFactory.createDisabledIcon(removeIcon));
+
+ remove.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ int selection = table.getSelectedRow();
+
+ if (selection < 0) {
+ return;
+ }
+
+ String prefetch = (String) table.getModel().getValueAt(selection, 0);
+
+ removePrefetch(prefetch);
+ }
+
+ });
+
+ JToolBar toolBar = new JToolBar();
+ toolBar.setBorder(BorderFactory.createEmptyBorder());
+ toolBar.setFloatable(false);
+ toolBar.add(add);
+ toolBar.add(remove);
+ return toolBar;
+ }
+
+ protected TreeModel createBrowserModel(Entity entity) {
+ EntityTreeModel treeModel = new EntityTreeModel(entity);
+ treeModel.setFilter(
+ new EntityTreeFilter() {
+ public boolean attributeMatch(Object node, Attribute attr) {
+ return false;
+ }
+
+ public boolean relationshipMatch(Object node, Relationship rel) {
+ return true;
+ }
+ });
+ return treeModel;
+ }
+
+ protected TableModel createTableModel() {
+ return new PrefetchModel();
+ }
+
+ public void addPrefetch(String prefetch) {
+
+ // check if such prefetch already exists
+ if (!sqlTemplate.getPrefetches().isEmpty() && sqlTemplate.getPrefetches().contains(prefetch)) {
+ return;
+ }
+
+ sqlTemplate.addPrefetch(prefetch);
+
+ // reset the model, since it is immutable
+ table.setModel(createTableModel());
+
+ mediator.fireQueryEvent(new QueryEvent(this, sqlTemplate));
+ }
+
+ public void removePrefetch(String prefetch) {
+ sqlTemplate.removePrefetch(prefetch);
+
+ // reset the model, since it is immutable
+ table.setModel(createTableModel());
+ mediator.fireQueryEvent(new QueryEvent(this, sqlTemplate));
+ }
+
+ boolean isToMany(String prefetch) {
+ if (sqlTemplate == null) {
+ return false;
+ }
+
+ Object root = sqlTemplate.getRoot();
+
+ // totally invalid path would result in ExpressionException
+ try {
+ Expression exp = ExpressionFactory.exp(prefetch);
+ Object object = exp.evaluate(root);
+ if (object instanceof Relationship) {
+ return ((Relationship) object).isToMany();
+ }
+ else {
+ return false;
+ }
+ }
+ catch (ExpressionException e) {
+ return false;
+ }
+ }
+
+ /**
+ * A table model for the Ordering editing table.
+ */
+ final class PrefetchModel extends AbstractTableModel {
+
+ String[] prefetches;
+
+ PrefetchModel() {
+ if (sqlTemplate != null) {
+ prefetches = new String[sqlTemplate.getPrefetches().size()];
+
+ for (int i = 0; i < prefetches.length; i++) {
+ prefetches[i] = sqlTemplate.getPrefetches().get(i);
+ }
+ }
+ }
+
+ public int getColumnCount() {
+ return 2;
+ }
+
+ public int getRowCount() {
+ return (prefetches != null) ? prefetches.length : 0;
+ }
+
+ public Object getValueAt(int row, int column) {
+ switch (column) {
+ case 0:
+ return prefetches[row];
+ case 1:
+ return isToMany(prefetches[row]) ? Boolean.TRUE : Boolean.FALSE;
+ default:
+ throw new IndexOutOfBoundsException("Invalid column: " + column);
+ }
+ }
+
+ public Class getColumnClass(int column) {
+ switch (column) {
+ case 0:
+ return String.class;
+ case 1:
+ return Boolean.class;
+ default:
+ throw new IndexOutOfBoundsException("Invalid column: " + column);
+ }
+ }
+
+ public String getColumnName(int column) {
+ switch (column) {
+ case 0:
+ return "Prefetch Path";
+ case 1:
+ return "To Many";
+ default:
+ throw new IndexOutOfBoundsException("Invalid column: " + column);
+ }
+ }
+
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateTabbedView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateTabbedView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateTabbedView.java
index 48c7bc7..2862c05 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateTabbedView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateTabbedView.java
@@ -37,6 +37,7 @@ public class SQLTemplateTabbedView extends JTabbedPane {
protected ProjectController mediator;
protected SQLTemplateMainTab mainTab;
protected SQLTemplateScriptsTab scriptsTab;
+ protected SQLTemplatePrefetchTab prefetchTab;
protected int lastSelectionIndex;
public SQLTemplateTabbedView(ProjectController mediator) {
@@ -54,6 +55,9 @@ public class SQLTemplateTabbedView extends JTabbedPane {
this.scriptsTab = new SQLTemplateScriptsTab(mediator);
addTab("SQL Scripts", scriptsTab);
+
+ this.prefetchTab = new SQLTemplatePrefetchTab(mediator);
+ addTab("Prefetches", prefetchTab);
}
private void initController() {
@@ -104,6 +108,9 @@ public class SQLTemplateTabbedView extends JTabbedPane {
case 1:
scriptsTab.initFromModel();
break;
+ case 2:
+ prefetchTab.initFromModel();
+ break;
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b48c7c6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/AddPrefetchUndoableEditForSqlTemplate.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/AddPrefetchUndoableEditForSqlTemplate.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/AddPrefetchUndoableEditForSqlTemplate.java
new file mode 100644
index 0000000..4ab68ac
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/AddPrefetchUndoableEditForSqlTemplate.java
@@ -0,0 +1,35 @@
+package org.apache.cayenne.modeler.undo;
+
+import org.apache.cayenne.modeler.editor.SQLTemplatePrefetchTab;
+import org.apache.cayenne.modeler.editor.SelectQueryPrefetchTab;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+
+public class AddPrefetchUndoableEditForSqlTemplate extends AbstractUndoableEdit {
+
+ private String prefetch;
+ private SQLTemplatePrefetchTab tab;
+
+ public AddPrefetchUndoableEditForSqlTemplate(String prefetch, SQLTemplatePrefetchTab tab) {
+ super();
+ this.prefetch = prefetch;
+ this.tab = tab;
+ }
+
+ @Override
+ public String getPresentationName() {
+ return "Add Prefetch";
+ }
+
+ @Override
+ public void redo() throws CannotRedoException {
+ tab.addPrefetch(prefetch);
+ }
+
+ @Override
+ public void undo() throws CannotUndoException {
+ tab.removePrefetch(prefetch);
+ }
+}
[4/4] cayenne git commit: Remove code duplication in SelectQuery and
SQLTemplate tabs
Posted by nt...@apache.org.
Remove code duplication in SelectQuery and SQLTemplate tabs
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/7758dbf4
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/7758dbf4
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/7758dbf4
Branch: refs/heads/master
Commit: 7758dbf420b1cb611d0710a26304d7d2c34227c7
Parents: f86af37
Author: stariy <st...@gmail.com>
Authored: Mon Mar 5 10:47:08 2018 +0300
Committer: stariy <st...@gmail.com>
Committed: Mon Mar 5 10:47:08 2018 +0300
----------------------------------------------------------------------
.../modeler/editor/BaseQueryMainTab.java | 90 ++++++++++
.../modeler/editor/RootSelectionHandler.java | 86 ++++++++++
.../modeler/editor/SQLTemplateMainTab.java | 169 ++-----------------
.../modeler/editor/SelectQueryMainTab.java | 140 +--------------
4 files changed, 199 insertions(+), 286 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/7758dbf4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/BaseQueryMainTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/BaseQueryMainTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/BaseQueryMainTab.java
new file mode 100644
index 0000000..a1d9033
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/BaseQueryMainTab.java
@@ -0,0 +1,90 @@
+package org.apache.cayenne.modeler.editor;
+
+import org.apache.cayenne.configuration.event.QueryEvent;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.util.CellRenderers;
+import org.apache.cayenne.modeler.util.ProjectUtil;
+import org.apache.cayenne.modeler.util.TextAdapter;
+import org.apache.cayenne.modeler.util.combo.AutoCompletion;
+import org.apache.cayenne.util.Util;
+import org.apache.cayenne.validation.ValidationException;
+
+import javax.swing.*;
+
+abstract class BaseQueryMainTab extends JPanel {
+ protected ProjectController mediator;
+ protected TextAdapter name;
+ protected JComboBox<ObjEntity> queryRoot;
+
+ BaseQueryMainTab(ProjectController mediator) {
+ this.mediator = mediator;
+ }
+
+ protected void initQueryRoot() {
+ queryRoot = Application.getWidgetFactory().createComboBox();
+ AutoCompletion.enable(queryRoot);
+ queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
+
+ RootSelectionHandler rootHandler = new RootSelectionHandler(this);
+
+ queryRoot.addActionListener(rootHandler);
+ queryRoot.addFocusListener(rootHandler);
+ queryRoot.getEditor().getEditorComponent().addFocusListener(rootHandler);
+ }
+
+ public TextAdapter getNameField() {
+ return name;
+ }
+
+ public JComboBox<ObjEntity> getQueryRoot() {
+ return queryRoot;
+ }
+
+ public ProjectController getMediator() {
+ return mediator;
+ }
+
+ /**
+ * Initializes Query name from string.
+ */
+ void setQueryName(String newName) {
+ if (newName != null && newName.trim().length() == 0) {
+ newName = null;
+ }
+
+ QueryDescriptor query = getQuery();
+
+ if (query == null) {
+ return;
+ }
+
+ if (Util.nullSafeEquals(newName, query.getName())) {
+ return;
+ }
+
+ if (newName == null) {
+ throw new ValidationException("SelectQuery name is required.");
+ }
+
+ DataMap map = mediator.getCurrentDataMap();
+ QueryDescriptor matchingQuery = map.getQueryDescriptor(newName);
+
+ if (matchingQuery == null) {
+ // completely new name, set new name for entity
+ QueryEvent e = new QueryEvent(this, query, query.getName());
+ ProjectUtil.setQueryName(map, query, newName);
+ mediator.fireQueryEvent(e);
+ } else if (matchingQuery != query) {
+ // there is a query with the same name
+ throw new ValidationException("There is another query named '"
+ + newName
+ + "'. Use a different name.");
+ }
+ }
+
+ abstract QueryDescriptor getQuery();
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/7758dbf4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/RootSelectionHandler.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/RootSelectionHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/RootSelectionHandler.java
new file mode 100644
index 0000000..8bafed2
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/RootSelectionHandler.java
@@ -0,0 +1,86 @@
+package org.apache.cayenne.modeler.editor;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.modeler.util.CellRenderers;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+/**
+ * Handler to user's actions with root selection combobox
+ */
+class RootSelectionHandler implements FocusListener, ActionListener {
+ private String newName = null;
+ private boolean needChangeName;
+ private final BaseQueryMainTab queryTab;
+
+ RootSelectionHandler(BaseQueryMainTab queryTab) {
+ this.queryTab = queryTab;
+ }
+
+ public void actionPerformed(ActionEvent ae) {
+ QueryDescriptor query = queryTab.getQuery();
+ if (query != null) {
+ Entity root = (Entity) queryTab.getQueryRoot().getModel().getSelectedItem();
+
+ if (root != null) {
+ query.setRoot(root);
+
+ if (needChangeName) { //not changed by user
+ /*
+ * Doing auto name change, following CAY-888 #2
+ */
+ String newPrefix = root.getName() + "Query";
+ newName = newPrefix;
+
+ DataMap map = queryTab.getMediator().getCurrentDataMap();
+ long postfix = 1;
+
+ while (map.getQueryDescriptor(newName) != null) {
+ newName = newPrefix + (postfix++);
+ }
+
+ queryTab.getNameField().setText(newName);
+ }
+ }
+ }
+ }
+
+ public void focusGained(FocusEvent e) {
+ //reset new name tracking
+ newName = null;
+
+ QueryDescriptor query = queryTab.getQuery();
+ if (query != null) {
+ needChangeName = hasDefaultName(query);
+ } else {
+ needChangeName = false;
+ }
+ }
+
+ public void focusLost(FocusEvent e) {
+ if (newName != null) {
+ queryTab.setQueryName(newName);
+ }
+
+ newName = null;
+ needChangeName = false;
+ }
+
+ /**
+ * @return whether specified's query name is 'default' i.e. Cayenne generated
+ * A query's name is 'default' if it starts with 'UntitledQuery' or with root name.
+ *
+ * We cannot follow user input because tab might be opened many times
+ */
+ boolean hasDefaultName(QueryDescriptor query) {
+ String prefix = query.getRoot() == null ? "UntitledQuery" :
+ CellRenderers.asString(query.getRoot()) + "Query";
+
+ return queryTab.getNameField().getComponent().getText().startsWith(prefix);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/7758dbf4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
index 78ef8d0..cbfb99e 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateMainTab.java
@@ -25,34 +25,23 @@ import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import org.apache.cayenne.configuration.event.QueryEvent;
import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.util.CellRenderers;
import org.apache.cayenne.modeler.util.Comparators;
-import org.apache.cayenne.modeler.util.ProjectUtil;
import org.apache.cayenne.modeler.util.TextAdapter;
-import org.apache.cayenne.modeler.util.combo.AutoCompletion;
import org.apache.cayenne.project.extension.info.ObjectInfo;
import org.apache.cayenne.query.CapsStrategy;
import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.util.Util;
-import org.apache.cayenne.validation.ValidationException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;
-import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -61,7 +50,7 @@ import java.util.Map;
* A main panel for editing a SQLTemplate.
*
*/
-public class SQLTemplateMainTab extends JPanel {
+public class SQLTemplateMainTab extends BaseQueryMainTab {
private static final String DEFAULT_CAPS_LABEL = "Database Default";
private static final String LOWER_CAPS_LABEL = "Force Lower Case";
@@ -79,17 +68,14 @@ public class SQLTemplateMainTab extends JPanel {
labelCapsLabels.put(CapsStrategy.UPPER, UPPER_CAPS_LABEL);
}
- protected ProjectController mediator;
- protected TextAdapter name;
protected TextAdapter comment;
- protected JComboBox<ObjEntity> queryRoot;
protected SelectPropertiesPanel properties;
public SQLTemplateMainTab(ProjectController mediator) {
- this.mediator = mediator;
+ super(mediator);
+ initQueryRoot();
initView();
- initController();
}
private void initView() {
@@ -108,10 +94,6 @@ public class SQLTemplateMainTab extends JPanel {
}
};
- queryRoot = Application.getWidgetFactory().createComboBox();
- AutoCompletion.enable(queryRoot);
- queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
-
properties = new SQLTemplateQueryPropertiesPanel(mediator);
// assemble
@@ -135,14 +117,6 @@ public class SQLTemplateMainTab extends JPanel {
this.add(properties, BorderLayout.CENTER);
}
- private void initController() {
- RootSelectionHandler rootHandler = new RootSelectionHandler();
-
- queryRoot.addActionListener(rootHandler);
- queryRoot.addFocusListener(rootHandler);
- queryRoot.getEditor().getEditorComponent().addFocusListener(rootHandler);
- }
-
/**
* Updates the view from the current model state. Invoked when a currently displayed
* query is changed.
@@ -173,120 +147,13 @@ public class SQLTemplateMainTab extends JPanel {
setVisible(true);
}
+ @Override
protected QueryDescriptor getQuery() {
QueryDescriptor query = mediator.getCurrentQuery();
return (query != null && QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) ? query : null;
}
/**
- * Initializes Query name from string.
- */
- void setQueryName(String newName) {
- if (newName != null && newName.trim().length() == 0) {
- newName = null;
- }
-
- QueryDescriptor query = getQuery();
-
- if (query == null) {
- return;
- }
-
- if (Util.nullSafeEquals(newName, query.getName())) {
- return;
- }
-
- if (newName == null) {
- throw new ValidationException("Query name is required.");
- }
-
- DataMap map = mediator.getCurrentDataMap();
-
- if (map.getQueryDescriptor(newName) == null) {
- // completely new name, set new name for entity
- QueryEvent e = new QueryEvent(this, query, query.getName());
- ProjectUtil.setQueryName(map, query, newName);
- mediator.fireQueryEvent(e);
- }
- else {
- // there is a query with the same name
- throw new ValidationException("There is another query named '"
- + newName
- + "'. Use a different name.");
- }
- }
-
- /**
- * Handler to user's actions with root selection combobox
- */
- class RootSelectionHandler implements FocusListener, ActionListener {
- String newName = null;
- boolean needChangeName;
-
- public void actionPerformed(ActionEvent ae) {
- QueryDescriptor query = getQuery();
- if (query != null) {
- Entity root = (Entity) queryRoot.getModel().getSelectedItem();
-
- if (root != null) {
- query.setRoot(root);
-
- if (needChangeName) { //not changed by user
- /*
- * Doing auto name change, following CAY-888 #2
- */
- String newPrefix = root.getName() + "Query";
- newName = newPrefix;
-
- DataMap map = mediator.getCurrentDataMap();
- long postfix = 1;
-
- while (map.getQueryDescriptor(newName) != null) {
- newName = newPrefix + (postfix++);
- }
-
- name.setText(newName);
- }
- }
- }
- }
-
- public void focusGained(FocusEvent e) {
- //reset new name tracking
- newName = null;
-
- QueryDescriptor query = getQuery();
- if (query != null) {
- needChangeName = hasDefaultName(query);
- } else {
- needChangeName = false;
- }
- }
-
- public void focusLost(FocusEvent e) {
- if (newName != null) {
- setQueryName(newName);
- }
-
- newName = null;
- needChangeName = false;
- }
-
- /**
- * @return whether specified's query name is 'default' i.e. Cayenne generated
- * A query's name is 'default' if it starts with 'UntitledQuery' or with root name.
- *
- * We cannot follow user input because tab might be opened many times
- */
- boolean hasDefaultName(QueryDescriptor query) {
- String prefix = query.getRoot() == null ? "UntitledQuery" :
- CellRenderers.asString(query.getRoot()) + "Query";
-
- return name.getComponent().getText().startsWith(prefix);
- }
- }
-
- /**
* Returns an entity that maps to a procedure query result class.
*/
ObjEntity getEntity(QueryDescriptor query) {
@@ -319,7 +186,7 @@ public class SQLTemplateMainTab extends JPanel {
}
final class LabelCapsRenderer extends DefaultListCellRenderer {
-
+ @Override
public Component getListCellRendererComponent(
JList list,
Object object,
@@ -333,22 +200,20 @@ public class SQLTemplateMainTab extends JPanel {
final class SQLTemplateQueryPropertiesPanel extends RawQueryPropertiesPanel {
- private JComboBox labelCase;
+ private JComboBox<CapsStrategy> labelCase;
SQLTemplateQueryPropertiesPanel(ProjectController mediator) {
super(mediator);
}
+ @Override
protected PanelBuilder createPanelBuilder() {
labelCase = Application.getWidgetFactory().createUndoableComboBox();
labelCase.setRenderer(new LabelCapsRenderer());
- labelCase.addActionListener(new ActionListener() {
-
- public void actionPerformed(ActionEvent event) {
- CapsStrategy value = (CapsStrategy) labelCase.getModel().getSelectedItem();
- setQueryProperty(SQLTemplate.COLUMN_NAME_CAPITALIZATION_PROPERTY, value.name());
- }
+ labelCase.addActionListener(event -> {
+ CapsStrategy value = (CapsStrategy) labelCase.getModel().getSelectedItem();
+ setQueryProperty(SQLTemplate.COLUMN_NAME_CAPITALIZATION_PROPERTY, value.name());
});
PanelBuilder builder = super.createPanelBuilder();
@@ -365,25 +230,27 @@ public class SQLTemplateMainTab extends JPanel {
return builder;
}
+ @Override
public void initFromModel(QueryDescriptor query) {
super.initFromModel(query);
if (query != null && QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) {
- DefaultComboBoxModel labelCaseModel = new DefaultComboBoxModel(
- LABEL_CAPITALIZATION);
-
+ DefaultComboBoxModel<CapsStrategy> labelCaseModel = new DefaultComboBoxModel<>(LABEL_CAPITALIZATION);
String columnNameCapitalization = query.getProperty(SQLTemplate.COLUMN_NAME_CAPITALIZATION_PROPERTY);
- labelCaseModel.setSelectedItem(columnNameCapitalization != null ?
- CapsStrategy.valueOf(columnNameCapitalization) : CapsStrategy.DEFAULT);
+ labelCaseModel.setSelectedItem(columnNameCapitalization != null
+ ? CapsStrategy.valueOf(columnNameCapitalization)
+ : CapsStrategy.DEFAULT);
labelCase.setModel(labelCaseModel);
}
}
+ @Override
protected void setEntity(ObjEntity entity) {
SQLTemplateMainTab.this.setEntity(entity);
}
+ @Override
public ObjEntity getEntity(QueryDescriptor query) {
if (query != null && QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) {
return SQLTemplateMainTab.this.getEntity(query);
@@ -399,5 +266,5 @@ public class SQLTemplateMainTab extends JPanel {
setEntity(null);
}
}
- };
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/7758dbf4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SelectQueryMainTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SelectQueryMainTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SelectQueryMainTab.java
index e68d17a..c0bc6d1 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SelectQueryMainTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SelectQueryMainTab.java
@@ -20,10 +20,6 @@
package org.apache.cayenne.modeler.editor;
import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
@@ -31,8 +27,6 @@ import java.util.Iterator;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.cayenne.configuration.event.QueryEvent;
@@ -44,18 +38,14 @@ import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.map.SelectQueryDescriptor;
-import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.swing.components.JCayenneCheckBox;
import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.util.CellRenderers;
import org.apache.cayenne.modeler.util.Comparators;
import org.apache.cayenne.modeler.util.ExpressionConvertor;
-import org.apache.cayenne.modeler.util.ProjectUtil;
import org.apache.cayenne.modeler.util.TextAdapter;
import org.apache.cayenne.modeler.util.ValidatorTextAdapter;
-import org.apache.cayenne.modeler.util.combo.AutoCompletion;
import org.apache.cayenne.project.extension.info.ObjectInfo;
-import org.apache.cayenne.query.*;
import org.apache.cayenne.util.CayenneMapEntry;
import org.apache.cayenne.util.Util;
import org.apache.cayenne.validation.ValidationException;
@@ -68,20 +58,17 @@ import com.jgoodies.forms.layout.FormLayout;
* A tabbed pane that contains editors for various SelectQuery parts.
*
*/
-public class SelectQueryMainTab extends JPanel {
+public class SelectQueryMainTab extends BaseQueryMainTab {
- protected ProjectController mediator;
-
- protected TextAdapter name;
protected TextAdapter comment;
- protected JComboBox<ObjEntity> queryRoot;
protected TextAdapter qualifier;
protected JCheckBox distinct;
protected ObjectQueryPropertiesPanel properties;
public SelectQueryMainTab(ProjectController mediator) {
- this.mediator = mediator;
+ super(mediator);
+ initQueryRoot();
initView();
initController();
}
@@ -96,10 +83,6 @@ public class SelectQueryMainTab extends JPanel {
}
};
- queryRoot = Application.getWidgetFactory().createComboBox();
- AutoCompletion.enable(queryRoot);
- queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
-
qualifier = new ValidatorTextAdapter(new JTextField()) {
@Override
@@ -150,11 +133,6 @@ public class SelectQueryMainTab extends JPanel {
}
private void initController() {
- RootSelectionHandler rootHandler = new RootSelectionHandler();
-
- queryRoot.addActionListener(rootHandler);
- queryRoot.addFocusListener(rootHandler);
- queryRoot.getEditor().getEditorComponent().addFocusListener(rootHandler);
distinct.addItemListener(new ItemListener() {
@@ -215,6 +193,7 @@ public class SelectQueryMainTab extends JPanel {
setVisible(true);
}
+ @Override
protected SelectQueryDescriptor getQuery() {
if(mediator.getCurrentQuery() == null) {
return null;
@@ -277,45 +256,6 @@ public class SelectQueryMainTab extends JPanel {
}
/**
- * Initializes Query name from string.
- */
- void setQueryName(String newName) {
- if (newName != null && newName.trim().length() == 0) {
- newName = null;
- }
-
- QueryDescriptor query = getQuery();
-
- if (query == null) {
- return;
- }
-
- if (Util.nullSafeEquals(newName, query.getName())) {
- return;
- }
-
- if (newName == null) {
- throw new ValidationException("SelectQuery name is required.");
- }
-
- DataMap map = mediator.getCurrentDataMap();
- QueryDescriptor matchingQuery = map.getQueryDescriptor(newName);
-
- if (matchingQuery == null) {
- // completely new name, set new name for entity
- QueryEvent e = new QueryEvent(this, query, query.getName());
- ProjectUtil.setQueryName(map, query, newName);
- mediator.fireQueryEvent(e);
- }
- else if (matchingQuery != query) {
- // there is a query with the same name
- throw new ValidationException("There is another query named '"
- + newName
- + "'. Use a different name.");
- }
- }
-
- /**
* Advanced checking of an expression, needed because Expression.fromString()
* might terminate normally, but returned Expression will not be appliable
* for real Entities.
@@ -351,76 +291,6 @@ public class SelectQueryMainTab extends JPanel {
throw new ValidationException(eex.getUnlabeledMessage());
}
}
-
- /**
- * Handler to user's actions with root selection combobox
- */
- class RootSelectionHandler implements FocusListener, ActionListener {
- String newName = null;
- boolean needChangeName;
-
- public void actionPerformed(ActionEvent ae) {
- QueryDescriptor query = getQuery();
- if (query != null) {
- Entity root = (Entity) queryRoot.getModel().getSelectedItem();
-
- if (root != null) {
- query.setRoot(root);
-
- if (needChangeName) { //not changed by user
- /*
- * Doing auto name change, following CAY-888 #2
- */
- String newPrefix = root.getName() + "Query";
- newName = newPrefix;
-
- DataMap map = mediator.getCurrentDataMap();
- long postfix = 1;
-
- while (map.getQueryDescriptor(newName) != null) {
- newName = newPrefix + (postfix++);
- }
-
- name.setText(newName);
- }
- }
- }
- }
-
- public void focusGained(FocusEvent e) {
- //reset new name tracking
- newName = null;
-
- QueryDescriptor query = getQuery();
- if (query != null) {
- needChangeName = hasDefaultName(query);
- } else {
- needChangeName = false;
- }
- }
-
- public void focusLost(FocusEvent e) {
- if (newName != null) {
- setQueryName(newName);
- }
-
- newName = null;
- needChangeName = false;
- }
-
- /**
- * @return whether specified's query name is 'default' i.e. Cayenne generated
- * A query's name is 'default' if it starts with 'UntitledQuery' or with root name.
- *
- * We cannot follow user input because tab might be opened many times
- */
- boolean hasDefaultName(QueryDescriptor query) {
- String prefix = query.getRoot() == null ? "UntitledQuery" :
- CellRenderers.asString(query.getRoot()) + "Query";
-
- return name.getComponent().getText().startsWith(prefix);
- }
- }
private void setQueryComment(String text) {
QueryDescriptor query = getQuery();
[2/4] cayenne git commit: CAY-2407 add prefetch to sqlTemplate in
Modeler
Posted by nt...@apache.org.
CAY-2407 add prefetch to sqlTemplate in Modeler
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/193c6aa4
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/193c6aa4
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/193c6aa4
Branch: refs/heads/master
Commit: 193c6aa4f6221efc7ac9d436fca50e865d63c229
Parents: 8b48c7c
Author: Arseni Bulatski <an...@gmail.com>
Authored: Tue Feb 20 12:39:14 2018 +0300
Committer: Arseni Bulatski <an...@gmail.com>
Committed: Tue Feb 20 13:08:03 2018 +0300
----------------------------------------------------------------------
RELEASE-NOTES.txt | 1 +
.../cayenne/map/QueryDescriptorLoader.java | 1 +
.../cayenne/map/SQLTemplateDescriptor.java | 24 +-
.../org/apache/cayenne/query/SQLTemplate.java | 1 +
.../modeler/editor/SQLTemplateOrderingTab.java | 237 -------------------
.../modeler/editor/SQLTemplatePrefetchTab.java | 193 ++++++++++++++-
6 files changed, 213 insertions(+), 244 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index bcbd440..cfd075a 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -23,6 +23,7 @@ CAY-2395 cdbimport: add option to create project file
CAY-2396 Upgrade maven-assembly-plugin to 3.1.0
CAY-2403 Extract eventbridges to top level
CAY-2404 Move itests to maven-plugins
+CAY-2407 Modeler: add prefetch support for the SQLTemplate query
Bug Fixes:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
index d8370de..8b05207 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
@@ -75,6 +75,7 @@ public class QueryDescriptorLoader {
break;
case QueryDescriptor.SQL_TEMPLATE:
((SQLTemplateDescriptor) descriptor).setSql(sql);
+ ((SQLTemplateDescriptor) descriptor).setPrefetches(prefetches);
((SQLTemplateDescriptor) descriptor).setAdapterSql(adapterSql);
break;
case QueryDescriptor.EJBQL_QUERY:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
index 7e449ca..e3a0709 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
@@ -19,10 +19,15 @@
package org.apache.cayenne.map;
import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.util.XMLEncoder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
/**
* @since 4.0
@@ -102,16 +107,17 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
template.setRoot(root);
}
- template.initWithProperties(this.getProperties());
- List<String> prefetches = this.getPrefetches();
+ List<String> prefetches = this.getPrefetches();
if (prefetches != null && !prefetches.isEmpty()) {
for (String prefetch : prefetches) {
- template.addPrefetch(prefetch);
+ template.addPrefetch(PrefetchTreeNode.withPath(prefetch, PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS));
}
}
+ template.initWithProperties(this.getProperties());
+
// init SQL
template.setDefaultTemplate(this.getSql());
@@ -188,6 +194,16 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
}
}
+ PrefetchTreeNode prefetchTree = new PrefetchTreeNode();
+
+ for (String prefetchPath : prefetches) {
+ PrefetchTreeNode node = prefetchTree.addPath(prefetchPath);
+ node.setSemantics(PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS);
+ node.setPhantom(false);
+ }
+
+ encoder.nested(prefetchTree, delegate);
+
delegate.visitQuery(this);
encoder.end();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
index eed51c1..3a5230f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
@@ -491,6 +491,7 @@ public class SQLTemplate extends AbstractQuery implements ParameterizedQuery {
return metaData.getPrefetchTree();
}
+
/**
* Adds a prefetch.
*
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
deleted file mode 100644
index c21841d..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplateOrderingTab.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*****************************************************************
- * 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
- *
- * 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 org.apache.cayenne.modeler.editor;
-
-import org.apache.cayenne.configuration.event.QueryEvent;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.QueryDescriptor;
-import org.apache.cayenne.map.SQLTemplateDescriptor;
-import org.apache.cayenne.map.SelectQueryDescriptor;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.MultiColumnBrowser;
-import org.apache.cayenne.modeler.util.UIUtil;
-import org.apache.cayenne.query.Ordering;
-import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.query.SortOrder;
-import org.apache.cayenne.swing.components.image.FilteredIconFactory;
-import org.apache.cayenne.util.CayenneMapEntry;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableModel;
-import javax.swing.tree.TreeModel;
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.prefs.Preferences;
-
-/**
- * A panel for picking SQLTemplate orderings.
- *
- */
-public class SQLTemplateOrderingTab extends JPanel implements PropertyChangeListener {
- // property for split pane divider size
- private static final String SPLIT_DIVIDER_LOCATION_PROPERTY = "query.orderings.divider.location";
-
- static final Dimension BROWSER_CELL_DIM = new Dimension(150, 100);
- static final Dimension TABLE_DIM = new Dimension(460, 60);
-
- static final String PATH_HEADER = "Path";
- static final String ASCENDING_HEADER = "Ascending";
- static final String IGNORE_CASE_HEADER = "Ignore Case";
-
- static final String REAL_PANEL = "real";
- static final String PLACEHOLDER_PANEL = "placeholder";
-
- protected ProjectController mediator;
- protected SQLTemplateDescriptor sqlTemplate;
-
- protected MultiColumnBrowser browser;
- protected JTable table;
-
- protected CardLayout cardLayout;
- protected JPanel messagePanel;
-
- public SQLTemplateOrderingTab(ProjectController mediator) {
- this.mediator = mediator;
-
- initView();
- initController();
- }
-
- protected void initView() {
-
- messagePanel = new JPanel(new BorderLayout());
- cardLayout = new CardLayout();
-
- Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
-
- int defLocation = Application.getFrame().getHeight() / 2;
- int location = detail != null ? detail.getInt(
- getDividerLocationProperty(),
- defLocation) : defLocation;
-
- //As of CAY-888 #3 main pane is now a JSplitPane. Top component is a bit larger.
- JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
- mainPanel.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, this);
- mainPanel.setDividerLocation(location);
-
- mainPanel.setTopComponent(createEditorPanel());
- mainPanel.setBottomComponent(createSelectorPanel());
-
- setLayout(cardLayout);
- add(mainPanel, REAL_PANEL);
- add(messagePanel, PLACEHOLDER_PANEL);
- }
-
- protected void initController() {
-
- // scroll to selected row whenever a selection even occurs
- table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
-
- public void valueChanged(ListSelectionEvent e) {
- if (!e.getValueIsAdjusting()) {
- UIUtil.scrollToSelectedRow(table);
- }
- }
- });
- }
-
- protected void initFromModel() {
- QueryDescriptor query = mediator.getCurrentQuery();
-
- if (query == null || !QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) {
- processInvalidModel("Unknown query.");
- return;
- }
-
- if (!(query.getRoot() instanceof Entity)) {
- processInvalidModel("SQLTemplate has no root set.");
- return;
- }
-
- this.sqlTemplate = (SQLTemplateDescriptor) query;
- browser.setModel(createBrowserModel((Entity) sqlTemplate.getRoot()));
-
- // init column sizes
- // table.getColumnModel().getColumn(0).setPreferredWidth(250);
-
- cardLayout.show(this, REAL_PANEL);
- }
-
- protected void processInvalidModel(String message) {
- JLabel messageLabel = new JLabel(message, JLabel.CENTER);
-
- messagePanel.removeAll();
- messagePanel.add(messageLabel, BorderLayout.CENTER);
- cardLayout.show(this, PLACEHOLDER_PANEL);
- }
-
- protected JPanel createEditorPanel() {
-
- table = new JTable();
- table.setRowHeight(25);
- table.setRowMargin(3);
- table.setPreferredScrollableViewportSize(TABLE_DIM);
- table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(new JScrollPane(table), BorderLayout.CENTER);
-
- return panel;
- }
-
- protected JPanel createSelectorPanel() {
- browser = new MultiColumnBrowser();
- browser.setPreferredColumnSize(BROWSER_CELL_DIM);
- browser.setDefaultRenderer();
-
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(new JScrollPane(
- browser,
- JScrollPane.VERTICAL_SCROLLBAR_NEVER,
- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
-
- // setting minimal size, otherwise scrolling looks awful, because of
- // VERTICAL_SCROLLBAR_NEVER strategy
- panel.setMinimumSize(panel.getPreferredSize());
-
- return panel;
- }
-
- protected TreeModel createBrowserModel(Entity entity) {
- return new EntityTreeModel(entity);
- }
-
- protected String getSelectedPath() {
- Object[] path = browser.getSelectionPath().getPath();
-
- // first item in the path is Entity, so we must have
- // at least two elements to constitute a valid ordering path
- if (path.length < 2) {
- return null;
- }
-
- StringBuilder buffer = new StringBuilder();
-
- // attribute or relationships
- CayenneMapEntry first = (CayenneMapEntry) path[1];
- buffer.append(first.getName());
-
- for (int i = 2; i < path.length; i++) {
- CayenneMapEntry pathEntry = (CayenneMapEntry) path[i];
- buffer.append(".").append(pathEntry.getName());
- }
-
- return buffer.toString();
- }
-
- /**
- * Updates split pane divider location in properties
- */
- public void propertyChange(PropertyChangeEvent evt) {
- if (JSplitPane.DIVIDER_LOCATION_PROPERTY.equals(evt.getPropertyName())) {
- int value = (Integer) evt.getNewValue();
-
- Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
- detail.putInt(getDividerLocationProperty(), value);
- }
- }
-
- /**
- * Returns name of a property for divider location.
- */
- protected String getDividerLocationProperty() {
- return SPLIT_DIVIDER_LOCATION_PROPERTY;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/193c6aa4/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
index b9e7147..0398eee 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/SQLTemplatePrefetchTab.java
@@ -25,32 +25,177 @@ import org.apache.cayenne.exp.ExpressionException;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.map.Attribute;
import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.map.SQLTemplateDescriptor;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEdit;
import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEditForSqlTemplate;
import org.apache.cayenne.modeler.util.CayenneAction;
import org.apache.cayenne.modeler.util.EntityTreeFilter;
import org.apache.cayenne.modeler.util.EntityTreeModel;
import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.util.MultiColumnBrowser;
+import org.apache.cayenne.modeler.util.UIUtil;
import org.apache.cayenne.swing.components.image.FilteredIconFactory;
+import org.apache.cayenne.util.CayenneMapEntry;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
import javax.swing.JToolBar;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.prefs.Preferences;
-public class SQLTemplatePrefetchTab extends SQLTemplateOrderingTab{
+public class SQLTemplatePrefetchTab extends JPanel implements PropertyChangeListener {
+
+ // property for split pane divider size
+ private static final String SPLIT_DIVIDER_LOCATION_PROPERTY = "query.orderings.divider.location";
+
+ static final Dimension BROWSER_CELL_DIM = new Dimension(150, 100);
+ static final Dimension TABLE_DIM = new Dimension(460, 60);
+
+ static final String PATH_HEADER = "Path";
+ static final String ASCENDING_HEADER = "Ascending";
+ static final String IGNORE_CASE_HEADER = "Ignore Case";
+
+ static final String REAL_PANEL = "real";
+ static final String PLACEHOLDER_PANEL = "placeholder";
+
+ protected ProjectController mediator;
+ protected SQLTemplateDescriptor sqlTemplate;
+
+ protected MultiColumnBrowser browser;
+ protected JTable table;
+
+ protected CardLayout cardLayout;
+ protected JPanel messagePanel;
public SQLTemplatePrefetchTab(ProjectController mediator) {
- super(mediator);
+ this.mediator = mediator;
+
+ initView();
+ initController();
+ }
+
+ protected void initView() {
+
+ messagePanel = new JPanel(new BorderLayout());
+ cardLayout = new CardLayout();
+
+ Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
+
+ int defLocation = Application.getFrame().getHeight() / 2;
+ int location = detail != null ? detail.getInt(
+ getDividerLocationProperty(),
+ defLocation) : defLocation;
+
+ //As of CAY-888 #3 main pane is now a JSplitPane. Top component is a bit larger.
+ JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+ mainPanel.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, this);
+ mainPanel.setDividerLocation(location);
+
+ mainPanel.setTopComponent(createEditorPanel());
+ mainPanel.setBottomComponent(createSelectorPanel());
+
+ setLayout(cardLayout);
+ add(mainPanel, REAL_PANEL);
+ add(messagePanel, PLACEHOLDER_PANEL);
+ }
+
+ protected void initController() {
+
+ // scroll to selected row whenever a selection even occurs
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+
+ public void valueChanged(ListSelectionEvent e) {
+ if (!e.getValueIsAdjusting()) {
+ UIUtil.scrollToSelectedRow(table);
+ }
+ }
+ });
+ }
+
+ protected void initFromModel() {
+ QueryDescriptor query = mediator.getCurrentQuery();
+
+ if (query == null || !QueryDescriptor.SQL_TEMPLATE.equals(query.getType())) {
+ processInvalidModel("Unknown query.");
+ return;
+ }
+
+ if (!(query.getRoot() instanceof Entity)) {
+ processInvalidModel("SQLTemplate has no root set.");
+ return;
+ }
+
+ this.sqlTemplate = (SQLTemplateDescriptor) query;
+ browser.setModel(createBrowserModel((Entity) sqlTemplate.getRoot()));
+ table.setModel(createTableModel());
+
+ // init column sizes
+ table.getColumnModel().getColumn(0).setPreferredWidth(250);
+
+ cardLayout.show(this, REAL_PANEL);
+ }
+
+ protected void processInvalidModel(String message) {
+ JLabel messageLabel = new JLabel(message, JLabel.CENTER);
+
+ messagePanel.removeAll();
+ messagePanel.add(messageLabel, BorderLayout.CENTER);
+ cardLayout.show(this, PLACEHOLDER_PANEL);
+ }
+
+ protected JPanel createEditorPanel() {
+
+ table = new JTable();
+ table.setRowHeight(25);
+ table.setRowMargin(3);
+ table.setPreferredScrollableViewportSize(TABLE_DIM);
+ table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(new JScrollPane(table), BorderLayout.CENTER);
+
+ return panel;
+ }
+
+ protected JPanel createSelectorPanel() {
+ browser = new MultiColumnBrowser();
+ browser.setPreferredColumnSize(BROWSER_CELL_DIM);
+ browser.setDefaultRenderer();
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(createToolbar(), BorderLayout.NORTH);
+ panel.add(new JScrollPane(
+ browser,
+ JScrollPane.VERTICAL_SCROLLBAR_NEVER,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
+
+ // setting minimal size, otherwise scrolling looks awful, because of
+ // VERTICAL_SCROLLBAR_NEVER strategy
+ panel.setMinimumSize(panel.getPreferredSize());
+
+ return panel;
}
protected JComponent createToolbar() {
@@ -106,6 +251,29 @@ public class SQLTemplatePrefetchTab extends SQLTemplateOrderingTab{
return toolBar;
}
+ protected String getSelectedPath() {
+ Object[] path = browser.getSelectionPath().getPath();
+
+ // first item in the path is Entity, so we must have
+ // at least two elements to constitute a valid ordering path
+ if (path.length < 2) {
+ return null;
+ }
+
+ StringBuilder buffer = new StringBuilder();
+
+ // attribute or relationships
+ CayenneMapEntry first = (CayenneMapEntry) path[1];
+ buffer.append(first.getName());
+
+ for (int i = 2; i < path.length; i++) {
+ CayenneMapEntry pathEntry = (CayenneMapEntry) path[i];
+ buffer.append(".").append(pathEntry.getName());
+ }
+
+ return buffer.toString();
+ }
+
protected TreeModel createBrowserModel(Entity entity) {
EntityTreeModel treeModel = new EntityTreeModel(entity);
treeModel.setFilter(
@@ -172,6 +340,25 @@ public class SQLTemplatePrefetchTab extends SQLTemplateOrderingTab{
}
/**
+ * Updates split pane divider location in properties
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (JSplitPane.DIVIDER_LOCATION_PROPERTY.equals(evt.getPropertyName())) {
+ int value = (Integer) evt.getNewValue();
+
+ Preferences detail = Application.getInstance().getPreferencesNode(this.getClass(), "");
+ detail.putInt(getDividerLocationProperty(), value);
+ }
+ }
+
+ /**
+ * Returns name of a property for divider location.
+ */
+ protected String getDividerLocationProperty() {
+ return SPLIT_DIVIDER_LOCATION_PROPERTY;
+ }
+
+ /**
* A table model for the Ordering editing table.
*/
final class PrefetchModel extends AbstractTableModel {
[3/4] cayenne git commit: Merge remote-tracking branch
'remotes/parent/pr/274' into asf-master
Posted by nt...@apache.org.
Merge remote-tracking branch 'remotes/parent/pr/274' into asf-master
# Conflicts:
# RELEASE-NOTES.txt
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/f86af37f
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/f86af37f
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/f86af37f
Branch: refs/heads/master
Commit: f86af37f6293494baa2616f67b8447429639724d
Parents: fd0d06e 193c6aa
Author: stariy <st...@gmail.com>
Authored: Mon Mar 5 10:13:29 2018 +0300
Committer: stariy <st...@gmail.com>
Committed: Mon Mar 5 10:13:29 2018 +0300
----------------------------------------------------------------------
RELEASE-NOTES.txt | 1 +
.../cayenne/map/QueryDescriptorLoader.java | 1 +
.../cayenne/map/SQLTemplateDescriptor.java | 51 +++
.../org/apache/cayenne/query/SQLTemplate.java | 1 +
.../modeler/editor/SQLTemplateMainTab.java | 116 ++++-
.../modeler/editor/SQLTemplatePrefetchTab.java | 423 +++++++++++++++++++
.../modeler/editor/SQLTemplateTabbedView.java | 7 +
.../AddPrefetchUndoableEditForSqlTemplate.java | 35 ++
8 files changed, 632 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f86af37f/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --cc RELEASE-NOTES.txt
index af9c490,cfd075a..fd87dd5
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@@ -23,7 -23,7 +23,8 @@@ CAY-2395 cdbimport: add option to creat
CAY-2396 Upgrade maven-assembly-plugin to 3.1.0
CAY-2403 Extract eventbridges to top level
CAY-2404 Move itests to maven-plugins
+CAY-2406 Add prefetch-related API to SQLSelect
+ CAY-2407 Modeler: add prefetch support for the SQLTemplate query
Bug Fixes:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f86af37f/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
----------------------------------------------------------------------