ObjectDB - Object Database for Java Home | About Us | Customers | Free Download | Purchase
 
  <Back to Main Menu>   
 
 
JDO Directory Demo
Demo Home

Source Code
directory.Utilities
directory.pc.*
directory.step1.*
directory.step2.*
directory.step3.*
directory.step4.*

J2SDK Instructions
J2SDK on Windows
J2SDK on Unix

IDE Instructions
Borland JBuilder
IBM Eclipse
NetBeans / Forte /
Sun One Studio
JCreator
 



 

ObjectDB for Java/JDO Demo
package directory.step4

     JDO Directory

Step 4 demonstrates using JDO with JFC/Swing to implement the visual manager application.

directory/step4/eMain.java
 // ObjectDB for Java Demo - JDO Directory - A Brief JDO Tutorial
 // Copyright (C) 2001-2003, ObjectDB Software. All rights reserved.
 
 package directory.step4;
 
 /**
  * A main class for Step 4 of the Directory Demo.
  *
  * This class ensures that all the persistence capable classes will be enhanced
  * at runtime just before they are being loaded into the JVM.
  * To make it work - NO PERSISTENCE CAPABLE CLASS IS MENTIONED IN THIS CLASS!
  * (otherwise non enhanced versions of the classes might be loaded into JVM).
  */
 public class eMain {
     
     public static void main(String[] args) {
         
         // Enhance the persistence capable classes when necessary:
         com.objectdb.Enhancer.enhance("directory.pc.*");
 
         // Now run the example:
         new Manager();
     }
 }
 

