Author: thomasobrien95
Date: Thu May  7 12:46:36 2009
New Revision: 3043

Modified:
   trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java
   trunk/src/ca/sqlpower/architect/swingui/DBTree.java
   trunk/src/ca/sqlpower/architect/swingui/olap/CubeEditPanel.java
   trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
   trunk/src/ca/sqlpower/architect/swingui/olap/OSUtils.java
   trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java
   trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateCubeAction.java
   trunk/src/ca/sqlpower/architect/swingui/olap/action/EditCubeAction.java

Log:
Added the ability to create a cube from a view. A ViewEntryPanel was
created in the CubeEditPanel which uses parts from the
SQLQueryUIComponents. The ViewEntryPanel allows users to see the
results of their query while they are building their view to understand
what they are creating.
This entry panel may be useful later to create views in the relational editor.

Modified: trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java  (original)
+++ trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java Thu May 7 12:46:36 2009
@@ -20,10 +20,17 @@
 package ca.sqlpower.architect.olap;

 import java.beans.PropertyChangeListener;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;

+import org.apache.log4j.Logger;
+
 import ca.sqlpower.architect.ArchitectUtils;
 import ca.sqlpower.architect.olap.MondrianModel.Cube;
 import ca.sqlpower.architect.olap.MondrianModel.CubeDimension;
@@ -41,9 +48,10 @@
 import ca.sqlpower.architect.olap.MondrianModel.View;
 import ca.sqlpower.architect.olap.MondrianModel.VirtualCube;
 import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeDimension;
-import ca.sqlpower.sqlobject.SQLObjectException;
 import ca.sqlpower.sqlobject.SQLCatalog;
+import ca.sqlpower.sqlobject.SQLColumn;
 import ca.sqlpower.sqlobject.SQLDatabase;
+import ca.sqlpower.sqlobject.SQLObjectException;
 import ca.sqlpower.sqlobject.SQLObjectUtils;
 import ca.sqlpower.sqlobject.SQLSchema;
 import ca.sqlpower.sqlobject.SQLTable;
