/*
* @(#)SerializationStorageFormat.java
*
* Project: JHotdraw - a GUI framework for technical drawings
* http://www.jhotdraw.org
* http://jhotdraw.sourceforge.net
* Copyright: � by the original author(s) and all contributors
* License: Lesser GNU Public License (LGPL)
* http://www.opensource.org/licenses/lgpl-license.html
*/
package org.jhotdraw.util;
import org.jhotdraw.framework.*;
import org.jhotdraw.standard.StandardDrawing;
import java.io.*;
import java.util.*;
import java.util.List;
import java.awt.*;
import javax.jdo.*;
import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
/**
* @author Wolfram Kaiser <mrfloppy@users.sourceforge.net>
* @version <$CURRENT_VERSION$>
*/
public class JDOStorageFormat extends StandardStorageFormat {
private Map pms;
/**
* Create a SerialzationStorageFormat for storing and restoring Drawings.
*/
public JDOStorageFormat() {
super();
pms = CollectionsFactory.current().createMap();
// close database connection when application exits
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
Iterator iter = pms.values().iterator();
// while (iter.hasNext()) {
// ((PersistenceManager)iter.next()).close();
// }
}
});
}
/**
* Factory method to create the file extension recognized by the FileFilter for this
* SerializationStorageFormat. The SerializationStorageFormat has the file extension "ser"
* (e.g. my_picasso.ser).
*
* @return new file extension
*/
protected String createFileExtension() {
return "j2";
}
/**
* Factory method to create a file description for the file type when displaying the
* associated FileFilter.
*
* @return new file description
*/
public String createFileDescription() {
return "Database (" + getFileExtension() + ")";
}
/**
* @see org.jhotdraw.util.StorageFormat#isRestoreFormat()
*/
public boolean isRestoreFormat() {
return true;
}
/**
* @see org.jhotdraw.util.StorageFormat#isStoreFormat()
*/
public boolean isStoreFormat() {
return true;
}
/**
* Store a Drawing under a given name. The name should be valid with regard to the FileFilter
* that means, it should already contain the appropriate file extension.
*
* @param fileName file name of the Drawing under which it should be stored
* @param storeDrawing drawing to be saved
*/
public String store(String fileName, Drawing storeDrawing) throws IOException {
PersistenceManager pm = getPersistenceManager(fileName);
String drawingName = null;
Drawing txnDrawing = crossTxnBoundaries(storeDrawing);
endTransaction(pm, false);
startTransaction(pm);
try {
Extent extent = pm.getExtent(StandardDrawing.class, true);
DrawingListModel listModel = new DrawingListModel(extent.iterator());
drawingName = showStoreDialog(listModel, storeDrawing);
if (drawingName != null) {
storeDrawing.setTitle(drawingName);
txnDrawing.setTitle(drawingName);
pm.makePersistent(txnDrawing);
}
}
finally {
endTransaction(pm, (drawingName != null));
}
// there must be always a transaction running
startTransaction(pm);
return drawingName;
}
/**
* Restore a Drawing from a file with a given name. The name must be should with regard to the
* FileFilter that means, it should have the appropriate file extension.
*
* @param fileName of the file in which the Drawing has been saved
* @return restored Drawing
*/
public synchronized Drawing restore(String fileName) throws IOException {
PersistenceManager pm = getPersistenceManager(fileName);
endTransaction(pm, false);
startTransaction(pm);
Drawing restoredDrawing = null;
try {
Extent extent = pm.getExtent(StandardDrawing.class, true);
DrawingListModel listModel = new DrawingListModel(extent.iterator());
Drawing txnDrawing = showRestoreDialog(listModel);
if (txnDrawing != null) {
// pm.retrieve(txnDrawing);
// retrieveAll(pm, (StandardDrawing)txnDrawing);
// restoredDrawing = crossTxnBoundaries(txnDrawing);
restoredDrawing = txnDrawing;
}
}
finally {
endTransaction(pm, false);
}
// there must be always a transaction running
startTransaction(pm);
return restoredDrawing;
}
private void retrieveAll(PersistenceManager pm, Figure figure) {
pm.retrieve(figure);
FigureEnumeration fe = figure.figures();
while (fe.hasNextFigure()) {
retrieveAll(pm, fe.nextFigure());
}
}
private Drawing crossTxnBoundaries(Drawing originalDrawing) {
return (Drawing)((StandardDrawing)originalDrawing).clone();
// return originalDrawing;
}
private synchronized PersistenceManager getPersistenceManager(String fileName) {
PersistenceManager pm = (PersistenceManager)pms.get(fileName);
if (pm == null) {
pm = createPersistenceManagerFactory(fileName).getPersistenceManager();
pms.put(fileName, pm);
}
return pm;
}
private PersistenceManagerFactory createPersistenceManagerFactory(String dbFileName) {
Properties pmfProps = new Properties();
pmfProps.put(
"javax.jdo.PersistenceManagerFactoryClass",
"com.poet.jdo.PersistenceManagerFactories" );
pmfProps.put(
"javax.jdo.option.ConnectionURL",
"fastobjects://LOCAL/MyBase.j1" );
final PersistenceManagerFactory pmf =
JDOHelper.getPersistenceManagerFactory( pmfProps );
return pmf;
}
private static void startTransaction(PersistenceManager pm) {
if (!pm.currentTransaction().isActive()) {
pm.currentTransaction().begin();
}
}
private static void endTransaction(PersistenceManager pm, boolean doCommit) {
if (pm.currentTransaction().isActive()) {
if (doCommit) {
pm.currentTransaction().commit();
}
else {
pm.currentTransaction().rollback();
}
}
}
private String showStoreDialog(ListModel listModel, Drawing storeDrawing) {
final String msgString = "Specify a name for the drawing";
final JTextField nameTextField = new JTextField(storeDrawing.getTitle());
final JList dataList = new JList(listModel);
final JScrollPane dbContentScrollPane = new JScrollPane(dataList);
Object[] guiComponents = {msgString, dbContentScrollPane, nameTextField};
dataList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataList.setValueIsAdjusting(true);
dataList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
nameTextField.setText(dataList.getSelectedValue().toString());
}
});
final JOptionPane optionPane = new JOptionPane(
guiComponents,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
final JDialog dialog = optionPane.createDialog(null, "Restore a drawing from the database");
// dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
// dialog.addWindowListener(new WindowAdapter() {
// public void windowClosing(WindowEvent we) {
// System.exit(0);
// }
// });
dialog.setVisible(true);
if ((optionPane.getValue() != null) && (optionPane.getValue().equals(new Integer(JOptionPane.OK_OPTION)))) {
return nameTextField.getText();
}
else {
return null;
}
}
private Drawing showRestoreDialog(DrawingListModel listModel) {
final String msgString = "Select a drawing";
final JList dataList = new JList(listModel);
final JScrollPane dbContentScrollPane = new JScrollPane(dataList);
Object[] guiComponents = {msgString, dbContentScrollPane};
dataList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataList.setValueIsAdjusting(true);
final JOptionPane optionPane = new JOptionPane(
guiComponents,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
final JDialog dialog = optionPane.createDialog(null, "Restore a drawing from the database");
dialog.setVisible(true);
if ((optionPane.getValue() != null)
&& (optionPane.getValue().equals(new Integer(JOptionPane.OK_OPTION)))
&& (dataList.getSelectedIndex() >= 0)
&& (dataList.getSelectedIndex() < dataList.getModel().getSize())) {
return listModel.getDrawingAt(dataList.getSelectedIndex());
}
else {
return null;
}
}
static class DrawingListModel extends AbstractListModel {
private List myList;
DrawingListModel(Iterator iter) {
myList = CollectionsFactory.current().createList();
while (iter.hasNext()) {
Object o = iter.next();
System.out.println("extent: " + o + " .. " + ((Drawing)o).getTitle());
myList.add(o);
}
}
public Object getElementAt(int index) {
return getDrawingAt(index).getTitle();
}
protected Drawing getDrawingAt(int index) {
return ((Drawing)myList.get(index));
}
public int getSize() {
return myList.size();
}
}
static class DrawingSelector extends JDialog {
DrawingSelector() {
init();
}
private void init() {
setTitle("Select Drawing");
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JLabel("Database content"), BorderLayout.NORTH);
setSize(200, 200);
}
}
public static void main(String[] args) {
DrawingSelector frame = new DrawingSelector();
try {
Drawing newDrawing = new StandardDrawing();
newDrawing.setTitle("TestDrawingName" + new Random(System.currentTimeMillis()).nextLong());
new JDOStorageFormat().store("base.j2", newDrawing);
System.exit(0);
}
catch (IOException e) {
e.printStackTrace();
}
// frame.setVisible(true);
}
}