directory/step4/Manager.java
 // ObjectDB for Java Demo - JDO Directory - A Brief JDO Tutorial
 // Copyright (C) 2001-2003, ObjectDB Software. All rights reserved.
 
 package directory.step4;
 
 import java.awt.*;
 import java.awt.event.*;
 import java.lang.reflect.Field;
 import java.text.*;
 import java.util.*;
 import javax.swing.*;
 import javax.swing.event.*;
 import javax.swing.table.*;
 import javax.swing.tree.*;
 import javax.jdo.*;
 import directory.pc.*;
 
 /**
  * The Manager class represents the main frame window.
  */
 public class Manager extends JFrame {
     
     //--------------//
     // Data Members //
     //--------------//
 
     // Icons for the directory's PersistenceCapable classes:
     private ImageIcon imageCategory =
         new ImageIcon(getClass().getResource("image/category.gif"));
     private ImageIcon imageBook =
         new ImageIcon(getClass().getResource("image/book.gif"));
     private ImageIcon imageItem =
         new ImageIcon(getClass().getResource("image/link.gif"));
     private HashMap classToIcon = new HashMap(); {
         classToIcon.put(Category.class, imageCategory);
         classToIcon.put(Item.class, imageItem);
         classToIcon.put(Book.class, imageBook);
     } // maps Class instances to Icon instances
 
     /** Long term PersistenceManager instance (application scope) */
     private PersistenceManager pm;
 
     /** A JTree component for the directory hierarchy */
     private JTree tree = new JTree();
     
     /** The directory tree model (manages the tree data) */
     private DirectoryTreeModel treeModel = new DirectoryTreeModel();
 
     /** A JTable component for the property table */
     private JTable table = new JTable();
 
     /** The property table model (manages the table data) */
     private PropertyTableModel tableModel = new PropertyTableModel();
 
     /** Date format for formatting and parsing dates */
     private SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy");
 
     //----------------//
     // Initialization //
     //----------------//
     
     /**
      * Constructs a Manager instance.
      */
     public Manager() {
 
         // Open the database connection:
         pm = directory.Utilities.getPersistenceManager(false);
         if (getChildElements(null).isEmpty())
             directory.step1.InitDB.insertObjects(pm);
                 // Use Step 1 to fill the database when necessary
 
         // Set the title and the icon of the main frame window:
         setTitle("Directory Manager");
         setIconImage(new ImageIcon(
             getClass().getResource("image/manager.gif")).getImage());
 
         // Add the split pane with the tree and the table:
         JSplitPane jSplitPane = new JSplitPane();
         jSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         jSplitPane.setDividerLocation(220);
         jSplitPane.setTopComponent(new JScrollPane(tree));
         jSplitPane.setBottomComponent(new JScrollPane(table));
         getContentPane().add(jSplitPane, BorderLayout.CENTER);
 
         // Add the button panel:
         JPanel buttonPanel = new JPanel();
         buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
         getContentPane().add(buttonPanel, BorderLayout.NORTH);
         
         // Add the New buttons:
         JButton addCtgButton = new JButton("New Category", imageCategory);
         addCtgButton.addActionListener(new NewActionListener(Category.class));
         buttonPanel.add(addCtgButton);
         JButton addItemButton = new JButton("New Item", imageItem);
         addItemButton.addActionListener(new NewActionListener(Item.class));
         buttonPanel.add(addItemButton);
         JButton addBookButton = new JButton("New Book", imageBook);
         addBookButton.addActionListener(new NewActionListener(Book.class));
         buttonPanel.add(addBookButton);
 
         // Add the Delete button:
         JButton deleteButton = new JButton("Delete", 
             new ImageIcon(getClass().getResource("image/delete.gif")));
         deleteButton.addActionListener(new DeleteActionListener());
         buttonPanel.add(deleteButton);
         
         // Prepare the directory tree:
         tree.setModel(treeModel);
         tree.setRootVisible(false);
         tree.getSelectionModel().setSelectionMode(
             TreeSelectionModel.SINGLE_TREE_SELECTION);
         tree.expandRow(0);
         tree.setCellRenderer( // just for adding icons to the tree
             new DefaultTreeCellRenderer() {
                 public Component getTreeCellRendererComponent(JTree tree,
                         Object value, boolean sel, boolean expanded,
                         boolean leaf, int row, boolean hasFocus) {
                     JLabel label = (JLabel)super.getTreeCellRendererComponent(
                         tree, value, sel, expanded, leaf, row, hasFocus);
                     label.setIcon((Icon)classToIcon.get(value.getClass()));
                     return label;
                 }
             }
         ); // end of renderer
 
         // Handler for DELETE key in the tree:
         tree.registerKeyboardAction(new DeleteActionListener(),
             KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false),
             JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
         );
 
         // Handler for selection change in the tree:
         tree.getSelectionModel().addTreeSelectionListener(
             new TreeSelectionListener() {
                 public void valueChanged(TreeSelectionEvent e) {
                     table.tableChanged(null);
                     initTableColumns();
                 }
             }
         );
         
         // Prepare the property table:
         table.setModel(tableModel);
         table.getParent().setBackground(Color.white);
         initTableColumns();
 
         // Handler for closing the main frame window:
         addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent evt) {
                 if (pm != null && !pm.isClosed())
                     pm.close(); // close the database connection
                 System.exit(0);
             }
         });
 
         // Show the main frame window:
         Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
         setBounds((ss.width - 680) / 2,(ss.height - 440) / 2, 680, 440);
         show();
         tree.requestFocus();
     }
 
     /**
      * Initializes the width of the table columns.
      */
     private void initTableColumns() {
         TableColumn tableColumn = table.getColumnModel().getColumn(0);
         tableColumn.setMinWidth(120);
         tableColumn.setPreferredWidth(180);
         tableColumn.setMaxWidth(240);
     }
 
     //----------------//
     // Data Retrieval //
     //----------------//
 
     /**
      * Retrieves the children of a specified parent element.
      */
     private java.util.List getChildElements(Object parent) {
         // Handle parent elements:
         if (parent instanceof Category)
             return ((Category)parent).getElements();
         if (parent instanceof Item)
             return Collections.EMPTY_LIST;
         
         // Handle root retrival:
         Query query = pm.newQuery(Category.class, "parent == null");
         try {
             return new ArrayList((Collection)query.execute());
         }
         finally {
             query.closeAll();
         }
     }
     
     //-------------------------//
     // Button Action Listeners //
     //-------------------------//
 
     /**
      * Handler for the [New Category] [New Item] [New Book] buttons.
      */
     private class NewActionListener implements ActionListener {
         private Class cls; // one of the directory's persistence capable classes
         NewActionListener(Class cls) {
             this.cls = cls;
         }
         public void actionPerformed(ActionEvent evt) {
             try {
                 // Get the selected (parent) path:
                 TreePath path = tree.getSelectionPath();
                 if (path == null)
                     path = tree.getPathForRow(0);
                 Object selectedNode = path.getLastPathComponent();
                 if (selectedNode instanceof Item) {
                     selectedNode = ((Item)selectedNode).getParent();
                     path = path.getParentPath();
                 }
                 else if (!(selectedNode instanceof Category))
                     if (cls != Category.class)
                         throw new RuntimeException(
                             "No selected parent category");
 
                 // Update the database:
                 pm.currentTransaction().begin();
                 Element newElement = (Element)cls.newInstance();
                 if (selectedNode instanceof Category)
                     newElement.setParent((Category)selectedNode);
                 pm.makePersistent(newElement);
                 pm.currentTransaction().commit();
 
                 // Refresh the display:
                 refreshTree(path);
                 tree.setSelectionPath(path.pathByAddingChild(newElement));
             }
             catch (Exception x) {
                 JOptionPane.showMessageDialog(Manager.this, x.getMessage(),
                     "New Element Error", JOptionPane.ERROR_MESSAGE);
             }
         }
     }
 
     /**
      * Handler for the [Delete] button and the [Delete] key.
      */
     private class DeleteActionListener implements ActionListener {
         public void actionPerformed(ActionEvent evt) {
             try {
                 // Get the selected element (for deletion):
                 TreePath path = tree.getSelectionPath();
                 if (path == null)
                     throw new RuntimeException("No selected object for delete");
                 Element element = (Element)path.getLastPathComponent();
                 if (element.getParent() == null)
                     throw new RuntimeException("Cannot delete a root category");
                 int rowIx = tree.getRowForPath(path);
 
                 // Update the database:
                 pm.currentTransaction().begin();
                 pm.deletePersistent(element);
                 pm.currentTransaction().commit();
 
                 // Refresh the display:
                 TreePath parentPath = path.getParentPath();
                 refreshTree(parentPath);
                 tree.setSelectionRow(Math.min(rowIx, tree.getRowCount() - 1));
             }
 
             // Handle errors:
             catch (Exception x) {
                 JOptionPane.showMessageDialog(Manager.this, x.getMessage(),
                     "Delete Error", JOptionPane.ERROR_MESSAGE);
             }
         }
     }
 
     /**
      * Updates the tree display after an Add / Delete operation.
      */
     private void refreshTree(TreePath path) {
         treeModel.fireTreeChanged(path);
         tree.expandPath(path);
         tree.setSelectionPath(path);
         tree.requestFocus();
     }
 
     //----------------------//
     // Directory Tree Model //
     //----------------------//
 
     /**
      * The DirectoryTreeModel inner class manages the directory tree data.
      */
     private class DirectoryTreeModel extends DefaultTreeModel {
         DirectoryTreeModel() {
             super(new DefaultMutableTreeNode("Directory"));
         }
         public int getChildCount(Object parent) {
             return getChildElements(parent).size();
         }
         public Object getChild(Object parent, int index) {
             return getChildElements(parent).get(index);
         }
         public boolean isLeaf(Object node) {
             return node instanceof Item;
         }
         public int getIndexOfChild(Object parent, Object child) {
             return getChildElements(parent).indexOf(child);
         }
         void fireTreeChanged(TreePath path) {
             fireTreeStructureChanged(this,new Object[] { path }, null, null);
         }
     }
 
     //----------------------//
     // Property Table Model //
     //----------------------//
 
     /**
      * The PropertyTableModel inner class manages the property table data.
      */
     private class PropertyTableModel extends AbstractTableModel {
         public int getRowCount() {
             return getFields().length;
         }
         public int getColumnCount() {
             return 2;
         }
         public String getColumnName(int columnIndex) {
             return (columnIndex == 0) ? "Field" : "Value";
         }
         public Object getValueAt(int rowIndex, int columnIndex) {
             try {
                 Field field = getFields()[rowIndex];
                 if (columnIndex == 0)
                     return field.getName();
                 field.setAccessible(true);
                 Object o = field.get(getSelectedElement());
                 return (o instanceof Date) ? dateFormat.format((Date)o) : o;
             }
             catch (Exception x) {
                 JOptionPane.showMessageDialog(Manager.this, x.getMessage(),
                     "Unexpected Error", JOptionPane.ERROR_MESSAGE);
                 return x.getMessage();
             }
         }
         public boolean isCellEditable(int rowIndex, int columnIndex) {
             return columnIndex == 1;
         }
         public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
             if (columnIndex == 1) {
                 Field field = getFields()[rowIndex];
                 try {
                     pm.currentTransaction().begin();
                     field.setAccessible(true);
                     Element element = getSelectedElement();
                     JDOHelper.makeDirty(element, field.getName());
                         // Direct reflection modification is not tracked
                         // automatically by the enhanced code...
                     Parser parser = (Parser)parsers.get(field.getType());
                     field.set(element, parser.parse(aValue.toString()));
                     pm.currentTransaction().commit();
                 }
                 catch (Exception x) {
                     JOptionPane.showMessageDialog(Manager.this, x.getMessage(),
                         "Edit Error", JOptionPane.ERROR_MESSAGE);
                 }
                 finally {
                     if (pm.currentTransaction().isActive())
                         pm.currentTransaction().rollback();
                     refreshTree(tree.getSelectionPath());
                 }
             }
         }
         
         /**
          * Gets the selected element in the tree.
          */
         private Element getSelectedElement() {
             TreePath path = tree.getSelectionPath();
             if (path != null)
                 return (Element)path.getLastPathComponent();
             return null;
         }
 
         /**
          * Uses reflection to get all the fields of the selected element.
          */
         private Field[] getFields() {
             Element e = getSelectedElement();
             if (e == null)
                 return new Field[0];
             ArrayList allFields = new ArrayList();
             Class cls = e.getClass();
             while (cls != Object.class) {
                 Field[] fields = cls.getDeclaredFields();
                 for (int i = 0; i < fields.length; i++) {
                     Field field = fields[i];
                     if (!field.getName().startsWith("jdo"))
                         if (parsers.get(field.getType()) != null)
                             allFields.add(fields[i]);
                 }
                 cls = cls.getSuperclass();
             }
             Collections.sort(allFields, new Comparator() {
                 public int compare(Object o1, Object o2) {
                     return ((Field)o1).getName().compareTo(
                         ((Field)o2).getName());
                 }
             });
             return (Field[])allFields.toArray(new Field[allFields.size()]);
         }
     }
     
     // Parsers for the supported types in the property table:
     interface Parser {
         Object parse(String str) throws ParseException;
     }
     private HashMap parsers = new HashMap();
     {
         parsers.put(String.class, new Parser() {
             public Object parse(String str) throws ParseException {
                 return str;
             }
         });
         parsers.put(Date.class, new Parser() {
             public Object parse(String str) throws ParseException {
                 return dateFormat.parse(str);
             }
         });
         parsers.put(int.class, new Parser() {
             public Object parse(String str) throws ParseException {
                 return new Integer(str);
             }
         });
     }
 }
 




Copyright 2001-2007 ObjectDB Software. All rights reserved.