@@ -52,6 +60,8 @@
* A collection of static utility methods for working with the OLAP classes.
  */
 public class OLAPUtil {
+
+    private static final Logger logger = Logger.getLogger(OLAPUtil.class);

     private OLAPUtil() {
         throw new AssertionError("Don't instantiate this class");
@@ -310,7 +320,55 @@
         } else if (relation instanceof Table) {
             return getSQLTableFromOLAPTable(database, (Table) relation);
         } else if (relation instanceof View) {
- throw new UnsupportedOperationException("Views not implemented yet");
+            if (((View) relation).getSelects().isEmpty()) {
+                return null;
+            }
+ String sql = ((View) relation).getSelects().get(0).getText(); //TODO: Handle having multiple selects in one relation.
+            Connection con = null;
+            Statement stmt = null;
+            ResultSet rs = null;
+            try {
+                con = database.getConnection();
+                stmt = con.createStatement();
+                stmt.setMaxRows(0);
+                rs = stmt.executeQuery(sql);
+                SQLTable table = new SQLTable(database, true);
+                ResultSetMetaData rsmd = rs.getMetaData();
+
+                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
+                    SQLColumn column = new SQLColumn(table,
+                            rsmd.getColumnLabel(i), rsmd.getColumnType(i),
+                            rsmd.getPrecision(i), rsmd.getScale(i));
+                    table.addColumn(column);
+                }
+
+                return table;
+            } catch (SQLException e) {
+ logger.error("Creating a view on the database " + database.getName() + " running the statement " + sql + " caused an exception.", e); + throw new RuntimeException("Creating a view on the database " + database.getName() + " caused an exception.", e);
+            } finally {
+                if (rs != null) {
+                    try {
+                        rs.close();
+                    } catch (SQLException e) {
+ logger.error("Exception while trying to close a result set used to create a view's table.", e);
+                    }
+                }
+                if (stmt != null) {
+                    try {
+                        stmt.close();
+                    } catch (SQLException e) {
+ logger.error("Exception while trying to close a statement used to create a view's table.", e);
+                    }
+                }
+                if (con != null) {
+                    try {
+                        con.close();
+                    } catch (SQLException e) {
+ logger.error("Exception while trying to close a connection used to create a view's table.", e);
+                    }
+                }
+            }
         } else if (relation instanceof InlineTable) {
throw new UnsupportedOperationException("Inline tables not implemented yet");
         } else if (relation instanceof Join) {

Modified: trunk/src/ca/sqlpower/architect/swingui/DBTree.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/DBTree.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/DBTree.java Thu May 7 12:46:36 2009
@@ -105,6 +105,11 @@
     protected Action expandAllAction;
        protected SetConnAsTargetDB setConnAsTargetDB;
        protected SelectAllChildTablesAction selectAllChildTablesAction;
+       /**
+        * A flag that if true, then popup menus will be displayed
+        * when DBTree is right-clicked.
+        */
+       private boolean popupMenuEnabled = true;

     /**
      * The architect session, so we can access common objects
@@ -330,9 +335,11 @@
                                    setSelectionPath(p);
                                }
                                
-                               popup = refreshMenu(p);
-                popup.show(e.getComponent(),
-                           e.getX(), e.getY());
+                               if (popupMenuEnabled) {
+                               popup = refreshMenu(p);
+                    popup.show(e.getComponent(),
+                               e.getX(), e.getY());
+                               }
             } else {
if ( p == null && !isPress && e.getButton() == MouseEvent.BUTTON1 )
                     setSelectionPath(null);
@@ -1059,6 +1066,16 @@
         return new TreePath(path.toArray());
     }

+    public void setPopupMenuEnabled(boolean popupMenuEnabled) {
+        this.popupMenuEnabled = popupMenuEnabled;
+    }
+
+    public boolean isPopupMenuEnabled() {
+        return popupMenuEnabled;
+    }
+
+
+
     protected class ShowInPlayPenAction extends AbstractAction {
         public ShowInPlayPenAction() {
super(Messages.getString("DBTree.showInPlaypenAction")); //$NON-NLS-1$

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/CubeEditPanel.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/CubeEditPanel.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/CubeEditPanel.java Thu May 7 12:46:36 2009
@@ -19,7 +19,10 @@

 package ca.sqlpower.architect.swingui.olap;

+import java.awt.Dimension;
 import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;
@@ -27,21 +30,39 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ButtonGroup;
+import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
+import javax.swing.JDialog;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
 import javax.swing.JTextField;
+import javax.swing.JToolBar;
+import javax.swing.tree.TreeModel;

+import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
+
+import ca.sqlpower.architect.olap.OLAPSession;
 import ca.sqlpower.architect.olap.OLAPUtil;
 import ca.sqlpower.architect.olap.MondrianModel.Cube;
 import ca.sqlpower.architect.olap.MondrianModel.Measure;
+import ca.sqlpower.architect.olap.MondrianModel.SQL;
 import ca.sqlpower.architect.olap.MondrianModel.Table;
+import ca.sqlpower.architect.olap.MondrianModel.View;
+import ca.sqlpower.architect.swingui.ArchitectSwingSession;
+import ca.sqlpower.architect.swingui.DBTree;
+import ca.sqlpower.architect.swingui.dbtree.DBTreeModel;
+import ca.sqlpower.sqlobject.SQLDatabase;
 import ca.sqlpower.sqlobject.SQLObjectException;
+import ca.sqlpower.sqlobject.SQLObjectRoot;
 import ca.sqlpower.sqlobject.SQLTable;
+import ca.sqlpower.swingui.DataEntryPanel;
+import ca.sqlpower.swingui.DataEntryPanelBuilder;
+import ca.sqlpower.swingui.query.SQLQueryUIComponents;
 import ca.sqlpower.validation.Validator;
 import ca.sqlpower.validation.swingui.FormValidationHandler;
 import ca.sqlpower.validation.swingui.StatusComponent;
@@ -53,6 +74,107 @@

 public class CubeEditPanel implements ValidatableDataEntryPanel {

+    /**
+     * This entry panel will create a view builder based on the
+     * SQLQueryUIComponents in the library.
+     */
+    private class ViewEntryPanel implements DataEntryPanel {
+
+        /**
+         * The main panel of this data entry panel
+         */
+        private JSplitPane splitPane;
+
+        /**
+         * The text area users will enter a select statement into.
+         */
+        private RSyntaxTextArea queryArea;
+
+        /**
+         * The query components used to create the view. This needs
+         * to be closed when the entry panel goes away or else connections
+         * will be leaked.
+         */
+        private SQLQueryUIComponents queryComponents;
+
+        public ViewEntryPanel(ArchitectSwingSession session) {
+ DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout("pref, 5dlu:grow, pref, 3dlu, pref", "pref, fill:pref:grow"));
+
+ SQLDatabase db = OSUtils.getAncestor(CubeEditPanel.this.cube, OLAPSession.class).getDatabase(); + queryComponents = new SQLQueryUIComponents(session, session.getContext().getPlDotIni(), session, builder.getPanel()); + queryComponents.getRowLimitSpinner().setValue(Integer.valueOf(1000)); + queryComponents.getDatabaseComboBox().setSelectedItem(db.getDataSource());
+
+            JToolBar toolbar = new JToolBar();
+            toolbar.add(queryComponents.getPrevQueryButton());
+            toolbar.add(queryComponents.getNextQueryButton());
+            toolbar.addSeparator();
+            toolbar.add(queryComponents.getExecuteButton());
+            toolbar.add(queryComponents.getStopButton());
+            toolbar.add(queryComponents.getClearButton());
+            toolbar.addSeparator();
+            toolbar.add(queryComponents.getUndoButton());
+            toolbar.add(queryComponents.getRedoButton());
+            toolbar.addSeparator();
+            toolbar.add(new JLabel(db.getName()));
+            builder.append(toolbar);
+ builder.append("Row Limit", queryComponents.getRowLimitSpinner());
+            builder.nextLine();
+
+            queryArea = queryComponents.getQueryArea();
+            builder.append(new JScrollPane(queryArea), 5);
+            queryArea.setText(selectStatements.getText());
+
+ JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+            rightSplitPane.setTopComponent(builder.getPanel());
+ rightSplitPane.setBottomComponent(queryComponents.getResultTabPane()); + rightSplitPane.setPreferredSize(new Dimension((int) Math.max(400, rightSplitPane.getPreferredSize().getWidth()), (int) Math.max(500, rightSplitPane.getPreferredSize().getHeight())));
+            rightSplitPane.setResizeWeight(0.5);
+
+            SQLObjectRoot root = new SQLObjectRoot();
+            TreeModel treeModel;
+            DBTree tree;
+            try {
+                root.addChild(db);
+                treeModel = new DBTreeModel(root);
+                tree = new DBTree(session);
+            } catch (SQLObjectException e) {
+                throw new RuntimeException(e);
+            }
+            tree.setModel(treeModel);
+            tree.setPopupMenuEnabled(false);
+
+            splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+            splitPane.setLeftComponent(tree);
+            splitPane.setRightComponent(rightSplitPane);
+            splitPane.setResizeWeight(0.2);
+
+        }
+
+        public boolean applyChanges() {
+            selectStatements.setText(queryArea.getText());
+            cleanup();
+            return true;
+        }
+
+        public void discardChanges() {
+            cleanup();
+        }
+
+        private void cleanup() {
+            queryComponents.closingDialogOwner();
+        }
+
+        public JComponent getPanel() {
+            return splitPane;
+        }
+
+        public boolean hasUnsavedChanges() {
+            return true;
+        }
+
+    }
+
     private final Cube cube;
     private final JPanel panel;
     private JTextField nameField;
