You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/05/14 04:14:32 UTC

svn commit: r944083 [3/4] - in /openjpa/trunk/openjpa-examples/openbooks/src: ./ main/ main/java/ main/java/jpa/ main/java/jpa/tools/ main/java/jpa/tools/swing/ main/java/openbook/ main/java/openbook/client/ main/java/openbook/domain/ main/java/openboo...

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Demo.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Demo.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Demo.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Demo.java Fri May 14 02:14:30 2010
@@ -0,0 +1,634 @@
+/*
+ * Copyright 2010-2012 Pinaki Poddar
+ *
+ *
+ *  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 openbook.client;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.Box;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JToolBar;
+import javax.swing.JTree;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.SwingWorker;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import jpa.tools.swing.AttributeLegendView;
+import jpa.tools.swing.ConfigurationViewer;
+import jpa.tools.swing.ErrorDialog;
+import jpa.tools.swing.GraphicOutputStream;
+import jpa.tools.swing.MetamodelView;
+import jpa.tools.swing.PowerPointViewer;
+import jpa.tools.swing.PreparedQueryViewer;
+import jpa.tools.swing.ScrollingTextPane;
+import jpa.tools.swing.SourceCodeViewer;
+import jpa.tools.swing.StatusBar;
+import jpa.tools.swing.SwingHelper;
+import openbook.domain.Customer;
+import openbook.server.OpenBookService;
+import openbook.server.ServiceFactory;
+import openbook.util.PropertyHelper;
+
+import org.apache.openjpa.conf.OpenJPAVersion;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+
+/**
+ * A graphical user interface based client of OpenBooks for demonstration.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class Demo extends JFrame implements Thread.UncaughtExceptionHandler {
+    private static final Dimension TAB_VIEW = new Dimension(1400,800);
+    private static final Dimension OUT_VIEW = new Dimension(1400,200);
+    private static final Dimension NAV_VIEW = new Dimension(400,1000);
+
+    /**
+     * The actions invoked by this sample demonstration.
+    */
+    private Action _root;
+    private Action _about;
+    private Action _buyBook;
+    private Action _deliver;
+    private Action _supply;       
+    private Action _viewConfig;  
+    private Action _viewDomain; 
+    private Action _viewData;  
+    private Action _viewSource;
+    private Action _viewQuery;
+    
+    /**
+     * The primary graphic widgets used to invoke and display the results of the actions.
+     */
+    private JToolBar    _toolBar;
+    private JTree       _navigator;
+    private JTabbedPane _tabbedPane;
+    private JTabbedPane _outputPane;
+    private StatusBar   _statusBar;
+    private ScrollingTextPane   _sqlLog;
+    public static final Icon    LOGO = Images.getIcon("images/OpenBooks.jpg");
+    
+    private boolean _debug = Boolean.getBoolean("openbook.debug");
+    
+    /**
+     * The handle to the service.
+     */
+    private OpenBookService     _service;
+    private Customer            _customer;
+    private Map<String, Object> _config;
+    
+    /**
+     * Runs the demo.
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String[] args) throws Exception {
+        SwingHelper.setLookAndFeel(14);
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                Demo demo = new Demo();
+                demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+                demo.pack();
+                SwingHelper.position(demo, null);
+                demo.setVisible(true);
+            }
+        });
+    }
+
+    
+    private Demo() {
+        Thread.currentThread().setUncaughtExceptionHandler(this);
+        _config = PropertyHelper.load(System.getProperty("openbook.client.config", "demo.properties"));
+        
+        setTitle("OpenBooks: A Sample JPA 2.0 Application");
+        
+        _root         = new WelcomeAction("OpenBooks", "images/OpenBooks.jpg", "OpenBooks");
+        _about        = new AboutAction("About OpenBooks", "images/OpenBooks.jpg", "About OpenBooks");
+        _buyBook      = new BuyBookAction("Buy", "images/Add2Cart.jpg", "Browse and Buy Books");
+        _deliver      = new DeliveryAction("Deliver", "images/Deliver.jpg", "Deliver Pending Orders");
+        _supply       = new SupplyAction("Supply", "images/Supply.jpg", "Supply Books");
+        _viewConfig   = new ViewConfigAction("Configuration", "images/browse.png", "View Configuration");
+        _viewDomain   = new ViewDomainAction("Domain", "images/DomainModel.jpg", "View Domain Model");
+        _viewData     = new ViewDataAction("Data", "images/DataModel.jpg", "View Instances");
+        _viewSource   = new ViewSourceAction("Source", "images/SourceCode.jpg", "View Source Code");
+        _viewQuery    = new ViewQueryCacheAction("Query", "images/DataModel.jpg", "View Queries");
+        
+        _toolBar    = createToolBar();
+        _navigator  = createNavigator();
+        _tabbedPane = createTabbedView();
+        _outputPane = createOutputView();
+        _statusBar  = createStatusBar();
+        
+        JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+        horizontalSplitPane.setContinuousLayout(true);
+        horizontalSplitPane.setDividerSize(1);
+        JScrollPane scrollPane = new JScrollPane(_navigator);
+        scrollPane.setMinimumSize(new Dimension(NAV_VIEW.width/4, NAV_VIEW.height));
+        scrollPane.setPreferredSize(NAV_VIEW);
+        horizontalSplitPane.add(scrollPane);
+        
+        JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+        verticalSplitPane.setContinuousLayout(true);
+        verticalSplitPane.setDividerSize(1);
+        verticalSplitPane.add(_tabbedPane);
+        verticalSplitPane.add(_outputPane);
+        horizontalSplitPane.add(verticalSplitPane);
+        
+        Container content = getContentPane();
+        content.add(_toolBar, BorderLayout.PAGE_START);
+        content.add(horizontalSplitPane, BorderLayout.CENTER);
+        content.add(_statusBar, BorderLayout.SOUTH);
+        
+        _root.actionPerformed(null);
+    }
+    
+    /**
+     * Gets the handle to OpenBooks service. 
+     */
+    public OpenBookService getService() {
+        if (_service == null) {
+            final String unitName = PropertyHelper.getString(_config, "openbook.unit", 
+                    OpenBookService.DEFAULT_UNIT_NAME);
+            
+            SwingWorker<OpenBookService, Void> getService = new SwingWorker<OpenBookService, Void> () {
+                @Override
+                protected OpenBookService doInBackground() throws Exception {
+                    return ServiceFactory.getService(unitName);
+                }
+                
+            };
+            getService.execute();
+            try {
+                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+                _service = getService.get(10, TimeUnit.SECONDS);
+            } catch (Exception t) {
+                new ErrorDialog(t).setVisible(true);
+            } finally {
+                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+            }
+        }
+        return _service;
+    }
+    
+    public Customer getCustomer() {
+        if (_customer == null) {
+            SwingWorker<Customer, Void> task = new SwingWorker<Customer, Void> () {
+                @Override
+                protected Customer doInBackground() throws Exception {
+                    return getService().login("guest");
+                }
+                
+            };
+            task.execute();
+            try {
+                _customer = task.get(1, TimeUnit.SECONDS);
+            } catch (Exception t) {
+                new ErrorDialog(t).setVisible(true);
+            }
+        }
+        return _customer;
+    }
+    
+    @Override
+    public void uncaughtException(Thread t, Throwable e) {
+        if (SwingUtilities.isEventDispatchThread()) {
+            new ErrorDialog(e);
+        } else {
+            e.printStackTrace();
+        }
+    }
+    
+    
+    private JToolBar  createToolBar() {
+        JToolBar toolBar = new JToolBar();
+        toolBar.add(_buyBook);
+        toolBar.add(_deliver);
+        toolBar.add(_supply);
+        Dimension d = new Dimension(40, 32);
+        toolBar.addSeparator(d);
+        
+        toolBar.add(_viewConfig);
+        toolBar.add(_viewDomain);
+        toolBar.add(_viewData);
+        toolBar.add(_viewSource);
+        toolBar.add(_viewQuery);
+        
+        toolBar.addSeparator(d);
+        
+        toolBar.add(Box.createHorizontalGlue());
+        toolBar.add(_about);
+        toolBar.add(Box.createHorizontalStrut(2));
+        return toolBar;
+    }
+    
+    private StatusBar createStatusBar() {
+        return new StatusBar();
+    }
+
+
+    /**
+     * Abstract root of all Action objects helps to locate/configure visual action parameters such as
+     * tooltip text or image.
+     * 
+     * @author Pinaki Poddar
+     *
+     */
+    public abstract class OpenBookAction extends AbstractAction {
+        public OpenBookAction(Map<String,Object> props, String key) {
+            this(PropertyHelper.getString(props, key + "name",    ""),
+                 PropertyHelper.getString(props, key + "icon",    null),
+                 PropertyHelper.getString(props, key + "tooltip", ""),
+                 PropertyHelper.getString(props, key + "help",    ""));
+        }
+        
+        public OpenBookAction(String name, String iconLocation, String tooltip) {
+            this(name, iconLocation, tooltip, tooltip);
+        }
+        
+        public OpenBookAction(String name, String iconLocation, String tooltip, String helpText) {
+            putValue(Action.NAME, name);
+            putValue(Action.SHORT_DESCRIPTION, tooltip);
+            putValue(Action.LONG_DESCRIPTION,  helpText);
+            
+            Icon icon = Images.getIcon(iconLocation, true);
+            putValue(Action.SMALL_ICON, icon);
+        }
+    }
+    
+    public class BuyBookAction extends OpenBookAction {
+        BuyBookPage         _buyBookPage;
+        public BuyBookAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        
+        public void actionPerformed(ActionEvent e) {
+            if (_buyBookPage == null) {
+                _buyBookPage = new BuyBookPage(getService(), getCustomer());
+            }
+            showTab(_tabbedPane, "Buy Books", _buyBookPage);
+            switchTab(_outputPane, _sqlLog);
+        }
+        
+    }
+    public class DeliveryAction extends OpenBookAction {
+        DeliveryPage        _deliveryPage;
+        public DeliveryAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            if (_deliveryPage == null) {
+                _deliveryPage = new DeliveryPage(getService());
+            }
+            showTab(_tabbedPane, "Deliver Books", _deliveryPage);
+            switchTab(_outputPane, _sqlLog);
+        }
+        
+    }
+    
+    public class SupplyAction extends OpenBookAction {
+        SupplyPage          _supplyPage;
+        public SupplyAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            if (_supplyPage == null) {
+                _supplyPage = new SupplyPage(getService());
+            }
+            showTab(_tabbedPane, "Supply Books", _supplyPage);
+            switchTab(_outputPane, _sqlLog);
+        }
+        
+    }
+    
+    public class ViewConfigAction extends OpenBookAction {
+        ConfigurationViewer _configView;
+        public ViewConfigAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            if (_configView == null) {
+                _configView = new ConfigurationViewer("Unit Configuration", getService().getUnit().getProperties());
+                showTab(_tabbedPane, "Configuration", new JScrollPane(_configView));
+            } else {
+                showTab(_tabbedPane, "Configuration", _configView);
+            }
+        }
+        
+    }
+    
+    public class ViewDomainAction extends OpenBookAction {
+        MetamodelView       _domainView;
+        AttributeLegendView _legends;
+        public ViewDomainAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            if (_domainView == null) {
+                _domainView = new MetamodelView(getService().getUnit().getMetamodel());
+                _legends = new AttributeLegendView();
+                showTab(_outputPane, "Legends", new JScrollPane(_legends));
+            }
+            showTab(_tabbedPane, "Domain Model", _domainView);
+        }
+        
+    }
+
+    public class ViewDataAction extends OpenBookAction {
+        public ViewDataAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            showTab(_tabbedPane, "Buy Books", null);
+        }
+        
+    }
+    
+    public class ViewQueryCacheAction extends OpenBookAction {
+        PreparedQueryViewer _queryView;
+        public ViewQueryCacheAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        public void actionPerformed(ActionEvent e) {
+            if (_queryView == null) {
+                _queryView = new PreparedQueryViewer(OpenJPAPersistence.cast(getService().getUnit()));
+                showTab(_tabbedPane, "JPQL Query", new JScrollPane(_queryView));
+            }
+            showTab(_tabbedPane, "JPQL Queries", _queryView);
+        }
+        
+    }
+    
+    public class ViewSourceAction extends OpenBookAction {
+        SourceCodeViewer _sourceViewer;
+        
+        public ViewSourceAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        
+        public void actionPerformed(ActionEvent e) {
+            if (_sourceViewer == null) {
+                _sourceViewer = new SourceCodeViewer("source");
+            }
+            showTab(_tabbedPane, "Source Code", _sourceViewer);
+        }
+        
+    }
+    
+    /**
+     * Displays the "welcome" page.
+     *  
+     * @author Pinaki Poddar
+     *
+     */
+    public class WelcomeAction extends OpenBookAction {
+        PowerPointViewer    _powerpoint;
+        JLabel              _logoLabel = new JLabel(LOGO);
+        boolean _showPresentation = true;
+        
+        public WelcomeAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        
+        public void actionPerformed(ActionEvent e) {
+            if (_powerpoint == null && _showPresentation) {
+                String dir = PropertyHelper.getString(_config, "openbook.slides.dir", "slides/");
+                String[] defaultSlides = { 
+                                    "Slide1.JPG",
+                                    "Slide2.JPG",
+                                    "Slide3.JPG",
+                                    "Slide4.JPG",
+                                    "Slide5.JPG",
+                                    "Slide6.JPG",
+                                    "Slide7.JPG",
+                                    "Slide8.JPG",
+                                    "Slide9.JPG",
+                                    "Slide10.JPG",
+                                    "Slide11.JPG",
+                                    "Slide12.JPG",
+                                    "Slide13.JPG",
+                                    "Slide14.JPG",
+                                    "Slide15.JPG"};
+                List<String> slides = PropertyHelper.getStringList(_config, "openbook.slides.list",
+                        Arrays.asList(defaultSlides));
+                try {
+                    _powerpoint = new PowerPointViewer(dir, slides);
+                } catch (Exception e1) {
+                    _showPresentation = false;
+                    System.err.println("Error while opening slide deck at " + dir + ". \r\n"+ e1);
+                }
+            } 
+            showTab(_tabbedPane, "Home", _powerpoint != null ? _powerpoint : _logoLabel);
+        }
+        
+    }
+    public class AboutAction extends OpenBookAction {
+        AboutDialog _dialog;
+        
+        public AboutAction(String name, String iconLocation, String tooltip) {
+            super(name, iconLocation, tooltip);
+        }
+        
+        public void actionPerformed(ActionEvent e) {
+            if (_dialog == null) {
+                _dialog = new AboutDialog(LOGO);
+                SwingHelper.position(_dialog, Demo.this);
+            }
+            _dialog.setVisible(true);
+        }
+        
+    }
+    
+    /**
+     * Show the given tab in the given pane.
+     * @param pane the tabbed pane
+     * @param title title of the tab component
+     * @param tab the component to show
+     */
+    void showTab(JTabbedPane pane, String title, Component tab) {
+        if (tab == null)
+            return;
+        Component c = locateTab(pane, tab);
+        if (c == null) {
+            pane.addTab(title, tab);
+            pane.setSelectedComponent(tab);
+        } else {
+            pane.setSelectedComponent(c);
+        }
+    }
+    
+    void switchTab(JTabbedPane pane, Component tab) {
+        if (tab == null)
+            return;
+        Component c = locateTab(pane, tab);
+        if (c == null) {
+            pane.setSelectedComponent(c);
+        } 
+    }
+    
+    Component locateTab(JTabbedPane pane, Component tab) {
+        int index = pane.indexOfComponent(tab);
+        if (index == -1) {
+            Component[] components = pane.getComponents();
+            for (int i = 0; i < components.length; i++) {
+                if (components[i] instanceof JScrollPane 
+                && (((JScrollPane)components[i]).getViewport().getView() == tab)) {
+                    return components[i];
+                }
+            }
+        } else {
+            return pane.getComponentAt(index);
+        }
+        return null;
+    }
+    
+    
+    private JTabbedPane createTabbedView() {
+        JTabbedPane pane = new JTabbedPane();
+        pane.setPreferredSize(TAB_VIEW);
+        pane.setMinimumSize(new Dimension(TAB_VIEW.width, TAB_VIEW.height));
+        return pane;
+    }
+    
+    private JTabbedPane createOutputView() {
+        JTabbedPane pane = new JTabbedPane();
+        pane.setPreferredSize(OUT_VIEW);
+        _sqlLog = new ScrollingTextPane();
+        GraphicOutputStream stream = new GraphicOutputStream(_sqlLog);
+        _sqlLog.setPreferredSize(TAB_VIEW);
+        SQLLogger.setOutput(stream);
+        pane.addTab("SQL Log", new JScrollPane(_sqlLog));
+        ScrollingTextPane consoleLog = new ScrollingTextPane();
+        GraphicOutputStream console = new GraphicOutputStream(consoleLog);
+        System.setErr(new PrintStream(console, true));
+        pane.addTab("Console", new JScrollPane(consoleLog));
+        return pane;
+    }
+    
+    /**
+     * Creates the navigation tree and adds the tree nodes. Each tree node is attached with an action
+     * that fires when the node is selected.  
+     */
+    private JTree createNavigator() {
+        ActionTreeNode root = new ActionTreeNode(_root);
+        DefaultMutableTreeNode app   = new DefaultMutableTreeNode("Application WorkFlows");
+        DefaultMutableTreeNode views = new DefaultMutableTreeNode("Views");
+        root.add(app);
+        root.add(views);
+        
+        
+        app.add(new ActionTreeNode(_buyBook));
+        app.add(new ActionTreeNode(_deliver));
+        app.add(new ActionTreeNode(_supply));
+        
+        views.add(new ActionTreeNode(_viewConfig));
+        views.add(new ActionTreeNode(_viewDomain));
+        views.add(new ActionTreeNode(_viewQuery));
+        views.add(new ActionTreeNode(_viewData));
+        views.add(new ActionTreeNode(_viewSource));
+        
+        
+        JTree tree = new JTree(root);
+        tree.setShowsRootHandles(true);
+        
+        tree.addTreeSelectionListener(new TreeSelectionListener() {
+            public void valueChanged(TreeSelectionEvent e) {
+                Object treeNode = _navigator.getLastSelectedPathComponent();
+                if (treeNode instanceof ActionTreeNode) {
+                    ((ActionTreeNode)treeNode)._action.actionPerformed(null);
+                }
+            }
+        });
+        tree.setCellRenderer(new TypedTreeCellRenderer());
+        
+        return tree;
+    }
+    
+    /**
+     * A tree node which may have an associated action.
+     * 
+     * @author Pinaki Poddar
+     *
+     */
+    public static class ActionTreeNode extends DefaultMutableTreeNode {
+        private final Action _action;
+        public ActionTreeNode(Action action) {
+            _action = action;
+        }
+        
+        public String toString() {
+            return _action.getValue(Action.SHORT_DESCRIPTION).toString();
+        }
+        
+    }
+    
+    public class TypedTreeCellRenderer extends DefaultTreeCellRenderer {
+        @Override
+        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, 
+                boolean leaf, int row, boolean hasFocus) { 
+            return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+        }
+    }
+    
+    public static class AboutDialog extends JDialog {
+        public AboutDialog(Icon logo) {
+            setModal(true);
+            setLayout(new BorderLayout());
+            JButton button = new JButton("<html>" 
+                    + "<b>OpenBooks</b> " 
+                    + "<br> using OpenJPA version " + OpenJPAVersion.MAJOR_RELEASE + "." + OpenJPAVersion.MINOR_RELEASE
+                    + "<br> by JPA Team, SWG" 
+                    + "<br>IBM Corporation" 
+                    + "<p>"
+                    + "</html>");
+            button.setIcon(logo);
+            button.setHorizontalTextPosition(SwingConstants.RIGHT);
+            button.setEnabled(true);
+            button.setBorderPainted(false);
+            add(button, BorderLayout.CENTER);
+            add(new JLabel(Images.getIcon("images/websphere.png")), BorderLayout.SOUTH);
+            setTitle("About OpenBooks");
+            setAlwaysOnTop(true);
+            setResizable(false);
+            pack();
+        }
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Demo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Images.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Images.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Images.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Images.java Fri May 14 02:14:30 2010
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010-2012 Pinaki Poddar
+ *
+ *
+ *  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 openbook.client;
+
+import java.awt.Image;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+/**
+ * Utility to load and cache images.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class Images {
+    
+    private static Map<String, Icon> images = new HashMap<String, Icon>();
+    public static Icon NEXT    = getIcon("images/nav_forward.gif");
+    public static Icon BACK    = getIcon("images/nav_backward.gif");
+    public static Icon DONE    = getIcon("images/done.png");
+    public static Icon CANCEL  = getIcon("images/cancel.png");
+    public static Icon ERROR   = getIcon("images/error.png");
+    public static Icon BROWSE  = getIcon("images/browse.png");
+    public static Icon START   = getIcon("images/start_task.gif");
+    public static Icon MONITOR = getIcon("images/console_view.gif");
+    
+    public static Icon getIcon(String name) {
+        Icon icon = images.get(name);
+        if (icon == null) {
+            icon = createImageIcon(name);
+            images.put(name, icon);
+        }
+        return icon;
+    }
+    
+    public static Icon getIcon(String name, boolean scale) {
+        return getIcon(name, 32, -1);
+    }
+    
+    public static Icon getIcon(String name, int width, int height) {
+        Icon icon = getIcon(name);
+        if (icon == null) {
+            return null;
+        }
+        icon = new ImageIcon(((ImageIcon)icon).getImage().getScaledInstance(32, -1, Image.SCALE_SMOOTH));
+        return icon;
+    }
+    
+    /** 
+     * Returns an ImageIcon, or null if the path was invalid. 
+     * 
+     **/
+    protected static ImageIcon createImageIcon(String path) {
+        if (path == null)
+            return null;
+        URL imgURL = Thread.currentThread().getContextClassLoader().getResource(path);
+        if (imgURL != null) {
+            return new ImageIcon(imgURL);
+        } else {
+            imgURL = Images.class.getResource(path);
+            if (imgURL != null) {
+                return new ImageIcon(imgURL);
+            } else {
+                System.err.println("Couldn't find file: " + path);
+                return null;
+            }
+        }
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/Images.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SQLLogger.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SQLLogger.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SQLLogger.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SQLLogger.java Fri May 14 02:14:30 2010
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010-2012 Pinaki Poddar
+ *
+ *
+ *  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 openbook.client;
+
+import java.awt.Color;
+import java.io.PrintStream;
+
+import javax.swing.SwingUtilities;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+import jpa.tools.swing.GraphicOutputStream;
+
+
+
+import org.apache.openjpa.lib.jdbc.AbstractJDBCListener;
+import org.apache.openjpa.lib.jdbc.JDBCEvent;
+
+/**
+ * Logs SQL statement to a graphic console.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class SQLLogger extends AbstractJDBCListener {
+    private static PrintStream out = null;
+    private static AttributeSet red, green, blue, magenta;
+    static {
+        StyleContext ctx = StyleContext.getDefaultStyleContext();
+        red = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.RED);
+        green = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.GREEN);
+        blue = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.BLUE);
+        magenta = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.MAGENTA);
+    }
+    
+    public static void setOutput(GraphicOutputStream o) {
+        out = new PrintStream(o, true);
+        o.registerStyle("INSERT", green);
+        o.registerStyle("SELECT", blue);
+        o.registerStyle("UPDATE", magenta);
+        o.registerStyle("DELETE", red);
+    }
+    
+    @Override
+    public void beforeExecuteStatement(final JDBCEvent event) {
+        if (out == null)
+            return;
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                out.println(event.getSQL());
+            }
+        });
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SQLLogger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SupplyPage.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SupplyPage.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SupplyPage.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SupplyPage.java Fri May 14 02:14:30 2010
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010-2012 Pinaki Poddar
+ *
+ *
+ *  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 openbook.client;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingWorker;
+
+import jpa.tools.swing.EntityDataModel;
+import jpa.tools.swing.EntityTableView;
+import jpa.tools.swing.ErrorDialog;
+import openbook.domain.Book;
+import openbook.domain.Inventory;
+import openbook.server.OpenBookService;
+
+/**
+ * A page to view and supply low inventory items.
+ * 
+ * @author Pinaki Poddar
+ * 
+ */
+@SuppressWarnings("serial")
+public class SupplyPage extends JPanel  {
+    private final OpenBookService _service;
+
+    private final EntityTableView<Inventory> _lowInventories;
+    
+    private final JButton _supply;
+    private final JButton _view;
+    private final JLabel  _title;
+    
+    private static int REORDER_LIMIT    = 10;
+    private static int REORDER_QUANTITY = 40;
+
+    public SupplyPage(final OpenBookService service) {
+        setLayout(new BorderLayout());
+        
+        _service = service;
+        
+        _title  = new JLabel(REORDER_LIMIT + " lowest inventory items");
+        _view   = new JButton("Show " + REORDER_LIMIT + " lowest inventory items");
+        _supply = new JButton("Supply " + REORDER_QUANTITY + " to each item");
+        
+        List<Inventory> orders = getInventory(REORDER_LIMIT);
+        _lowInventories = new EntityTableView<Inventory>(Inventory.class, 
+                orders, 
+                EntityDataModel.BASIC_ATTR | EntityDataModel.ASSOCIATION_ATTR, 
+                service.getUnit());
+        
+        add(_title, BorderLayout.NORTH);
+        add(_lowInventories, BorderLayout.CENTER);
+        JPanel buttons = new JPanel();
+        buttons.add(_view);
+        buttons.add(_supply);
+        add(buttons, BorderLayout.SOUTH);
+        
+        
+        _view.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                _lowInventories.getDataModel().updateData(getInventory(REORDER_LIMIT));
+            }
+        });
+        
+        /**
+         * Supplies each inventory displayed.
+         */
+        _supply.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                new SwingWorker<List<Inventory>, Void>() {
+                    @Override
+                    protected List<Inventory> doInBackground() throws Exception {
+                        EntityDataModel<Inventory> invs = _lowInventories.getDataModel();
+                        List<Inventory> updated = new ArrayList<Inventory>();
+                        for (Inventory inv : invs) {
+                            Book supplied = _service.supply(inv.getBook(), REORDER_QUANTITY);
+                            updated.add(supplied.getInventory());
+                        }
+                        return updated;
+                    }
+                    
+                    public void done() {
+                        try {
+                            _lowInventories.getDataModel().updateData(get(1, TimeUnit.SECONDS));
+                        } catch (Exception e) {
+                            new ErrorDialog(e).setVisible(true);
+                        }
+                    }
+                }.execute();
+                
+            }
+            
+        });
+    }
+    
+    /**
+     * Gets the orders in a background (i.e. not AWT event dispatch thread) thread.
+     * <br>
+     * But blocks painting anyway, because that is what is intended.
+     * 
+     */
+    private List<Inventory> getInventory(final Integer limit) {
+        SwingWorker<List<Inventory>, Void> worker = new SwingWorker<List<Inventory>, Void>() {
+            @Override
+            protected List<Inventory> doInBackground() throws Exception {
+                return _service.getReorderableBooks(REORDER_LIMIT);         
+            }
+        };
+        worker.execute();
+        try {
+            return worker.get();
+        } catch (Exception e) {
+            new ErrorDialog(e).setVisible(true);
+        }
+        return Collections.emptyList();
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/SupplyPage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author.java Fri May 14 02:14:30 2010
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Version;
+
+/**
+ * A persistent entity to represent an author of one or more Book.
+ * <br>
+ * <b>Notes</b>: No setter for identity value.
+ * <br>
+ * <LI><b>Identity</b>:Generated value as identity.
+ * <LI><b>Mapping</b>:Many-to-Many mapping to Books.
+ * <LI><b>Version</b>: Yes.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+@Entity
+public class Author {
+    @Id
+    @GeneratedValue
+    private long id;
+    
+    private String name;
+    
+    @ManyToMany(mappedBy="authors")
+    private Set<Book> books;
+    
+    @Version
+    private int version;
+    
+    public long getId() {
+        return id;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public Set<Book> getBooks() {
+        return books;
+    }
+    
+    public void addBook(Book book) {
+        if (books == null)
+            books = new HashSet<Book>();
+        books.add(book);
+    }
+    
+    public int getVersion() {
+        return version;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,19 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.Author.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class Author_ {
+    public static volatile SetAttribute<Author,Book> books;
+    public static volatile SingularAttribute<Author,Long> id;
+    public static volatile SingularAttribute<Author,String> name;
+    public static volatile SingularAttribute<Author,Integer> version;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Author_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book.java Fri May 14 02:14:30 2010
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Version;
+
+/**
+ * An immutable persistent entity represents a Book.
+ * <br>
+ * The mutable properties of the book such as number of items in stock etc.
+ * are factored out in a separate {@link Inventory} instance.
+ * <br>
+ * The state of inventory is mutable, but the relation to inventory is immutable. 
+ * 
+ * <LI><b>Identity</b>: Application-defined identity.
+ * <LI><b>Mapping</b>: One-to-One bi-directional, immutable mapping to {@link Inventory}.
+ * Many-to-Many bi-directional mapping to {@linkplain Author}.
+ * <LI><b>Version</b>: No.
+ * <p>
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+public class Book implements Serializable {
+    @Id
+    private String ISBN;
+    
+    private String title;
+    
+    private double price;
+    
+    @OneToOne(mappedBy="book",
+              fetch=FetchType.LAZY,
+              cascade=CascadeType.ALL,
+              optional=false,
+              orphanRemoval=true)
+    private Inventory inventory;
+    
+    @ManyToMany(fetch=FetchType.EAGER)
+    private List<Author> authors;
+    
+    /**
+     * A no-arg constructor is required for JPA Specification.
+     */
+    public Book() {
+    }
+    
+    /**
+     * Construct a book with given parameters.
+     * 
+     * @param ISBN primary identity of this Book
+     * @param title Title of the book.
+     * @param price price of the book.
+     * @param initialSupply initial inventory quantity.
+     */
+    public Book(String ISBN, String title, double price, int initialSupply) {
+        this.ISBN = ISBN;
+        this.title = title;
+        this.price = price;
+        inventory = new Inventory(this, initialSupply);
+    }
+    
+    public String getISBN() {
+        return ISBN;
+    }
+    
+    public String getTitle() {
+        return title;
+    }
+    
+    public double getPrice() {
+        return price;
+    }
+    
+    public List<Author> getAuthors() {
+        return authors;
+    }
+    
+    public void addAuthor(Author...authors) {
+        if (this.authors == null)
+            this.authors = new ArrayList<Author>();
+        for (Author a : authors) {
+            if (!this.authors.contains(a))
+                this.authors.add(a);
+        }
+    }
+    
+    public void setAuthors(List<Author> authors) {
+        this.authors = authors;
+    }
+    
+    public Inventory getInventory() {
+        return inventory;
+    }
+    
+    @Version
+    private int version;
+    
+    public int getVersion() {
+        return version;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,21 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.Book.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class Book_ {
+    public static volatile SingularAttribute<Book,String> ISBN;
+    public static volatile ListAttribute<Book,Author> authors;
+    public static volatile SingularAttribute<Book,Inventory> inventory;
+    public static volatile SingularAttribute<Book,Double> price;
+    public static volatile SingularAttribute<Book,String> title;
+    public static volatile SingularAttribute<Book,Integer> version;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Book_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer.java Fri May 14 02:14:30 2010
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Version;
+
+/**
+ * A persistent entity represents a Customer.
+ * 
+ * <br><b>Persistent Identity</b>: auto-generated identity.
+ * <br><b>Mapping</b>:
+ * 
+ * <br><b>Design Notes</b>: No setter for identity value.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+public class Customer implements Serializable {
+    @Id
+    @GeneratedValue
+    private long id;
+    private String name;
+    private String email;
+    
+    public Customer() {
+    }
+    
+    public long getId() {
+        return id;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+    
+    /**
+     * Create a {@link ShoppingCart} for this customer.
+     * @return
+     */
+    public ShoppingCart newCart() {
+        return new ShoppingCart(this);
+    }
+    
+    @Version
+    private int version;
+    
+    public int getVersion() {
+        return version;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,18 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.Customer.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class Customer_ {
+    public static volatile SingularAttribute<Customer,String> email;
+    public static volatile SingularAttribute<Customer,Long> id;
+    public static volatile SingularAttribute<Customer,String> name;
+    public static volatile SingularAttribute<Customer,Integer> version;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Customer_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory.java Fri May 14 02:14:30 2010
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+import javax.persistence.Version;
+
+/**
+ * A mutable persistent entity.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+public class Inventory implements Serializable {
+    @Id
+    @OneToOne(fetch=FetchType.EAGER, optional=false)
+    private Book book;
+    
+    private int supplied;
+    
+    private int sold;
+    
+    protected Inventory() {
+        
+    }
+    /**
+     * Construct with the given Book and initial inventory count.
+     * Package protected because only a Book can create its own inventory.
+     * 
+     * @param book non-null Book.
+     * @param initialSupply must be greater than zero.
+     */
+    Inventory(Book book, int initialSupply) {
+        if (book == null)
+            throw new NullPointerException("Can not create inventory for null Book");
+        if (initialSupply < 1)
+            throw new IllegalArgumentException("Can not create inventory " + initialSupply + " for " + book +
+                    " Initial inventory must be greater than zero.");
+        this.book = book;
+        increment(initialSupply);
+    }
+    
+    /**
+     * Gets the Book that this inventory represents.
+     * 
+     * @return non-null Book.
+     */
+    public Book getBook() {
+        return book;
+    }
+    
+    /**
+     * Gets the available quantity.
+     * This is an <em>in-flight</em> value representing the difference between the quantity supplied and quantity sold
+     * so far.
+     */
+    public int getInStock() {
+        return supplied - sold;
+    }
+    
+    /**
+     * Gets the quantity supplied so far.
+     * 
+     * @return a monotonically increasing positive number.
+     */
+    public int getSupplied() {
+        return supplied;
+    }
+    
+    /**
+     * Gets the quantity sold so far.
+     * 
+     * @return a monotonically increasing positive number.
+     */
+    public int getSold() {
+        return sold;
+    }
+    
+    /**
+     * Increment this inventory by the given quantity.
+     * 
+     * @param supplied must be positive.
+     */
+    public void increment(int supplied) {
+        if (supplied < 1)
+            throw new IllegalArgumentException("Can not add " + supplied + " supplies to " + this + 
+                    " Suuplied quanlity must be greater than zero.");
+        this.supplied += supplied;
+    }
+    
+    /**
+     * Decrement this inventory by the given quantity.
+     * 
+     * @param sold must be positive.
+     */
+    public void decrement(int sold) {
+        if (sold < 1)
+            throw new IllegalArgumentException("can not sell " + sold + "quantity to " + this 
+                    + "Sold quantity Must be greater than zero.");
+        this.sold += sold;
+    }
+    
+    @Version
+    private int version;
+    
+    public int getVersion() {
+        return version;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,18 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.Inventory.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class Inventory_ {
+    public static volatile SingularAttribute<Inventory,Book> book;
+    public static volatile SingularAttribute<Inventory,Integer> sold;
+    public static volatile SingularAttribute<Inventory,Integer> supplied;
+    public static volatile SingularAttribute<Inventory,Integer> version;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Inventory_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem.java Fri May 14 02:14:30 2010
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.OrderColumn;
+
+/**
+ * An immutable persistent entity with complex primary key.
+ * The primary key is combination of the primary identity of {@linkplain PurchaseOrder} and
+ * an 1-based integer index.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+@IdClass(LineItem.LineItemId.class)
+public class LineItem implements Serializable {
+    @Id
+    @OneToOne
+    private PurchaseOrder order;
+    
+    @Id
+    @OrderColumn
+    @Column(name="IDX") // index is keyword
+    private int index;
+    
+    @ManyToOne(optional=false)
+    private Book book;
+    
+    private int quantity;
+    
+    protected LineItem() {
+        
+    }
+    
+    /**
+     * Constructed as a line item for the given PurchaseOrder for the given Book for the given quantity.
+     * Package protected because only the PurchaseOrder can create its own LineItem.
+     *  
+     * @param order non-null PurchaseOrder
+     * @param i the 1-based index of this line item in its parent PurchaseOrder 
+     * @param book non-null Book of this line item
+     * @param quantity no. of books must be greater than zero. 
+     */
+    LineItem(PurchaseOrder order, int i, Book book, int quantity) {
+        if (order == null)
+            throw new NullPointerException("Can not create LineItem for null PurchaseOrder");
+        if (i < 1)
+            throw new IllegalArgumentException("Can not create LineItem with index " + i + ". Must be > 0");
+        if (book == null)
+            throw new NullPointerException("Can not create LineItem for null Book");
+        if (quantity < 1)
+            throw new IllegalArgumentException("Can not create LineItem with quantity " + i + ". Must be > 0");
+        
+        this.order = order;
+        this.index = i;
+        this.book = book;
+        this.quantity = quantity;
+    }
+    
+    /**
+     * Gets the Book for this line item.
+     * @return non-null Book.
+     */
+    public Book getBook() {
+        return book;
+    }
+
+    /**
+     * Gets the quantity of the book for this line item.
+     * @return a positive number.
+     */
+    public int getQuantity() {
+        return quantity;
+    }
+
+    /**
+     * Gets the parent PurchaseOrder of this line item.
+     * @return non-null PurchaseOrder.
+     */
+    public PurchaseOrder getOrder() {
+        return order;
+    }
+
+    /**
+     * Gets the 1-based index this line item in its parent PurchaseOrder.
+     * @return index must be greater than zero.
+     */
+    public int getIndex() {
+        return index;
+    }
+    
+    /**
+     * Separate identity class.
+     * 
+     * @author Pinaki Poddar
+     *
+     */
+    public static class LineItemId implements Serializable {
+        long order; 
+        int index;
+        
+        @Override
+        public boolean equals(Object other) {
+            if (other == this)
+                return true;
+            if (other instanceof LineItemId) {
+                LineItemId that = (LineItemId)other;
+                return order == that.order && index == that.index;
+            }
+            return false;
+        }
+        
+        @Override
+        public int hashCode() {
+            return (int) (31 ^ order + index);
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,18 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.LineItem.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class LineItem_ {
+    public static volatile SingularAttribute<LineItem,Book> book;
+    public static volatile SingularAttribute<LineItem,Integer> index;
+    public static volatile SingularAttribute<LineItem,PurchaseOrder> order;
+    public static volatile SingularAttribute<LineItem,Integer> quantity;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/LineItem_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder.java Fri May 14 02:14:30 2010
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+import java.sql.Time;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+/**
+ * A persistent entity.
+ * Auto-generated identity.
+ * Enum and Date type persistent attribute.
+ * One-to-One uni-directional mapping to Customer.
+ * One-to-Many bi-directional mapping to LineItem.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+public class PurchaseOrder implements Serializable {
+    public enum Status {PENDING, DELEVERED};
+    
+    @Id
+    @GeneratedValue
+    private long id;
+    
+    @OneToOne(optional=false)
+    private Customer customer;
+    
+    private Status status;
+    
+    @OneToMany(mappedBy="order", cascade=CascadeType.ALL, orphanRemoval=true)
+    private List<LineItem> items;
+    
+    private int total;
+    
+    @Temporal(TemporalType.TIME)
+    private Date placedOn;
+    
+    @Temporal(TemporalType.TIME)
+    private Date deliveredOn;
+    
+    protected PurchaseOrder() {}
+    
+    /**
+     * Constructed by transferring the content of the given {@linkplain ShoppingCart}.
+     * @param cart
+     */
+    public PurchaseOrder(ShoppingCart cart) {
+        customer = cart.getCustomer();
+        status = Status.PENDING;
+        placedOn = new Time(System.currentTimeMillis());
+        Map<Book, Integer> items = cart.getItems();
+        for (Map.Entry<Book, Integer> entry : items.entrySet()) {
+            addItem(entry.getKey(), entry.getValue());
+        }
+    }
+    
+    public long getId() {
+        return id;
+    }
+
+    public Customer getCustomer() {
+        return customer;
+    }
+    
+    public Status getStatus() {
+        return status;
+    }
+    
+    public void setDelivered() {
+        if (this.status == Status.DELEVERED)
+            throw new IllegalStateException(this + " has been delivered");
+        this.status = Status.DELEVERED;
+        this.deliveredOn = new Time(System.currentTimeMillis());
+    }
+    
+    public List<LineItem> getItems() {
+        return items;
+    }
+    
+    void addItem(Book book, int quantity) {
+        if (items == null)
+            items = new ArrayList<LineItem>();
+        items.add(new LineItem(this, items.size()+1, book, quantity));
+        total += (book.getPrice() * quantity);
+    }
+    
+    public double getTotal() {
+        return total;
+    }
+    
+    public Date getPlacedOn() {
+        return placedOn;
+    }
+
+    public Date getDeliveredOn() {
+        return deliveredOn;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder_.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder_.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder_.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder_.java Fri May 14 02:14:30 2010
@@ -0,0 +1,24 @@
+/** 
+ *  Generated by OpenJPA MetaModel Generator Tool.
+**/
+
+package openbook.domain;
+
+import java.util.Date;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import openbook.domain.PurchaseOrder.Status;
+
+@javax.persistence.metamodel.StaticMetamodel
+(value=openbook.domain.PurchaseOrder.class)
+@javax.annotation.Generated
+(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Thu May 13 20:18:23 CDT 2010")
+public class PurchaseOrder_ {
+    public static volatile SingularAttribute<PurchaseOrder,Customer> customer;
+    public static volatile SingularAttribute<PurchaseOrder,Date> deliveredOn;
+    public static volatile SingularAttribute<PurchaseOrder,Long> id;
+    public static volatile ListAttribute<PurchaseOrder,LineItem> items;
+    public static volatile SingularAttribute<PurchaseOrder,Date> placedOn;
+    public static volatile SingularAttribute<PurchaseOrder,Status> status;
+    public static volatile SingularAttribute<PurchaseOrder,Integer> total;
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/PurchaseOrder_.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Range.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Range.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Range.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Range.java Fri May 14 02:14:30 2010
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2010-2012 Pinaki Poddar
+ *
+ *
+ *  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 openbook.domain;
+
+
+/**
+ * A simple numeric range.
+ * Minimum value is included, maximum value is excluded.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class Range<N extends Number> {
+    private N min;
+    private N max;
+    private final Class<N> type;
+    
+    public Range(Object min, Object max) {
+        this((N)min, (N)max);
+    }
+
+    /**
+     * Creates a range. Empty range i.e. where minimum equals maximum is allowed.
+     * 
+     * @param min non-null minimum value.
+     * @param max non-null maximum value.
+     */
+    public Range(N min, N max) {
+        if (min == null || max == null)
+            throw new IllegalArgumentException("Supplied Min or Max is null");
+        if (max.doubleValue() < min.doubleValue())
+            throw new IllegalArgumentException("Invalid range (" + min + "," + max + ")");
+        this.min = min;
+        this.max = max;
+        type = (Class<N>)min.getClass();
+    }
+    
+    public Class<N> type() {
+        return type;
+    }
+    
+    /**
+     * Affirms if the given value is within this range.
+     * Minimum is included, maximum is excluded.
+     * 
+     * @param x a non-null value
+     * @return true if the given value is greater than or equals to minimum and less than the maximum.
+     */
+    public boolean contains(Number x) {
+        return x != null && x.doubleValue() >= min.doubleValue() && x.doubleValue() < max.doubleValue();
+    }
+    
+    /**
+     * Affirms if the given range is within this range.
+     * Minimum is included, maximum is excluded.
+     * 
+     * @param x a non-null value
+     * @return true if the given value is greater than or equals to minimum and less than the maximum.
+     */
+    public <X extends Number> boolean contains(Range<X> r) {
+        return r != null && r.getMinimum().doubleValue() >= min.doubleValue() && 
+            r.getMaximum().doubleValue() <= max.doubleValue();
+    }
+    
+    /**
+     * Gets the minimum value.
+     */
+    public N getMinimum() {
+        return min;
+    }
+    
+    /**
+     * Gets the maximum value.
+     */
+    public N getMaximum() {
+        return max;
+    }
+    
+    /**
+     * Adjusts this range by the given number.
+     * 
+     * @param x a non-null value.
+     * 
+     * @return if this range is adjusted by this value.
+     */
+    public boolean adjust(N x) {
+        if (x == null)
+            return false;
+        if (x.doubleValue() < min.doubleValue()) {
+            min = x;
+            return true;
+        }
+        if (x.doubleValue() > max.doubleValue()) {
+            max = x;
+            return true;
+        }
+        return false;
+    }
+    
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((max == null) ? 0 : max.hashCode());
+        result = prime * result + ((min == null) ? 0 : min.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Range other = (Range) obj;
+        if (max == null) {
+            if (other.max != null)
+                return false;
+        } else if (!max.equals(other.max))
+            return false;
+        if (min == null) {
+            if (other.min != null)
+                return false;
+        } else if (!min.equals(other.min))
+            return false;
+        if (type == null) {
+            if (other.type != null)
+                return false;
+        } else if (!type.equals(other.type))
+            return false;
+        return true;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/Range.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/ShoppingCart.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/ShoppingCart.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/ShoppingCart.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/ShoppingCart.java Fri May 14 02:14:30 2010
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.domain;
+
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A non-persistent entity holds the content of a shopping session for a {@linkplain Customer}.
+ * Used to create a persistent PurchaseOrder.
+ * Books can be added or removed from this cart.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class ShoppingCart implements Serializable {
+    private Customer customer;
+    private Map<Book, Integer> items;
+    
+    /**
+     * Construct a cart for the given Customer.
+     *  
+     * @param c non-null Customer.
+     */
+    ShoppingCart(Customer c) {
+        customer = c;
+        items = new HashMap<Book, Integer>();
+    }
+    
+    /**
+     * Gets the Customer who owns this cart.
+     * 
+     * @return non-null Customer.
+     */
+    public Customer getCustomer() {
+        return customer;
+    }
+    
+    /**
+     * Gets the books with their corresponding quantity in this cart.
+     * 
+     * @return
+     */
+    public Map<Book, Integer> getItems() {
+        return items;
+    }
+    
+    /**
+     * Add the given book with the given quantity in the cart.
+     * If the book already exists then the quantity is added to the existing quantity.
+     * 
+     * @param book non-null Book
+     * @param quantity a positive quantity.  
+     */
+    public void addItem(Book book, int quantity) {
+        if (book == null)
+            throw new NullPointerException("Can not add null Book to " + this);
+        if (quantity < 1)
+            throw new IllegalArgumentException("Can not add " + quantity + " " + book + " to " + this + 
+               " Added qunatity must be greater than zero");
+        int current = items.containsKey(book) ? items.get(book) : 0;
+        items.put(book, current + quantity);
+    }
+    
+    /**
+     * Change the quantity of the given book by the given delta.
+     * 
+     * @param book a non-null Book that must exist in this cart.
+     * @param delta no. of quantity to change. Can be positive or negative.
+     * If the resultant quantity becomes zero of negative, the book is removed from the cart.
+     */
+    public void changeQuantity(Book book, int delta) {
+        if (book == null)
+            throw new NullPointerException("Can not change quantity for null Book in " + this);
+        if (!items.containsKey(book))
+            throw new IllegalArgumentException("Can not change quantity for " + book + " becuase the book does not " +
+                    "exist in " + this);
+        int current = items.containsKey(book) ? items.get(book) : 0;
+        if (current + delta <= 0) {
+            items.remove(book);
+        } else {
+            items.put(book, current + delta);
+        }
+    }
+    
+    /**
+     * Removes the given book from this cart.
+     * 
+     * @param book book a non-null Book that must exist in this cart.
+     */
+    public void remove(Book book) {
+        if (book == null)
+            throw new NullPointerException("Can not remove null Book from " + this);
+        if (!items.containsKey(book))
+            throw new IllegalArgumentException("Can not remove " + book + " becuase the book does not " +
+                    "exist in " + this);
+        items.remove(book);
+    }
+    
+    public void clear() {
+        items.clear();
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/domain/ShoppingCart.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java Fri May 14 02:14:30 2010
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2010 Pinaki Poddar
+ *
+ *  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 openbook.server;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManagerFactory;
+
+import openbook.domain.Book;
+import openbook.domain.Customer;
+import openbook.domain.Inventory;
+import openbook.domain.PurchaseOrder;
+import openbook.domain.ShoppingCart;
+
+/**
+ * A simple service to select Books, purchase them and manage their inventory.
+ * A service handle can be obtained from {@link ServiceFactory#getService(String)
+ * Service Factory}. 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public interface OpenBookService {
+    public static final String DEFAULT_UNIT_NAME = "OpenBooks";
+    
+    /**
+     * Starts a session for the given named Customer.
+     * If no record of the given name exists, a new Customer record is created.
+     * 
+     * @param name name of a possibly existing customer. Or a new one.
+     * 
+     * @return a Customer
+     */
+    public Customer login(String name);
+    
+    /**
+     * Selects a list of Books matching the given conditions.
+     * Each of the conditional parameter can be null.
+     * A null parameter implies that the resultant query should ignore that parameter.
+     * 
+     * @param title title of the Book
+     * @param min minimum price
+     * @param max maximum price
+     * @param author name of author
+     * @param decorators to modify the executable query such as its range.
+     * @return
+     */
+    public List<Book> select(String title, 
+            Double min, Double max, 
+            String author, 
+            QueryDecorator...decorators);
+    /**
+     * Gets the query String for the given parameters.
+     * Each of the conditional parameter can be null.
+     * A null parameter implies that the resultant query should ignore that parameter.
+     * 
+     * @param title title of the Book
+     * @param min minimum price
+     * @param max maximum price
+     * @param author name of author
+     * @param decorators to modify the executable query such as its range.
+     * @return
+     */
+    public String getQuery(String title, 
+            Double min, Double max, 
+            String author);
+    
+    /**
+     * Runs an arbitrary JPQL query to return a list of result.
+     * 
+     * @param jpql a valid JPQL query string.
+     * @param resultClass type of the result.
+     * @param decorators zero or more QueryDecorators to be applied before Query is executed.
+     * @return the selected instances.
+     */
+    <T> List<T> query(String jpql, Class<T> resultClass, QueryDecorator...decorators);
+    <T> List<T> getExtent(Class<T> entity);
+
+    /**
+     * Buys the content of the given cart.
+     * 
+     * @param cart a non-empty cart.
+     * @return a PurchaseOrder for the content of the cart.
+     */
+    public PurchaseOrder placeOrder(ShoppingCart cart); 
+    
+    /**
+     * Delivers the given order. Delivery changes the status of the order, decrements
+     * inventory and finally removes the line items.
+     *  
+     * @param order a PENDING order to be delivered.
+     * @return the PurchaseOrder after delivery.
+     * 
+     */
+    public PurchaseOrder deliver(PurchaseOrder order);
+    
+    /**
+     * Add inventory of the given Book by the given quantity.
+     * 
+     * @param b a Book whose inventory is to be incremented
+     * @param quantity positive number.
+     * 
+     * @return the Book after incrementing its inventory.
+     */
+    public Book supply(Book b, int quantity);
+    
+    /**
+     * Gets the list of orders of given status.
+     * 
+     * @param status status of the orders. null implies all orders.
+     * 
+     * @return list of orders sorted by their placement dates.
+     */
+    public List<PurchaseOrder> getOrders(PurchaseOrder.Status status);
+    
+    
+    /**
+     * Gets the list of Books whose inventory is lower than the given limit.
+     * 
+     * @param limit reorder limit. null implies all inventory.
+     * 
+     * @return list of Books with inventory lower than the given limit.
+     */
+    public List<Inventory> getReorderableBooks(int limit);
+    
+    /**
+     * Count the number of instances of the given persistent type.
+     * 
+     * @param cls a persistent type.
+     * @return number of persistent entity of the given type.
+     */
+    public long count(Class<?> cls);
+    
+    /**
+     * Populates the underlying data repository with sample values, only if
+     * the data repository is empty.
+     * 
+     *  @param loadParameters control the number of Books etc. to be created.
+     *  null is allowed.
+     *  
+     * @return true if the repository is initialized by this invocation.
+     */
+    public boolean initialize(Map<String,Object> loadParameters);
+    public void clean();
+    /**
+     * Gets the underlying persistence unit.
+     * 
+     * @return
+     */
+    public EntityManagerFactory getUnit();
+    
+    /**
+     * Gets the name of the underlying persistence unit.
+     * 
+     * @return
+     */
+    public String getUnitName();
+    
+    /**
+     * Affirms if the transaction on this persistence unit is managed by a container.
+     * 
+     * @return
+     */
+    public boolean isManaged();
+    
+    
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java
------------------------------------------------------------------------------
    svn:eol-style = native