/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package jdbc; import java.awt.event.KeyEvent; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.sql.RowSet; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JToolBar; import ganttChart.GanttExample; import ilog.views.gantt.IlvActivity; import ilog.views.gantt.IlvActivityFactory; import ilog.views.gantt.IlvGanttChart; import ilog.views.gantt.IlvGanttModel; import ilog.views.gantt.IlvHierarchyChart; import ilog.views.gantt.IlvResource; import ilog.views.gantt.IlvResourceFactory; import ilog.views.gantt.IlvTimeInterval; import ilog.views.gantt.action.IlvAction; import ilog.views.gantt.model.table.IlvTableActivity; import ilog.views.gantt.model.table.IlvTableGanttModel; import ilog.views.gantt.model.table.IlvTableResource; import ilog.views.gantt.project.IlvGanttProjectConfiguration; import ilog.views.gantt.property.IlvActivityReservationsProperty; import ilog.views.gantt.property.IlvResourceNameProperty; import ilog.views.gantt.swing.IlvJTableColumn; import ilog.views.gantt.swing.IlvStringColumn; import ilog.views.util.convert.IlvConvert; import ilog.views.util.convert.IlvConvertException; import ilog.views.util.convert.IlvConverter; import ilog.views.util.data.IlvRowSetTableModel; import ilog.views.util.data.IlvTableModelMapper; import ilog.views.util.data.IlvTableModelMappingException; import ilog.views.util.styling.IlvStylingException; import ilog.views.util.swing.IlvSwingUtil; import shared.swing.ExampleFrame; /** * This example shows how to use the ilog.views.gantt.model.table package to * fill Gantt data from a database and conversly update the database on Gantt * chart data changes. This class works together with the JdbcGanttActions * class. */ public class JdbcGanttExample extends GanttExample { /** * The various menu and toolbar actions. */ protected IlvAction commitAction; protected IlvAction rollbackAction; protected IlvAction refreshAction; protected IlvAction reinitAction; protected IlvAction reconnectAction; private Map<? extends Object, Object> helpProperties; /** * Did the connection failed? Not yet. */ boolean tryConnectionFailed = false; /** * Parameters for the database access. */ static final String databaseURL = "jdbc:mysql:///test_ilog_demos"; static final String user = ""; static final String passwd = ""; static final String driverName = "com.mysql.jdbc.Driver"; static final int CACHE_SIZE = Integer.MAX_VALUE; // 0 private static final Class<?>[] from = new Class[] { java.util.Date.class }; private static final Class<?>[] to = new Class[] { Timestamp.class }; // converter that allows to convert Date object created by the Gantt // to objects required by the database type static { IlvConvert.addConverter(new IlvConverter() { Override public Class<?>[] fromTypes() { return from; } Override public Class<?>[] toTypes() { return to; } Override SuppressWarnings("rawtypes") public Object convert(Object value, Class toType) throws IlvConvertException { // this is needed to overcome a mySQL limitation on Timestamp // object precision and to avoid the synchronization problems // it creates with CachedRowsSet return new Timestamp((((java.util.Date) value).getTime() / 1000) * 1000); } }); } /** * Creates the Gantt chart. */ Override protected IlvHierarchyChart createChart() { return new IlvGanttChart() { Override protected IlvJTableColumn[] createDefaultTableColumns() { IlvJTableColumn[] columns = super.createDefaultTableColumns(); // we want to display a Name not an ID for the resource // (id is not very meaningfull in our database table) IlvStringColumn resourceCol = new IlvStringColumn(columns[4].getColumn().getHeaderValue(), new IlvActivityReservationsProperty(this, new IlvResourceNameProperty()), columns[4].getColumn().getIdentifier()); resourceCol.setChildrenEditable(false); resourceCol.setParentsEditable(false); columns[4] = resourceCol; return columns; } }; } /** * Creates and returns the Gantt data model. */ Override protected IlvGanttModel createGanttModel() { try { Class.forName(driverName); } catch (ClassNotFoundException e) { // cannot happen, it is in the class path... } IlvTableModelMapper activityMapper = createActivityMapper(); IlvTableModelMapper constraintMapper = null; IlvTableModelMapper resourceMapper = null; IlvTableModelMapper reservationMapper = null; IlvTableGanttModel model = null; if (activityMapper != null) { constraintMapper = createConstraintMapper(); resourceMapper = createResourceMapper(); reservationMapper = createReservationMapper(); // otherwise no need to bother with other cases as connection is broken } try { // alternatively a ilog.views.gantt.jdbc.IlvJDBCGanttModel could be used // see its javadoc for information on how to use it but then only // autocommit // would be available. model = new IlvTableGanttModel(activityMapper, resourceMapper, constraintMapper, reservationMapper); } catch (IlvTableModelMappingException e) { // should not happen IlvSwingUtil.showErrorDialog(this, e); } return model; } void retryConnection() { if (tryConnectionFailed) { setConnectionFailedStatus(false); tryConnectionFailed = false; IlvTableModelMapper activityMapper = createActivityMapper(); IlvTableModelMapper constraintMapper = null; IlvTableModelMapper resourceMapper = null; IlvTableModelMapper reservationMapper = null; if (activityMapper != null) { constraintMapper = createConstraintMapper(); resourceMapper = createResourceMapper(); reservationMapper = createReservationMapper(); // otherwise no need to bother with other cases as connection is broken } IlvTableGanttModel model = (IlvTableGanttModel) chart.getGanttModel(); model.setActivityMapper(activityMapper); model.setConstraintMapper(constraintMapper); model.setResourceMapper(resourceMapper); model.setReservationMapper(reservationMapper); try { model.initializeMapping(); } catch (IlvTableModelMappingException e) { // should not happen IlvSwingUtil.showErrorDialog(this, e); } } } /** * Creates the activity mapper */ private IlvTableModelMapper createActivityMapper() { IlvTableModelMapper activityMapper = null; try { RowSet rowSet = IlvRowSetTableModel.createRowSet(databaseURL, user, passwd, "select * from activities", false, CACHE_SIZE); IlvRowSetTableModel activities = new IlvRowSetTableModel(rowSet); activityMapper = IlvTableGanttModel.createActivityMapper(activities, 0, 1, 2, 3, 4); } catch (SQLException e) { Logger.getLogger("ganttdemo").log(Level.INFO, e.getMessage(), e); if (!tryConnectionFailed) { // if it did not failed yet IlvSwingUtil.showErrorDialog(this, "cannot connect to the database\n" + "please start the database and try to reconnect"); setConnectionFailedStatus(true); } } return activityMapper; } /** * Creates the constraint mapper */ private IlvTableModelMapper createConstraintMapper() { IlvTableModelMapper constraintMapper = null; try { RowSet rowSet = IlvRowSetTableModel.createRowSet(databaseURL, user, passwd, "select * from constraints", false, CACHE_SIZE); IlvRowSetTableModel constraints = new IlvRowSetTableModel(rowSet); constraintMapper = IlvTableGanttModel.createConstraintMapper(constraints, 0, 1, 2, new Object[] { "Start-Start", "Start-End", "End-Start", "End-End" }); } catch (SQLException e) { Logger.getLogger("ganttdemo").log(Level.INFO, e.getMessage(), e); if (!tryConnectionFailed) { // if it did not failed yet IlvSwingUtil.showErrorDialog(this, "cannot connect to the database\n" + "please start the database and try to reconnect"); setConnectionFailedStatus(true); } } return constraintMapper; } /** * Creates the resource mapper */ private IlvTableModelMapper createResourceMapper() { IlvTableModelMapper resourceMapper = null; try { RowSet rowSet = IlvRowSetTableModel.createRowSet(databaseURL, user, passwd, "select * from resources", false, CACHE_SIZE); IlvRowSetTableModel resources = new IlvRowSetTableModel(rowSet); resourceMapper = IlvTableGanttModel.createResourceMapper(resources, 0, 1, 2, 3); } catch (SQLException e) { Logger.getLogger("ganttdemo").log(Level.INFO, e.getMessage(), e); if (!tryConnectionFailed) { // if it did not failed yet IlvSwingUtil.showErrorDialog(this, "cannot connect to the database\n" + "please start the database and try to reconnect"); setConnectionFailedStatus(true); } } return resourceMapper; } /** * Creates the reservation mapper */ private IlvTableModelMapper createReservationMapper() { IlvTableModelMapper reservationMapper = null; try { RowSet rowSet = IlvRowSetTableModel.createRowSet(databaseURL, user, passwd, "select * from reservations", false, CACHE_SIZE); IlvRowSetTableModel constraints = new IlvRowSetTableModel(rowSet); // in our case first column is activity, second is resource => reverse reservationMapper = IlvTableGanttModel.createReservationMapper(constraints, 1, 0); } catch (SQLException e) { Logger.getLogger("ganttdemo").log(Level.INFO, e.getMessage(), e); if (!tryConnectionFailed) { // if it did not failed yet IlvSwingUtil.showErrorDialog(this, "cannot connect to the database\n" + "please start the database and try to reconnect"); setConnectionFailedStatus(true); } } return reservationMapper; } /** * Change the connection failed status */ private void setConnectionFailedStatus(boolean value) { tryConnectionFailed = value; // update actions depending on the status of the connection if (reconnectAction != null) { reconnectAction.setEnabled(tryConnectionFailed); } if (commitAction != null) { commitAction.setEnabled(!tryConnectionFailed); } if (rollbackAction != null) { rollbackAction.setEnabled(!tryConnectionFailed); } if (refreshAction != null) { refreshAction.setEnabled(!tryConnectionFailed); } if (reinitAction != null) { reinitAction.setEnabled(!tryConnectionFailed); } if (commitAction != null) { commitAction.setEnabled(!tryConnectionFailed); } if (insertRowAction != null) { insertRowAction.setEnabled(!tryConnectionFailed); } if (makeConstraintAction != null) { makeConstraintAction.setEnabled(!tryConnectionFailed); } } Override SuppressWarnings("unused") protected void customizeChart() { if (CACHE_SIZE == 0) { // if no cache we can use auto increment ((IlvTableGanttModel) chart.getGanttModel()).configureHierarchyChart(chart, true); } else { // if there is a cache we can't because the database is not queried // each time a row is added! ((IlvTableGanttModel) chart.getGanttModel()).configureHierarchyChart(chart); // well actually due to Sun BR 6193078 we have to slightly change it, // otherwise we will get NPEs when commiting for the emtpy "originalID" // column chart.setActivityFactory(new ActivityFactory(chart.getActivityFactory())); chart.setResourceFactory(new ResourceFactory(chart.getResourceFactory())); } super.customizeChart(); // Let's take the styling of the chart from a Gantt Designer Project File IlvGanttProjectConfiguration configuration = new IlvGanttProjectConfiguration(); try { // Read the configuration file. URL url = getResourceURL("data/basicGantt.igpr"); configuration.read(url); // get the style from the configuration file String[] stylesheets = configuration.getStyleSheets(); // set the style from the configuration file on the chart itself getChart().setStyleSheets(stylesheets); } catch (MalformedURLException ex) { // cannot happen except if URL is changed IlvSwingUtil.showErrorDialog(this, ex); } catch (IOException e) { // cannot happen except if URL is changed IlvSwingUtil.showErrorDialog(this, e); } catch (IlvStylingException e) { // can happen if CSS content is changed... IlvSwingUtil.showErrorDialog(this, "Styling Exception Occured", e); } } // ========================================= // Menu // ========================================= /** * Initializes the actions for the Edit menu. */ Override protected void initEditActions() { super.initEditActions(); if (insertRowAction != null) { insertRowAction.setEnabled(!tryConnectionFailed); } if (makeConstraintAction != null) { makeConstraintAction.setEnabled(!tryConnectionFailed); } // indexes of activities are created from the ordering of the rows in the // database so remove leveling actions. rowDownAction = null; rowUpAction = null; // action for "Commit" commitAction = new JdbcGanttActions.CommitAction(this); // action for "Rollback" rollbackAction = new JdbcGanttActions.RollbackAction(this); // action for "Refresh" refreshAction = new JdbcGanttActions.RefreshAction(this); // action for "ReInit" reinitAction = new JdbcGanttActions.ReInitAction(this); // action for "ReConnect" reconnectAction = new JdbcGanttActions.ReConnectAction(this); } // Creates and installs the menu bar. Override public JMenuBar createMenuBar() { JMenuBar menu = super.createMenuBar(); // Remove the Exit menu item from the Edit menu. if (isExitAllowed()) { JMenu edit = menu.getMenu(0); edit.remove(edit.getItemCount() - 1); edit.remove(edit.getItemCount() - 1); } // Add the File menu. menu.add(createDatabaseMenu(), 0); return menu; } /** * Creates the "Database" menu. */ public JMenu createDatabaseMenu() { JMenu menu = new JMenu("Database"); menu.setMnemonic(KeyEvent.VK_D); setStatusText(menu, "Database operations"); addAction(menu, reconnectAction); menu.addSeparator(); addAction(menu, commitAction); addAction(menu, rollbackAction); menu.addSeparator(); addAction(menu, refreshAction); addAction(menu, reinitAction); // Menu item for "Exit". if (isExitAllowed()) { menu.addSeparator(); addAction(menu, exitAction); } return menu; } // ========================================= // Toolbar // ========================================= /** * Populates the toolbar file actions. */ Override protected void populateToolBarFileActions(JToolBar toolbar) { if (reconnectAction != null) { addAction(toolbar, reconnectAction); } if (commitAction != null) { addAction(toolbar, commitAction); } if (rollbackAction != null) { addAction(toolbar, rollbackAction); } if (refreshAction != null) { addAction(toolbar, refreshAction); } if (reinitAction != null) { addAction(toolbar, reinitAction); } } // ========================================== // Help Related Methods // ========================================== Override SuppressWarnings("unchecked") protected Map<String, Object> getHelpProperties() { return (Map<String, Object>) helpProperties; } Override protected void initHelpSystem() { helpProperties = new Properties(); InputStream istream = getClass().getResourceAsStream("help/help.properties"); if (istream != null) { try { ((Properties) helpProperties).load(istream); } catch (IOException e) { IlvSwingUtil.showErrorDialog(this, e); helpProperties.clear(); } } else { IlvSwingUtil.showErrorDialog(this, "Help properties not found: help/help.properties"); } super.initHelpSystem(); } // ========================================= // Factory Classes // ========================================= private class ActivityFactory implements IlvActivityFactory { private IlvActivityFactory delegate; public ActivityFactory(IlvActivityFactory delegate) { this.delegate = delegate; } Override public IlvActivity createActivity(IlvTimeInterval interval) { IlvActivity activity = delegate.createActivity(interval); ((IlvTableActivity) activity).setProperty("originalID", "NA"); return activity; } } private class ResourceFactory implements IlvResourceFactory { private IlvResourceFactory delegate; public ResourceFactory(IlvResourceFactory delegate) { this.delegate = delegate; } Override public IlvResource createResource() { IlvResource resource = delegate.createResource(); ((IlvTableResource) resource).setProperty("originalID", "NA"); return resource; } } // ========================================= // Example Application // ========================================= /** * Returns the title of the example. * * @return The title of the example. */ Override public String getTitle() { return "Database Read/Write Gantt Chart Example"; } /** * Application mainline. * * @param args * The command line arguments. */ public static void main(String[] args) { ExampleFrame.createAndShowGUI(JdbcGanttExample.class); } }