@@ -76,7 +198,7 @@
      *
      * @param cube The data model of the cube to edit
      */
-    public CubeEditPanel(Cube cube) throws SQLObjectException {
+ public CubeEditPanel(Cube cube, final ArchitectSwingSession session) throws SQLObjectException {
         this.cube = cube;

         List<SQLTable> tables = OLAPUtil.getAvailableTables(cube);
@@ -127,11 +249,25 @@
         builder.append(viewRadioButton, 3);
         builder.append("Alias", viewAlias = new JTextField());
         builder.append(new JLabel("SELECT Statements"), 3);
- builder.append(new JScrollPane(selectStatements = new JTextArea("Adding View as a source table in a cube" +
-                       " has not yet been implemented", 4, 30)), 3);
+ builder.append(new JScrollPane(selectStatements = new JTextArea("", 4, 30)), 3);
+        builder.append(new JButton(new AbstractAction("Edit...") {
+            public void actionPerformed(ActionEvent e) {
+ JDialog dialog = DataEntryPanelBuilder.createDataEntryPanelDialog(new ViewEntryPanel(session), null, "View Builder", "OK");
+                dialog.pack();
+                dialog.setVisible(true);
+            }
+        }));
         selectStatements.setLineWrap(true);
+        selectStatements.setEditable(false);

-        if (tables.isEmpty()) {
+        if (cube.getFact() instanceof View) {
+            viewRadioButton.doClick();
+            tableRadioButton.setEnabled(false);
+            tableChooser.setEnabled(false);
+            for (SQL sql : ((View) cube.getFact()).getSelects()) {
+                selectStatements.append(sql.getText() + "\n");
+            }
+        } else if (tables.isEmpty()) {
             tableChooser.addItem("Database has no tables");
             viewRadioButton.doClick();
             tableRadioButton.setEnabled(false);
@@ -154,6 +290,15 @@
         handler = new FormValidationHandler(status);
Validator validator = new OLAPObjectNameValidator(cube.getParent(), cube, false);
         handler.addValidateObject(nameField, validator);
+
+        selectStatements.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseReleased(MouseEvent e) {
+ JDialog dialog = DataEntryPanelBuilder.createDataEntryPanelDialog(new ViewEntryPanel(session), null, "View Builder", "OK");
+                dialog.pack();
+                dialog.setVisible(true);
+            }
+        });
     }

     public boolean applyChanges() {
@@ -170,10 +315,12 @@
                     }
                 }
             } else if (viewRadioButton.isSelected()) {
-                //TODO construct and set up the view
-//                View view = new View();
-//                view.setAlias(viewAlias.getText());
-//                cube.setFact(view);
+                View view = new View();
+                view.setAlias(viewAlias.getText());
+                SQL sql = new SQL();
+                sql.setText(selectStatements.getText());
+                view.addSelect(sql);
+                cube.setFact(view);
             }
             cube.setName(nameField.getText());
             if (!(captionField.getText().equals(""))) {

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java  (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java Thu May 7 12:46:36 2009
@@ -93,7 +93,7 @@
         DataEntryPanel panel;
         // TODO add getName() method to DataEntryPanel.
         if (coord.getIndex() == PlayPenCoordinate.ITEM_INDEX_TITLE) {
-            panel = new CubeEditPanel(model);
+ panel = new CubeEditPanel(model, getParent().getOwner().getSession()); } else if (coord.getIndex() == PlayPenCoordinate.ITEM_INDEX_SECTION_TITLE) {
             panel = null;
         } else if (coord.getIndex() > PlayPenCoordinate.ITEM_INDEX_TITLE){

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/OSUtils.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/OSUtils.java   (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/OSUtils.java Thu May 7 12:46:36 2009
@@ -187,4 +187,22 @@

         return BlankIcon.getInstance(16, 16);
     }
+
+    /**
+ * Returns the first ancestor of <tt>so</tt> which is of the given type, or
+     * <tt>null</tt> if <tt>so</tt> doesn't have an ancestor whose class is
+     * <tt>ancestorType</tt>.
+     *
+     * @param so
+     *            The object for whose ancestor to look. (Thanks, Winston).
+ * @return The nearest ancestor of type ancestorType, or null if no such
+     *         ancestor exists.
+     */
+ public static <T extends OLAPObject> T getAncestor(OLAPObject so, Class<T> ancestorType) {
+        while (so != null) {
+            if (so.getClass().equals(ancestorType)) return (T) so;
+            so = so.getParent();
+        }
+        return null;
+    }
 }

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java Thu May 7 12:46:36 2009
@@ -112,7 +112,7 @@
                 CubeUsage cu = (CubeUsage) coord.getItem();
                 Cube c = OLAPUtil.findReferencedCube(model, cu);
if (c == null) throw new NullPointerException("Couldn't find cube!");
-                panel = new CubeEditPanel(c);
+ panel = new CubeEditPanel(c, getParent().getOwner().getSession());
             } else if (coord.getItem() instanceof VirtualCubeDimension) {
VirtualCubeDimension vcd = (VirtualCubeDimension) coord.getItem();
                 Dimension d = OLAPUtil.findReferencedDimension(vcd);

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateCubeAction.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateCubeAction.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateCubeAction.java Thu May 7 12:46:36 2009
@@ -84,7 +84,7 @@
             playpen.addPlayPenComponent(cp, p);
             cp.setSelected(true,SelectionEvent.SINGLE_SELECT);

-            CubeEditPanel editPanel = new CubeEditPanel(cp.getModel()) {
+ CubeEditPanel editPanel = new CubeEditPanel(cp.getModel(), cp.getParent().getOwner().getSession()) {
                 @Override
                 public void discardChanges() {
                     schema.removeCube(cp.getModel());

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/action/EditCubeAction.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/action/EditCubeAction.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/action/EditCubeAction.java Thu May 7 12:46:36 2009
@@ -54,7 +54,7 @@

     public void actionPerformed(ActionEvent e) {
         try {
-            DataEntryPanel panel = new CubeEditPanel(cube);
+            DataEntryPanel panel = new CubeEditPanel(cube, session);
JDialog dialog = DataEntryPanelBuilder.createDataEntryPanelDialog(panel, dialogOwner, "Cube Properties", "OK");
             dialog.setLocationRelativeTo(session.getArchitectFrame());
             dialog.setVisible(true);

Reply via email to