/* * Copyright 2007 - 2017 the original author or authors. * * Licensed 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 net.sf.jailer.ui; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import net.sf.jailer.datamodel.DataModel; import net.sf.jailer.modelbuilder.ModelBuilder; import net.sf.jailer.util.Pair; /** * Data Model Management dialog. * * @author Ralf Wisser */ public abstract class DataModelManagerDialog extends javax.swing.JFrame { /** * <code>true</code> if a model is selected. */ public boolean hasSelectedModel = false; /** * List of available models. */ private List<String> modelList; /** * Model details as pair of folder-name and last-modified timestamp. */ private Map<String, Pair<String, Long>> modelDetails; /** * Currently selected connection. */ private String currentModel; /** * Creates new. */ public DataModelManagerDialog(String applicationName) { this.applicationName = applicationName; initComponents(); InfoBar infoBar = new InfoBar("Data Model Configuration", "A data model is a set of interrelated tables. Acquire information about tables by analyzing\n" + "database schemas, or use the data model editor to manually define tables and associations.\n" + "Select a data model to work with."); UIUtil.replace(infoBarLabel, infoBar); String modelpath = CommandLineInstance.getExecutionContext().getQualifiedDatamodelFolder(); try { modelpath = new File(modelpath).getAbsolutePath(); } catch (Throwable t) { // use default modelpath } locationLabel.setText(modelpath); locationLabel.setToolTipText(modelpath); try { ImageIcon imageIcon = new ImageIcon(getClass().getResource("/net/sf/jailer/ui/resource/jailer.png")); setIconImage(imageIcon.getImage()); infoBar.setIcon(imageIcon); } catch (Throwable t) { try { ImageIcon imageIcon = new ImageIcon(getClass().getResource("/net/sf/jailer/ui/resource/jailer.gif")); setIconImage(imageIcon.getImage()); infoBar.setIcon(imageIcon); } catch (Throwable t2) { } } loadModelList(); initTableModel(); final TableCellRenderer defaultTableCellRenderer = dataModelsTable .getDefaultRenderer(String.class); dataModelsTable.setShowGrid(false); dataModelsTable.setDefaultRenderer(Object.class, new TableCellRenderer() { public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component render = defaultTableCellRenderer .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (render instanceof JLabel && !isSelected) { final Color BG1 = new Color(255, 255, 255); final Color BG2 = new Color(230, 255, 255); ((JLabel) render) .setBackground((row % 2 == 0) ? BG1 : BG2); } return render; } }); dataModelsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); dataModelsTable.getSelectionModel().addListSelectionListener( new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent evt) { if (dataModelsTable.getSelectedRow() >= 0) { currentModel = modelList.get(dataModelsTable.getSelectedRow()); } else { currentModel = null; } refresh(); } }); dataModelsTable.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent me) { JTable table =(JTable) me.getSource(); Point p = me.getPoint(); int row = table.rowAtPoint(p); if (me.getClickCount() >= 2) { table.getSelectionModel().setSelectionInterval(row, row); if (row >= 0) { currentModel = modelList.get(row); } else { currentModel = null; } refresh(); if (currentModel != null) { okButtonActionPerformed(null); } } } }); currentModel = restore(); if (currentModel != null) { int i = modelList.indexOf(currentModel); if (i >= 0) { dataModelsTable.getSelectionModel().setSelectionInterval(i, i); } else { currentModel = null; } } setTitle(applicationName); setLocation(80, 130); pack(); setSize(Math.max(740, getWidth()), 360); refresh(); UIUtil.initPeer(); okButton.grabFocus(); } private void loadModelList() { DataModelManager.setCurrentModelSubfolder(null); modelList = new ArrayList<String>(); modelDetails = new HashMap<String, Pair<String,Long>>(); for (String mf: DataModelManager.getModelFolderNames()) { String modelFolder = mf == null? "" : mf; modelList.add(modelFolder); modelDetails.put(modelFolder, DataModelManager.getModelDetails(mf)); } Collections.sort(modelList, new Comparator<String>() { @Override public int compare(String o1, String o2) { return modelDetails.get(o1).a.compareTo(modelDetails.get(o2).a); } }); } /** * Initializes the table model. */ private Object[][] initTableModel() { Object[][] data = new Object[modelList.size()][]; int i = 0; for (String model: modelList) { Pair<String, Long> details = modelDetails.get(model); data[i++] = new Object[] { details == null? "" : details.a, model == null || model.length() == 0? "." : model, details == null? "" : toDateAsString(details.b) }; } DefaultTableModel tableModel = new DefaultTableModel(data, new String[] { "Data Model", "Subfolder", "Last Modified" }) { @Override public boolean isCellEditable(int row, int column) { return false; } private static final long serialVersionUID = 1535384744352159695L; }; dataModelsTable.setModel(tableModel); return data; } private String toDateAsString(Long time) { if (time == null) { return ""; } return SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT).format(new Date(time)); } private boolean inRefresh = false; /** * Application name. Used to create the name of the demo database alias. */ private final String applicationName; /** * Refreshes the dialog after model changes. */ private void refresh() { if (inRefresh) return; inRefresh = true; try { String theModel = currentModel; Object[][] data = initTableModel(); currentModel = theModel; if (currentModel != null) { int i = modelList.indexOf(currentModel); if (i >= 0) { dataModelsTable.getSelectionModel().setSelectionInterval(i, i); } else { dataModelsTable.getSelectionModel().clearSelection(); currentModel = null; } } else { dataModelsTable.getSelectionModel().clearSelection(); } for (int i = 0; i < dataModelsTable.getColumnCount(); i++) { TableColumn column = dataModelsTable.getColumnModel().getColumn(i); int width = 1; Component comp = dataModelsTable.getDefaultRenderer(String.class). getTableCellRendererComponent( dataModelsTable, column.getHeaderValue(), false, false, 0, i); width = Math.max(width, comp.getPreferredSize().width); for (int line = 0; line < data.length; ++line) { comp = dataModelsTable.getDefaultRenderer(String.class). getTableCellRendererComponent( dataModelsTable, data[line][i], false, false, line, i); width = Math.max(width, comp.getPreferredSize().width); } column.setPreferredWidth(width); } editButton.setEnabled(currentModel != null); deleteButton.setEnabled(currentModel != null); okButton.setEnabled(currentModel != null); analyzeButton.setEnabled(currentModel != null); } finally { inRefresh = false; } } /** * File to store selection. */ private static String MODEL_SELECTION_FILE = ".selecteddatamodel"; /** * Stores the selection. */ private void store() { if (currentModel != null) { try { File file = new File(MODEL_SELECTION_FILE); BufferedWriter out = new BufferedWriter(new FileWriter(file)); out.write(currentModel + "\n"); out.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * Restores the selection. */ private String restore() { String selection = null; try { File file = new File(MODEL_SELECTION_FILE); BufferedReader in = new BufferedReader(new FileReader(file)); selection = (String) in.readLine(); in.close(); } catch (Exception e) { // ignore } return selection; } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; jPanel1 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); jPanel4 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); locationLabel = new javax.swing.JLabel(); jButton2 = new javax.swing.JButton(); okButton = new javax.swing.JButton(); jScrollPane2 = new javax.swing.JScrollPane(); dataModelsTable = new javax.swing.JTable(); jPanel3 = new javax.swing.JPanel(); newButton = new javax.swing.JButton(); editButton = new javax.swing.JButton(); analyzeButton = new javax.swing.JButton(); deleteButton = new javax.swing.JButton(); infoBarLabel = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Connect with DB"); getContentPane().setLayout(new java.awt.CardLayout()); jPanel1.setLayout(new java.awt.GridBagLayout()); jPanel2.setLayout(new java.awt.GridBagLayout()); jPanel4.setLayout(new java.awt.GridBagLayout()); jLabel2.setText(" Base Folder: "); jPanel4.add(jLabel2, new java.awt.GridBagConstraints()); locationLabel.setText("jLabel3"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; jPanel4.add(locationLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; jPanel2.add(jPanel4, gridBagConstraints); jButton2.setText(" Cancel "); jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 4); jPanel2.add(jButton2, gridBagConstraints); okButton.setText(" OK "); okButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { okButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4); jPanel2.add(okButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 100; gridBagConstraints.gridwidth = 20; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; jPanel1.add(jPanel2, gridBagConstraints); jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder("Data Models")); dataModelsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null} }, new String [] { "Title 1", "Title 2", "Title 3", "Title 4" } )); jScrollPane2.setViewportView(dataModelsTable); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 20; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; jPanel1.add(jScrollPane2, gridBagConstraints); jPanel3.setLayout(new java.awt.GridBagLayout()); newButton.setText(" New "); newButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { newButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 10; gridBagConstraints.gridy = 10; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.insets = new java.awt.Insets(16, 4, 2, 0); jPanel3.add(newButton, gridBagConstraints); editButton.setText(" Edit "); editButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { editButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 10; gridBagConstraints.gridy = 11; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.insets = new java.awt.Insets(0, 4, 2, 0); jPanel3.add(editButton, gridBagConstraints); analyzeButton.setText(" Analyze Database "); analyzeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { analyzeButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 10; gridBagConstraints.gridy = 30; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.insets = new java.awt.Insets(0, 4, 2, 0); jPanel3.add(analyzeButton, gridBagConstraints); deleteButton.setText(" Delete "); deleteButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { deleteButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 10; gridBagConstraints.gridy = 31; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.insets = new java.awt.Insets(0, 4, 2, 0); jPanel3.add(deleteButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 10; gridBagConstraints.gridy = 20; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; jPanel1.add(jPanel3, gridBagConstraints); infoBarLabel.setText("info bar"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 11; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; jPanel1.add(infoBarLabel, gridBagConstraints); getContentPane().add(jPanel1, "card2"); pack(); }// </editor-fold>//GEN-END:initComponents private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed if (currentModel != null) { if (JOptionPane.showConfirmDialog(this, "Do you really want to delete Data Model \"" + modelDetails.get(currentModel).a + "\"?", "Delete", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { modelList.remove(currentModel); DataModelManager.deleteModel(currentModel); dataModelsTable.getSelectionModel().clearSelection(); refresh(); store(); } } }//GEN-LAST:event_deleteButtonActionPerformed private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newButtonActionPerformed DataModelManager.setCurrentModelSubfolder(null); NewDataModelDialog newDataModelDialog = new NewDataModelDialog(this, modelList); String newName = newDataModelDialog.getNameEntered(); if (newName != null) { try { DataModelManager.createNewModel(newName, newDataModelDialog.getFolderName()); loadModelList(); currentModel = newName; refresh(); store(); } catch (Exception e) { UIUtil.showException(this, "Error", e, UIUtil.EXCEPTION_CONTEXT_USER_ERROR); } } }//GEN-LAST:event_newButtonActionPerformed private void editButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editButtonActionPerformed if (currentModel == null) return; activateCurrentModel(); edit(currentModel.length() == 0? null : currentModel); loadModelList(); refresh(); store(); }//GEN-LAST:event_editButtonActionPerformed private void activateCurrentModel() { DataModelManager.setCurrentModelSubfolder(currentModel.length() == 0? null : currentModel); } private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed hasSelectedModel = false; setVisible(false); dispose(); }//GEN-LAST:event_jButton2ActionPerformed private void analyzeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analyzeButtonActionPerformed activateCurrentModel(); try { DbConnectionDialog dbConnectionDialog = new DbConnectionDialog(this, applicationName, new InfoBar("Connect with Database", "Select a connection to the database to be analyzed, or create a new connection.\n" + "New connections will be assigned to the datamodel \"" + modelDetails.get(currentModel).a + "\".")); if (dbConnectionDialog.connect("Analyze Database")) { List<String> args = new ArrayList<String>(); args.add("build-model-wo-merge"); dbConnectionDialog.addDbArgs(args); DataModel dataModel = new DataModel(CommandLineInstance.getExecutionContext()); AnalyseOptionsDialog analyseOptionsDialog = new AnalyseOptionsDialog(this, dataModel); boolean[] isDefaultSchema = new boolean[1]; String[] defaultSchema = new String[1]; setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); List<String> schemas; try { schemas = dbConnectionDialog.getDBSchemas(defaultSchema); } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } if (analyseOptionsDialog.edit(schemas, defaultSchema[0], isDefaultSchema, dbConnectionDialog.currentConnection.user)) { String schema = analyseOptionsDialog.getSelectedSchema(); if (schema != null) { args.add("-schema"); args.add(schema); } if (!isDefaultSchema[0]) { args.add("-qualifyNames"); } analyseOptionsDialog.appendAnalyseCLIOptions(args); ModelBuilder.assocFilter = analyseOptionsDialog.getAssociationLineFilter(); if (UIUtil.runJailer(this, args, false, true, false, true, null, dbConnectionDialog.getPassword(), null, null, false, true, false)) { ModelBuilder.assocFilter = null; String modelname = dataModel.getName(); DataModelEditor dataModelEditor = new DataModelEditor(this, true, analyseOptionsDialog.isRemoving(), null, analyseOptionsDialog.getTableLineFilter(), analyseOptionsDialog.getAssociationLineFilter(), modelname, schema == null? dbConnectionDialog.getName() : schema); if (dataModelEditor.dataModelHasChanged()) { dataModelEditor.setVisible(true); } } loadModelList(); refresh(); store(); } } } catch (Exception e) { UIUtil.showException(this, "Error", e); } finally { ModelBuilder.assocFilter = null; } }//GEN-LAST:event_analyzeButtonActionPerformed /** * Opens data model editor. */ private void edit(String modelFolder) { try { DataModelEditor dataModelEditor = new DataModelEditor(this, false, false, null, null, null, modelDetails.get(modelFolder == null? "" : modelFolder).a, null); dataModelEditor.setVisible(true); } catch (Exception e) { UIUtil.showException(this, "Error", e); } } private void okButtonActionPerformed(java.awt.event.ActionEvent evt) { if (currentModel == null) { return; } activateCurrentModel(); hasSelectedModel = true; setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); store(); onSelect(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); setVisible(false); dispose(); }// GEN-LAST:event_okButtonActionPerformed protected abstract void onSelect(); // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton analyzeButton; private javax.swing.JTable dataModelsTable; private javax.swing.JButton deleteButton; private javax.swing.JButton editButton; private javax.swing.JLabel infoBarLabel; private javax.swing.JButton jButton2; private javax.swing.JLabel jLabel2; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JLabel locationLabel; private javax.swing.JButton newButton; private javax.swing.JButton okButton; // End of variables declaration//GEN-END:variables private static final long serialVersionUID = -3983034803834547687L; }