/*
* 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);
}
}