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 [2/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/jpa/tools/swing/PathFinder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PathFinder.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PathFinder.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PathFinder.java Fri May 14 02:14:30 2010
@@ -0,0 +1,183 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A* Algorithm to find rectilinear path through a {@link Maze}.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class PathFinder {
+ private final Maze _maze;
+
+ public PathFinder(Maze maze) {
+ _maze = maze;
+ }
+
+ /**
+ * A* algorithm to find a path through a maze.
+ * The algorithm follows these steps
+ * <LI> Add the starting square (or node) to the open list.
+ * <LI> Repeat the following:
+ * <LI> Current node is the lowest cost square on the open list
+ * <LI> Move current node to the closed list.
+ * <LI> For each of adjacent neighbor n to this current square
+ * <LI> If n is not {@link Maze#isReachable(int, int) reachable} or if n is on the closed list, ignore.
+ * Otherwise do the following.
+ * <LI> If n is not on the open list, add it to the open list. Make the current square
+ * the parent of n. Record the cost of n.
+ * <LI> If n is on the open list already, replace if this path to n is lower cost.
+ * until the target node is added to the closed list, or fail to find the target square
+ * i.e. the open list is empty.
+ *
+ * @param x1 the x-coordinate of the starting point
+ * @param y1 the y-coordinate of the starting point
+ * @param x2 the x-coordinate of the target point
+ * @param y2 the y-coordinate of the target point
+ * @return a array of points in the form of x1,y1, x2,y2, ....
+ */
+ public List<Point> findPath(int x1, int y1, int x2, int y2) {
+ Node source = new Node(null, x1, y1);
+ Node target = new Node(null, x2, y2);
+ int maxCost = distance(source, target)*2;
+ LinkedList<Node> openList = new LinkedList<Node>();
+ List<Node> closedList = new ArrayList<Node>();
+ openList.add(source);
+ do {
+ Node current = openList.remove(0);
+ closedList.add(current);
+ if (current.f < maxCost) {
+ exploreNeighbours(current, target, openList, closedList);
+ }
+ } while (!openList.isEmpty() && findMatchingNode(x2, y2, closedList) == null);
+ target = findMatchingNode(x2, y2, closedList);
+ if (target == null)
+ return traceBackPath(closedList.get(closedList.size()-1));
+ return traceBackPath(target);
+ }
+
+ private void exploreNeighbours(Node current, Node target, List<Node> openList, List<Node> closedList) {
+ insertNeighbour(current, current.x+1, current.y, target, openList, closedList);
+ insertNeighbour(current, current.x-1, current.y, target, openList, closedList);
+ insertNeighbour(current, current.x, current.y+1, target, openList, closedList);
+ insertNeighbour(current, current.x, current.y-1, target, openList, closedList);
+ Collections.sort(openList);
+ }
+
+ private Node insertNeighbour(Node n, int x, int y, Node target, List<Node> openList, List<Node> closedList) {
+ if (distance(x,y,target) != 0) {
+ if (!_maze.isReachable(x, y) || findMatchingNode(x, y, closedList) != null) {
+ return null;
+ }
+ }
+ Node m = findMatchingNode(x, y, openList);
+ if (m == null) {
+ m = new Node(n,x,y);
+ m.g = n.g + 1;
+ m.h = distance(target, m);
+ m.f = m.g + m.h;
+ openList.add(m);
+ } else if (m.g > n.g+1){
+ m.parent = n;
+ m.g = n.g + 1;
+ m.f = m.g + m.h;
+ }
+ return m;
+ }
+
+ private Node findMatchingNode(int x, int y, List<Node> list) {
+ for (Node n : list) {
+ if (n.x == x && n.y == y)
+ return n;
+ }
+ return null;
+ }
+
+ int distance(Node n, Node m) {
+ return Math.abs(n.x - m.x) + Math.abs(n.y - m.y);
+ }
+ int distance(int x, int y, Node m) {
+ return Math.abs(x - m.x) + Math.abs(y - m.y);
+ }
+
+ List<Point> traceBackPath(Node target) {
+ LinkedList<Point> path = new LinkedList<Point>();
+ path.add(new Point(target.x, target.y));
+ Node next = target.parent;
+ while (next != null) {
+ path.add(0,new Point(next.x, next.y));
+ next = next.parent;
+ }
+ return straighten(path);
+ }
+
+ List<Point> straighten(List<Point> path) {
+ if (path.size() < 3)
+ return path;
+ List<Point> mids = new ArrayList<Point>();
+ Point prev = path.get(0);
+ Point mid = path.get(1);
+ for (int i = 2; i < path.size(); i++) {
+ Point next = path.get(i);
+ if ((mid.x == prev.x && mid.x == next.x) || (mid.y == prev.y && mid.y == next.y)) {
+ mids.add(mid);
+ }
+ prev = mid;
+ mid = next;
+ }
+ path.removeAll(mids);
+ return path;
+ }
+
+ private static class Node implements Comparable<Node> {
+ int f,g,h;
+ int x; int y;
+ Node parent;
+
+ public Node(Node p, int x, int y) {
+ parent = p;
+ this.x = x;
+ this.y = y;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o instanceof Node) {
+ Node that = (Node)o;
+ return x == that.x && y == that.y;
+ }
+ return false;
+ }
+
+ @Override
+ public int compareTo(Node o) {
+ if (f == o.f) return 0;
+ return f > o.f ? 1 : -1;
+ }
+
+ public String toString() {
+ return "(" + x + "," + y + ":" + g + ")";
+ }
+ }
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PathFinder.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PowerPointViewer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PowerPointViewer.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PowerPointViewer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PowerPointViewer.java Fri May 14 02:14:30 2010
@@ -0,0 +1,253 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import openbook.client.Images;
+
+/**
+ * Displays and navigates PowerPoint slides.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class PowerPointViewer extends JPanel {
+ private List<WeakReference<ImageIcon>> _slides = new ArrayList<WeakReference<ImageIcon>>();
+ private int _total; // Total number of slides in the deck.
+ private String _dir;
+ private List<URL> _slideURLs;
+ private JButton _prev, _next;
+ private JSpinner _goto;
+ private JButton[] _navButtons;
+ private int MAX_BUTTONS = 10; // Total number of navigation buttons excluding the PREVIOUS and NEXT button.
+
+ // The slide
+ private JLabel _view;
+
+ // The key for client property in the navigation buttons denoting the 0-based index of the slides.
+ private static final String SLIDE_INDEX = "slide.index";
+
+ /**
+ * Create a viewer with slides in the specified directory.
+ *
+ * @param dir path to a directory containing PowerPoint slides.
+ * @param slides name of the slides
+ */
+ public PowerPointViewer(String dir, List<String> slides) {
+ super(true);
+ _dir = dir.endsWith("/") ? dir : dir + "/";
+ _slideURLs = validateSlides(_dir, slides);
+ _total = _slideURLs.size();
+ for (int i = 0; i < _total; i++) {
+ _slides.add(null);
+ }
+
+ setLayout(new BorderLayout());
+ _view = new JLabel(getSlideAt(0));
+ add(new JScrollPane(_view), BorderLayout.CENTER);
+ add(createNavigationButtons(), BorderLayout.SOUTH);
+ }
+
+ /**
+ * Create buttons to navigate the slides.
+ *
+ * @return a panel containing the navigation buttons.
+ */
+ private JPanel createNavigationButtons() {
+ JPanel buttons = new JPanel();
+ _navButtons = new JButton[Math.min(MAX_BUTTONS, _total)];
+ _prev = new JButton(Images.BACK);
+ buttons.add(_prev);
+ _prev.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ prevPage();
+ }
+ });
+ buttons.add(Box.createHorizontalGlue());
+ for (int i = 0; i < _navButtons.length; i++) {
+ if (i == _navButtons.length/2) {
+ JLabel gotoLabel = new JLabel("Go to ");
+ _goto = new JSpinner(new SpinnerNumberModel(1,1,_total,1));
+ buttons.add(gotoLabel);
+ buttons.add(_goto);
+ _goto.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ Integer page = (Integer)_goto.getValue();
+ showPage(page-1);
+ }
+ });
+ }
+ int slideIndex = i + 2;
+ _navButtons[i] = new JButton(""+slideIndex);
+ buttons.add(_navButtons[i]);
+ _navButtons[i].putClientProperty(SLIDE_INDEX, i+1);
+ _navButtons[i].addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JButton button = (JButton)e.getSource();
+ int index = (Integer)button.getClientProperty(SLIDE_INDEX);
+ showPage(index);
+ }
+ });
+ }
+ _next = new JButton(Images.NEXT);
+ buttons.add(Box.createHorizontalGlue());
+ buttons.add(_next);
+ _next.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ nextPage();
+ }
+ });
+ return buttons;
+
+ }
+
+ /**
+ * Show the next page.
+ */
+ private void nextPage() {
+ int current = getCurrentPageIndex();
+ if (current >= _total-1)
+ return;
+ current += 1;
+ showPage(current);
+ }
+
+ private void prevPage() {
+ int current = getCurrentPageIndex();
+ if (current <= 0)
+ return;
+ current -= 1;
+ showPage(current);
+ }
+
+ int getCurrentPageIndex() {
+ return (Integer)_goto.getValue()-1;
+ }
+
+ /**
+ * Shows the slide at the given index.
+ *
+ * @param index 0-based index of the slides.
+ */
+ private void showPage(int index) {
+ _view.setIcon(getSlideAt(index));
+ updateButtons(index);
+ }
+
+ /**
+ * Updates the buttons.
+ *
+ * @param current 0-based index of the currently displayed slide.
+ */
+ private void updateButtons(int index) {
+ _goto.setValue(index+1);
+
+ int last = index + _navButtons.length;
+ if (last >= _total)
+ return;
+
+ for (int i = 0; i < _navButtons.length; i++) {
+ int slideIndex = index+i+2;
+ _navButtons[i].setText(""+ slideIndex);
+ _navButtons[i].putClientProperty(SLIDE_INDEX, (index+i+1));
+ }
+ }
+
+ public int getSlideCount() {
+ return _total;
+ }
+
+ public ImageIcon getSlideAt(int index) {
+ WeakReference<ImageIcon> weak = _slides.get(index);
+ if (weak == null) {
+ return loadSlide(index);
+ }
+ return (weak.get() == null) ? loadSlide(index) : weak.get();
+ }
+
+ ImageIcon loadSlide(int index) {
+ URL imgURL = _slideURLs.get(index);
+ ImageIcon icon = new ImageIcon(imgURL);
+ _slides.add(index, new WeakReference<ImageIcon>(icon));
+ return icon;
+ }
+
+ List<URL> validateSlides(String dir, List<String> slides) {
+ List<URL> valid = new ArrayList<URL>();
+ for (String slide : slides) {
+ URL url = findResource(dir + slide);
+ if (url != null) {
+ valid.add(url);
+ }
+ }
+ return valid;
+ }
+
+ private URL findResource(String path) {
+ if (path == null)
+ return null;
+ URL imgURL = Thread.currentThread().getContextClassLoader().getResource(path);
+ if (imgURL == null) {
+ imgURL = getClass().getResource(path);
+ if (imgURL == null) {
+ System.err.println("Couldn't find file: " + path);
+ return null;
+ }
+ }
+ return imgURL;
+ }
+
+// private 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/jpa/tools/swing/PowerPointViewer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PreparedQueryViewer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PreparedQueryViewer.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PreparedQueryViewer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PreparedQueryViewer.java Fri May 14 02:14:30 2010
@@ -0,0 +1,39 @@
+/*
+ * 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 jpa.tools.swing;
+
+import javax.swing.JTable;
+
+
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+
+/**
+ * A specialized table to display statistics of queries.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class PreparedQueryViewer extends JTable {
+
+ public PreparedQueryViewer(OpenJPAEntityManagerFactory emf) {
+ super(new QueryStatisticsModel(((OpenJPAEntityManagerFactorySPI)emf).getConfiguration()
+ .getQuerySQLCacheInstance().getStatistics()));
+ }
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/PreparedQueryViewer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryDecorator.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryDecorator.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryDecorator.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryDecorator.java Fri May 14 02:14:30 2010
@@ -0,0 +1,29 @@
+/*
+ * 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 jpa.tools.swing;
+
+import javax.persistence.Query;
+
+/**
+ * Decorates an executable query.
+ * Concrete decorative action can be binding parameters, limiting the result range etc.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public interface QueryDecorator {
+ void decorate(Query q);
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryDecorator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryStatisticsModel.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryStatisticsModel.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryStatisticsModel.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryStatisticsModel.java Fri May 14 02:14:30 2010
@@ -0,0 +1,79 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.openjpa.kernel.QueryStatistics;
+
+@SuppressWarnings("serial")
+class QueryStatisticsModel extends AbstractTableModel {
+ QueryStatistics<String> _stats;
+ private List<String> _keys = new ArrayList<String>();
+
+ QueryStatisticsModel(QueryStatistics<String> stats) {
+ _stats = stats;
+ sortKeys(stats);
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public int getRowCount() {
+ sortKeys(_stats);
+ return _keys.size();
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ switch (columnIndex) {
+ case 0: return "Total";
+ case 1: return "Hit";
+ case 2: return "Query";
+ default : return "null";
+ }
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ String query = _keys.get(rowIndex);
+ switch (columnIndex) {
+ case 0: return _stats.getExecutionCount(query);
+ case 1: return _stats.getHitCount(query);
+ case 2: return query;
+ default : return null;
+ }
+ }
+
+ void sortKeys(QueryStatistics<String> stats) {
+ if (_stats.keys().size() != _keys.size()) {
+ _keys = new ArrayList<String>(_stats.keys());
+ if (_keys.size() > 1) {
+ Collections.sort(_keys);
+ }
+ fireTableDataChanged();
+ }
+ }
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/QueryStatisticsModel.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SQLLogger.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SQLLogger.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SQLLogger.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/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 jpa.tools.swing;
+
+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/jpa/tools/swing/SQLLogger.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/ScrollingTextPane.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/ScrollingTextPane.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/ScrollingTextPane.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/ScrollingTextPane.java Fri May 14 02:14:30 2010
@@ -0,0 +1,79 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.Timer;
+import javax.swing.UIManager;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+
+/**
+ * A TextPane where text that scrolls as new text is appended.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class ScrollingTextPane extends JTextPane {
+
+ public void appendText(String text) {
+ if (text == null)
+ return;
+ try {
+ Document doc = getDocument();
+ setCaretPosition(doc.getLength());
+ replaceSelection(text);
+ Rectangle r = modelToView(doc.getLength());
+ if (r != null) {
+ scrollRectToVisible(r);
+ }
+ } catch (Exception e) {
+
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ JFrame f = new JFrame();
+ f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ final ScrollingTextPane test = new ScrollingTextPane();
+ f.getContentPane().add(new JScrollPane(test));
+ f.pack();
+ f.setSize(600,450);
+ f.setVisible(true);
+
+ Timer timer = new Timer(1000, new ActionListener() {
+ SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss");
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ test.appendText(fmt.format(new Date()) + "\r\n");
+ }
+ });
+ timer.start();
+ }
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/ScrollingTextPane.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SourceCodeViewer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SourceCodeViewer.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SourceCodeViewer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SourceCodeViewer.java Fri May 14 02:14:30 2010
@@ -0,0 +1,161 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.swing.Box;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+
+
+/**
+ * A viewer for source code.
+ * The input to this viewer is a set of *.html file names which may or may not have anchors.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class SourceCodeViewer extends JPanel implements ActionListener {
+ private final JEditorPane _editor;
+ private final JComboBox _bookmarks;
+ private Map<String, File> _files = new TreeMap<String, File>();
+
+ public SourceCodeViewer(String dir) {
+ super(true);
+ setLayout(new BorderLayout());
+
+
+ _editor = new JEditorPane();
+ _editor.setEditorKit(new HTMLEditorKit());
+ _editor.setEditable(false);
+
+ File root = getFile(dir);
+ if (root != null) {
+ List<File> files = new FileScanner("html", true).scan(root);
+ for (File f : files) {
+ String fileName = f.getAbsolutePath();
+ String key = fileName.substring(
+ root.getAbsolutePath().length()+1,
+ fileName.length()- "html".length()-1)
+ .replace(File.separatorChar,'.');
+ _files.put(key, f);
+ }
+ }
+
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ for (String key : _files.keySet()) {
+ model.addElement(key);
+ }
+ _bookmarks = new JComboBox(model);
+ _editor.setEditable(false);
+ _bookmarks.setEditable(false);
+
+ _bookmarks.addActionListener(this);
+
+ add(new JScrollPane(_editor), BorderLayout.CENTER);
+ JPanel topPanel = new JPanel();
+ ((FlowLayout)topPanel.getLayout()).setAlignment(FlowLayout.LEADING);
+ topPanel.add(new JLabel("Select File "));
+ topPanel.add(_bookmarks);
+ topPanel.add(Box.createHorizontalGlue());
+ add(topPanel, BorderLayout.NORTH);
+ }
+
+
+
+ public void actionPerformed(ActionEvent e) {
+ String name = (String)_bookmarks.getSelectedItem();
+ try {
+ HTMLDocument doc = new HTMLDocument();
+ _editor.read(new FileInputStream(_files.get(name)), doc);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Check the given string for a matching file. The string is first
+ * tested to see if it is an existing file path. If it does not
+ * represent an existing file, it is checked as a resource name of a
+ * file.
+ * @param name the file path or resource name
+ */
+ private File getFile(String name) {
+ if (name == null)
+ return null;
+
+ File file = new File(name);
+ if (file.exists())
+ return file;
+
+ URL url = Thread.currentThread().getContextClassLoader().getResource(name);
+ if (url == null) {
+ url = getClass().getClassLoader().getResource(name);
+ }
+ if (url != null) {
+ String urlFile = url.getFile();
+ if (urlFile != null) {
+ File rsrc = new File(URLDecoder.decode(urlFile));
+ if (rsrc.exists())
+ return rsrc;
+ }
+ }
+
+ return null;
+ }
+
+
+ InputStream getResource(String resource) {
+ InputStream stream = getClass().getResourceAsStream(resource);
+ if (stream == null) {
+ stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
+ }
+ return stream;
+ }
+
+ public static void main(String[] args) throws Exception {
+ SourceCodeViewer viewer = new SourceCodeViewer(args.length == 0 ? "source" : args[0]);
+ JFrame frame = new JFrame("Source Code Viewer");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().add(viewer);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SourceCodeViewer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/StatusBar.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/StatusBar.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/StatusBar.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/StatusBar.java Fri May 14 02:14:30 2010
@@ -0,0 +1,159 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.Color;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.SwingWorker;
+import javax.swing.Timer;
+
+@SuppressWarnings("serial")
+public class StatusBar extends JPanel implements PropertyChangeListener {
+ private JProgressBar progressBar;
+ private JProgressBar memoryBar;
+ private JLabel messageText;
+ private TaskProgress task;
+
+ public StatusBar() {
+ progressBar = new JProgressBar();
+ memoryBar = new JProgressBar();
+
+ messageText = new JLabel();
+
+ setLayout(new GridLayout(1,0));
+ add(messageText);
+ add(Box.createHorizontalGlue());
+ add(memoryBar);
+ add(new JLabel("Total " + (Runtime.getRuntime().maxMemory()/1000000) + "MB"));
+ add(progressBar);
+ MemoryDisplay memory = new MemoryDisplay(memoryBar);
+ new Timer(100, memory).start();
+ }
+
+ public void showMessage(String text) {
+ messageText.setText(text);
+ }
+
+ public void startTimer(long duration, int interval, TimeUnit unit) {
+ progressBar.setEnabled(true);
+ if (duration > 0) {
+ progressBar.setStringPainted(true);
+ progressBar.setMaximum(100);
+ progressBar.setMinimum(0);
+ task = new TaskProgress(unit.toMillis(duration), interval);
+ task.addPropertyChangeListener(this);
+ task.execute();
+ } else {
+ progressBar.setStringPainted(false);
+ progressBar.setIndeterminate(true);
+ task = new TaskProgress(duration, interval);
+ task.addPropertyChangeListener(this);
+ task.execute();
+ }
+ }
+
+ /**
+ * Invoked when task's progress property changes.
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("progress".equals(evt.getPropertyName())) {
+ progressBar.setValue((Integer)evt.getNewValue());
+ }
+ }
+
+
+ public void stopTimer() {
+ if (task != null) {
+ task.cancel(true);
+ task = null;
+ }
+ progressBar.setIndeterminate(false);
+ progressBar.setString("");
+ progressBar.setEnabled(false);
+ }
+
+ /*
+ * Emits progress property from a background thread.
+ */
+ class TaskProgress extends SwingWorker<Void, Integer> {
+ private long startTimeInMillis;
+ private long _total = 100;
+ private int _interval = 100;
+
+ public TaskProgress(long total, int interval) {
+ _total = Math.max(total, 1);
+ _interval = Math.max(interval, 1);
+ }
+ @Override
+ public Void doInBackground() {
+ startTimeInMillis = System.currentTimeMillis();
+ long endTimeInMillis = startTimeInMillis + _total;
+ long current = System.currentTimeMillis();
+ while (current < endTimeInMillis && !isCancelled()) {
+ try {
+ current = System.currentTimeMillis();
+ int pctComplete = (int)((100*(current - startTimeInMillis))/_total);
+ setProgress(pctComplete);
+ Thread.sleep(_interval);
+ } catch (InterruptedException ignore) {
+ }
+ }
+ return null;
+ }
+ }
+
+ public class MemoryDisplay implements ActionListener {
+ JProgressBar bar;
+ public MemoryDisplay(JProgressBar bar) {
+ this.bar = bar;
+ bar.setStringPainted(true);
+ bar.setMinimum(0);
+ bar.setMaximum(100);
+ }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Runtime jvm = Runtime.getRuntime();
+ long totalMemory = jvm.totalMemory();
+ long usedMemory = totalMemory-jvm.freeMemory();
+ int usedPct = (int)((100*usedMemory)/totalMemory);
+ bar.setForeground(getColor(usedPct));
+ bar.setValue((int)usedPct);
+ bar.setString(usedPct + "% (" + mb(usedMemory) + "/" + mb(totalMemory) + "MB) ");
+ }
+
+ private long mb(long m) {
+ return m/1000000;
+ }
+
+ Color getColor(int pct) {
+ int red = 255*pct/100;
+ int green = 255*(100-pct)/100;
+ return new Color(red, green, 0);
+ }
+ }
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/StatusBar.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SwingHelper.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SwingHelper.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SwingHelper.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SwingHelper.java Fri May 14 02:14:30 2010
@@ -0,0 +1,147 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.concurrent.TimeUnit;
+
+import javax.imageio.ImageIO;
+import javax.swing.AbstractButton;
+import javax.swing.ButtonGroup;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.plaf.FontUIResource;
+
+
+/**
+ * Assorted utility methods.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class SwingHelper {
+ /**
+ * Position the given component at the center of the given parent component or physical screen.
+ *
+ * @param c the component to be positioned
+ * @param parent the component whose center will match the center of the given component.
+ * If null, the given component will match the screen center.
+ *
+ */
+ public static void position(Component c, Component parent) {
+ Dimension d = c.getPreferredSize();
+ if (parent == null) {
+ Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
+ c.setLocation(s.width/2 - d.width/2, s.height/2 - d.height/2);
+ } else {
+ Point p = parent.getLocationOnScreen();
+ int pw = parent.getWidth();
+ int ph = parent.getHeight();
+ c.setLocation(p.x + pw/2 - d.width/2, p.y + ph/2 - d.height/2);
+ }
+ }
+
+ private static int[] factors = {1000, 1000, 1000, 1000, 60, 60, 24};
+
+ public static String getTimeString(long value, TimeUnit unit) {
+ if (value <= 0)
+ return "";
+ int i = unit.ordinal();
+ TimeUnit[] units = TimeUnit.values();
+ TimeUnit next = null;
+ int factor = -1;
+ if (i < factors.length -1) {
+ next = units[i+1];
+ factor = factors[i+1];
+ long nextValue = value/factor;
+ if (nextValue > 0)
+ return getTimeString(value/factor, next) + " " + getTimeString(value%factor, unit);
+ }
+
+ return value + toString(unit);
+ }
+
+ public static String toString(TimeUnit unit) {
+ switch (unit) {
+ case HOURS:
+ case DAYS:
+ case MINUTES:
+ case SECONDS:
+ return unit.toString().substring(0,1).toLowerCase();
+ case MILLISECONDS:
+ return "ms";
+ case MICROSECONDS:
+ return "micros";
+ case NANOSECONDS:
+ return "ns";
+ }
+ return "";
+ }
+
+ public static void print(Component c, String format, File output) {
+ try {
+ Robot robot = new Robot();
+ Point root = c.getLocationOnScreen();
+ BufferedImage shot = robot.createScreenCapture(new Rectangle(root.x, root.y, c.getWidth(), c.getHeight()));
+ ImageIO.write(shot, format, output);
+ } catch (AWTException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public static AbstractButton getSelectedButton(ButtonGroup group) {
+ Enumeration<AbstractButton> buttons = group.getElements();
+ while (buttons.hasMoreElements()) {
+ AbstractButton b = buttons.nextElement();
+ if (b.isSelected()) {
+ return b;
+ }
+ }
+ return null;
+ }
+
+ public static void setLookAndFeel(int fontSize) throws Exception {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ UIDefaults defaults = UIManager.getDefaults();
+ Enumeration<Object> keys = defaults.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+
+ if ((key instanceof String) && (((String) key).endsWith(".font"))) {
+ FontUIResource font = (FontUIResource) UIManager.get(key);
+ defaults.put (key, new FontUIResource(font.getFontName(), font.getStyle(), fontSize));
+ }
+ }
+ }
+
+
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/SwingHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/TextStyles.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/TextStyles.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/TextStyles.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/TextStyles.java Fri May 14 02:14:30 2010
@@ -0,0 +1,42 @@
+/*
+ * 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 jpa.tools.swing;
+
+import java.awt.Color;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+public class TextStyles {
+ public static AttributeSet KEYS, VALUES;
+ static {
+ StyleContext ctx = StyleContext.getDefaultStyleContext();
+ KEYS = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.BLUE);
+ KEYS = ctx.addAttribute(KEYS, StyleConstants.Bold, true);
+ KEYS = ctx.addAttribute(KEYS, StyleConstants.FontSize, 14);
+ KEYS = ctx.addAttribute(KEYS, StyleConstants.FontFamily, "Courier");
+
+ Color indianRed = new Color(205, 92, 92);
+ VALUES = ctx.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, indianRed);
+ VALUES = ctx.addAttribute(VALUES, StyleConstants.Bold, true);
+ VALUES = ctx.addAttribute(VALUES, StyleConstants.FontFamily, "Courier");
+ VALUES = ctx.addAttribute(VALUES, StyleConstants.FontSize, 14);
+ }
+
+}
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/TextStyles.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/package.html
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/package.html?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/package.html (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/package.html Fri May 14 02:14:30 2010
@@ -0,0 +1,5 @@
+<html>
+<body>
+Swing widgets to browse persistent entities using JPA 2.0 MetaModel API.
+</body>
+</html>
\ No newline at end of file
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/BuyBookPage.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/BuyBookPage.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/BuyBookPage.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/BuyBookPage.java Fri May 14 02:14:30 2010
@@ -0,0 +1,459 @@
+/*
+ * 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.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.SwingConstants;
+import javax.swing.SwingWorker;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import jpa.tools.swing.EntityDataModel;
+import jpa.tools.swing.EntityTable;
+import jpa.tools.swing.EntityTableView;
+import jpa.tools.swing.ErrorDialog;
+import openbook.domain.Author;
+import openbook.domain.Book;
+import openbook.domain.Customer;
+import openbook.domain.PurchaseOrder;
+import openbook.domain.ShoppingCart;
+import openbook.server.OpenBookService;
+import openbook.server.QueryDecorator;
+
+import org.apache.openjpa.lib.jdbc.SQLFormatter;
+
+/**
+ * A visual page coordinates the following functions of {@link OpenBookService} :
+ * <li>query for books
+ * <li>choose one or more of the selected books
+ * <li>add them to Shopping Cart
+ * <li>place a purchase order of the books in the shopping cart.
+ * <p>
+ * Each interaction with the underlying service occurs in a background i.e.
+ * a <em>non</em>-AWT event dispatching thread. The background threads are
+ * used via {@link SwingWorker} and hence each persistence operation is
+ * can be potentially handled by a different JPA persistence context.
+ * This threading model not only adheres to the good practice of responsive graphical
+ * user interface design, it exercises the <em>remote</em> nature of JPA service
+ * (even within this single process Swing application) where every operation
+ * on a persistence context results into a set of <em>detached</em> instances
+ * to the remote client.
+ *
+ * @author Pinaki Poddar
+ */
+@SuppressWarnings("serial")
+public final class BuyBookPage extends JPanel {
+ private final OpenBookService _service;
+ private final Customer _customer;
+ private final SearchPanel _searchPanel;
+ private final BuyPanel _buyPanel;
+ private final SelectBookPanel _selectPanel;
+ private final ShoppingCartPanel _cartPanel;
+
+ /**
+ * A Page with 2x2 Grid of panels each for one of the specific action.
+ *
+ * @param service the OpenBooks service handle.
+ */
+ public BuyBookPage(OpenBookService service, Customer customer) {
+ super(true);
+ _service = service;
+ _customer = customer;
+
+ GridLayout gridLayout = new GridLayout(2, 2);
+ this.setLayout(gridLayout);
+
+ _searchPanel = new SearchPanel("Step 1: Search for Books");
+ _selectPanel = new SelectBookPanel("Step 2: Select Books to view details");
+ _buyPanel = new BuyPanel("Step 3: Add Book to Shopping Cart");
+ _cartPanel = new ShoppingCartPanel("Step 4: Purchase Books in the Shopping Cart");
+
+ add(_searchPanel);
+ add(_cartPanel);
+ add(_selectPanel);
+ add(_buyPanel);
+
+ _selectPanel._selectedBooks.getTable()
+ .getSelectionModel()
+ .addListSelectionListener(_buyPanel);
+ }
+
+ /**
+ * A form like panel displays the different fields to search for books.
+ * Zero or more form fields can be filled in. Though the service level
+ * contract does not mandate how to form the exact query from the form
+ * field values, the actual implementation demonstrates how dynamic
+ * query construction introduced via Criteria Query API in JPA 2.0
+ * can aid in such common user scenarios.
+ * <br>
+ * The object level query is displayed to demonstrate the ability of
+ * OpenJPA to express a dynamic Criteria Query is a human-readable,
+ * JPQL-like query string.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+ class SearchPanel extends JPanel implements ActionListener {
+ private final JTextField _title = new JTextField("", 20);
+ private final JTextField _author = new JTextField("", 20);
+ private final JTextField _maxPrice = new JTextField("", 6);
+ private final JTextField _minPrice = new JTextField("", 6);
+ private final JTextArea _queryView = new JTextArea();
+ private final SQLFormatter _formatter = new SQLFormatter();
+
+ SearchPanel(String title) {
+ super(true);
+ setBorder(BorderFactory.createTitledBorder(title));
+
+ JButton searchButton = new JButton("Search", Images.START);
+ searchButton.setHorizontalTextPosition(SwingConstants.LEADING);
+
+ JLabel titleLabel = new JLabel("Title :", SwingConstants.RIGHT);
+ JLabel authorLabel = new JLabel("Author:", SwingConstants.RIGHT);
+ JLabel priceLabel = new JLabel("Price :", SwingConstants.RIGHT);
+ JLabel fromLabel = new JLabel("from ", SwingConstants.RIGHT);
+ JLabel toLabel = new JLabel("to ", SwingConstants.RIGHT);
+
+ JPanel panel = new JPanel();
+ GroupLayout layout = new GroupLayout(panel);
+ panel.setLayout(layout);
+ layout.setAutoCreateContainerGaps(true);
+ layout.setAutoCreateGaps(true);
+ GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
+ hGroup.addGroup(layout.createParallelGroup()
+ .addComponent(titleLabel)
+ .addComponent(authorLabel)
+ .addComponent(priceLabel));
+ hGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
+ .addComponent(_title)
+ .addComponent(_author)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(fromLabel)
+ .addComponent(_minPrice)
+ .addComponent(toLabel)
+ .addComponent(_maxPrice)));
+
+ GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
+ vGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
+ .addComponent(titleLabel)
+ .addComponent(_title));
+ vGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
+ .addComponent(authorLabel)
+ .addComponent(_author));
+ vGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
+ .addComponent(priceLabel)
+ .addComponent(fromLabel)
+ .addComponent(_minPrice)
+ .addComponent(toLabel)
+ .addComponent(_maxPrice));
+
+ layout.setHorizontalGroup(hGroup);
+ layout.setVerticalGroup(vGroup);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.add(Box.createHorizontalGlue());
+ buttonPanel.add(searchButton);
+ buttonPanel.add(Box.createHorizontalGlue());
+
+ BoxLayout box = new BoxLayout(this, BoxLayout.Y_AXIS);
+ setLayout(box);
+ add(panel);
+ add(Box.createVerticalGlue());
+ add(buttonPanel);
+
+ _queryView.setBorder(BorderFactory.createTitledBorder("Criteria Query as CQL"));
+ _queryView.setWrapStyleWord(true);
+ _queryView.setEditable(false);
+ _queryView.setBackground(getBackground());
+ add(_queryView);
+ searchButton.addActionListener(this);
+ }
+
+ /**
+ * Execute a query and displays the result onto {@linkplain SelectBookPanel}.
+ *
+ * The query is executed in a background, non-AWT thread.
+ */
+ public void actionPerformed(ActionEvent e) {
+ new SwingWorker<List<Book>, Void>() {
+ private String queryString;
+ @Override
+ protected List<Book> doInBackground() throws Exception {
+ queryString = _service.getQuery(_title.getText(),
+ asDouble(_minPrice), asDouble(_maxPrice),
+ _author.getText());
+ return _service.select(_title.getText(),
+ asDouble(_minPrice), asDouble(_maxPrice),
+ _author.getText(),
+ (QueryDecorator[])null);
+ }
+
+ @Override
+ protected void done() {
+ try {
+ _queryView.setText(_formatter.prettyPrint(queryString).toString());
+ List<Book> selectedBooks = get(1, TimeUnit.SECONDS);
+ _selectPanel.updateDataModel(selectedBooks);
+ } catch (Exception e) {
+ new ErrorDialog(e).setVisible(true);
+ }
+ }
+ }.execute();
+ }
+
+ boolean isEmpty(JTextField text) {
+ if (text == null)
+ return true;
+ String s = text.getText();
+ return s == null || s.isEmpty() || s.trim().isEmpty();
+ }
+
+ Double asDouble(JTextField field) {
+ if (isEmpty(field)) return null;
+ try {
+ return Double.parseDouble(field.getText());
+ } catch (NumberFormatException e) {
+ System.err.println("Can not convert [" + field.getText() + "] to a double");
+ }
+ return null;
+ }
+ }
+
+ /**
+ * A panel to display the selected books in a tabular format.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+ class SelectBookPanel extends JPanel {
+ private final JLabel _bookCount;
+ private final EntityTableView<Book> _selectedBooks;
+
+ SelectBookPanel(String title) {
+ setLayout(new BorderLayout());
+ setBorder(BorderFactory.createTitledBorder(title));
+
+ _selectedBooks = new EntityTableView<Book>(Book.class,
+ EntityDataModel.BASIC_ATTR | EntityDataModel.ROW_COUNT,
+ _service.getUnit());
+ _bookCount = new JLabel();
+
+ add(_bookCount, BorderLayout.NORTH);
+ add(_selectedBooks, BorderLayout.CENTER);
+ }
+
+ void updateDataModel(List<Book> books) {
+ _bookCount.setText(books.size() + " Book selected");
+ _selectedBooks.getDataModel().updateData(books);
+ }
+ }
+
+ /**
+ * A panel to display the details of a single book and a button to add the
+ * book to cart. Listens to the selection in the selected books.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+ class BuyPanel extends JPanel implements ListSelectionListener {
+ JLabel _bookTitle;
+ JLabel _bookAuthors;
+ JLabel _bookPrice;
+ JLabel _bookISBN;
+ JButton _addToCart;
+ JSpinner _quantity;
+ JPanel _quantityPanel;
+
+ public BuyPanel(String title) {
+ super(true);
+
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ setBorder(BorderFactory.createTitledBorder(title));
+
+ JPanel descPanel = new JPanel();
+ descPanel.setLayout(new BoxLayout(descPanel, BoxLayout.Y_AXIS));
+ _bookTitle = new JLabel();
+ _bookAuthors = new JLabel();
+ _bookPrice = new JLabel();
+ _bookISBN = new JLabel();
+ descPanel.add(_bookTitle);
+ descPanel.add(_bookAuthors);
+ descPanel.add(_bookPrice);
+ descPanel.add(_bookISBN);
+ add(descPanel);
+
+ _quantityPanel = new JPanel();
+ SpinnerNumberModel spinnerModel = new SpinnerNumberModel(1, 1, 10, 1);
+ _quantity = new JSpinner(spinnerModel);
+ _quantityPanel.add(new JLabel("Quantity:"));
+ _quantity.setEnabled(false);
+ _quantityPanel.add(_quantity);
+ _quantityPanel.setVisible(false);
+ add(_quantityPanel);
+
+ add(Box.createVerticalGlue());
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.add(Box.createHorizontalGlue());
+ _addToCart = new JButton("Add to Cart", Images.getIcon("images/Add2Cart.jpg", true));
+ _addToCart.setEnabled(false);
+ buttonPanel.add(_addToCart);
+ buttonPanel.add(Box.createHorizontalGlue());
+ add(buttonPanel);
+
+ _addToCart.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ _cartPanel.addBook((Book)_addToCart.getClientProperty("Book"),
+ (Integer)_quantity.getValue());
+ }
+ });
+ }
+
+ void showBookDetails(Book book) {
+ _bookTitle.setText(book.getTitle());
+ List<Author> authors = book.getAuthors();
+ if (authors != null && !authors.isEmpty()) {
+ StringBuilder names = new StringBuilder();
+ for (Author author : authors) {
+ if (names.length() != 0) names.append(", ");
+ names.append(author.getName());
+ }
+ _bookAuthors.setText("by " + names);
+ }
+ _bookPrice.setText("Price:" + book.getPrice());
+ _bookISBN.setText("ISBN: " + book.getISBN());
+ _addToCart.setEnabled(true);
+ _quantity.setEnabled(true);
+ _quantityPanel.setVisible(true);
+ _addToCart.putClientProperty("Book", book);
+ }
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ EntityTable<Book> table = _selectPanel._selectedBooks.getTable();
+ int row = table.getSelectedRow();
+ if (row == -1)
+ return;
+ int col = table.getSelectedColumn();
+ if (col == -1)
+ return;
+ EntityDataModel<Book> model = (EntityDataModel<Book>) table.getModel();
+ Book book = model.getRow(row);
+ showBookDetails(book);
+ }
+ }
+
+ /**
+ * A panel to display the shopping cart.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+ class ShoppingCartPanel extends JPanel implements ActionListener {
+ private static final int MAX_ITEMS = 10;
+ private final ShoppingCart _cart;
+ private final JButton _placeOrder;
+ private final JLabel[] _items = new JLabel[MAX_ITEMS];
+
+ public ShoppingCartPanel(String title) {
+ _cart = _customer.newCart();
+ setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
+ setBorder(BorderFactory.createTitledBorder(title));
+ _placeOrder = new JButton("Place Order", Images.START);
+ _placeOrder.setHorizontalTextPosition(SwingConstants.LEADING);
+
+ _placeOrder.setEnabled(false);
+ for (int i = 0; i < MAX_ITEMS; i++) {
+ _items[i] = new JLabel("");
+ add(_items[i]);
+ }
+ add(Box.createVerticalGlue());
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.add(Box.createHorizontalGlue());
+ buttonPanel.add(_placeOrder);
+ buttonPanel.add(Box.createHorizontalGlue());
+ add(buttonPanel);
+ _placeOrder.addActionListener(this);
+ }
+
+ /**
+ * Add the given book to the cart. Updates the display.
+ */
+ public void addBook(Book book, int quantity) {
+ _cart.addItem(book, quantity);
+ updateDisplay();
+ }
+
+ void updateDisplay() {
+ Map<Book, Integer> items = _cart.getItems();
+ int i = 0;
+ for (Map.Entry<Book, Integer> entry : items.entrySet()) {
+ JLabel item = _items[i++];
+ int quantity = entry.getValue();
+ Book book = entry.getKey();
+ item.setText(quantity + (quantity == 1 ? " copy of " : " copies of ") + book.getTitle());
+ item.setIcon(Images.DONE);
+ }
+ _placeOrder.setEnabled(items.size()>0);
+ super.repaint();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ new SwingWorker<PurchaseOrder, Void>() {
+ @Override
+ protected PurchaseOrder doInBackground() throws Exception {
+ return _service.placeOrder(_cart);
+ }
+
+ @Override
+ protected void done() {
+ try {
+ get(1, TimeUnit.SECONDS);
+ _cart.clear();
+ for (int i = 0; i < MAX_ITEMS; i++) {
+ _items[i].setText("");
+ _items[i].setIcon(null);
+ }
+ _placeOrder.setEnabled(false);
+ } catch (Exception e) {
+ new ErrorDialog(e).setVisible(true);
+ }
+ }
+ }.execute();
+ }
+ }
+}
\ No newline at end of file
Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/BuyBookPage.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/DeliveryPage.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/DeliveryPage.java?rev=944083&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/DeliveryPage.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/client/DeliveryPage.java Fri May 14 02:14:30 2010
@@ -0,0 +1,170 @@
+/*
+ * 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.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.SwingWorker;
+
+import jpa.tools.swing.EntityDataModel;
+import jpa.tools.swing.EntityTableView;
+import jpa.tools.swing.ErrorDialog;
+import openbook.domain.PurchaseOrder;
+import openbook.server.OpenBookService;
+
+/**
+ * A page to control delivery of pending orders.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class DeliveryPage extends JPanel {
+ private final JButton _deliver;
+ private EntityTableView<PurchaseOrder> _orders;
+ private final OpenBookService _service;
+ private final JLabel _title;
+ private final JRadioButton _showPending;
+ private final JRadioButton _showDelivered;
+ private final JRadioButton _showBoth;
+
+ public DeliveryPage(final OpenBookService service) {
+ setLayout(new BorderLayout());
+
+ _service = service;
+
+ _orders = new EntityTableView<PurchaseOrder>(PurchaseOrder.class, getOrders(PurchaseOrder.Status.PENDING),
+ EntityDataModel.ALL_ATTR, service.getUnit());
+
+ _title = new JLabel(_orders.getDataModel().getRowCount() + " " + PurchaseOrder.Status.PENDING
+ + " PurchaseOrder");
+
+ _deliver = new JButton("Deliver Pending Orders");
+
+ JPanel statusPanel = new JPanel();
+ ButtonGroup statusSelection = new ButtonGroup();
+ _showPending = new JRadioButton("Pending");
+ _showDelivered = new JRadioButton("Delivered");
+ _showBoth = new JRadioButton("All");
+ _showPending.setSelected(true);
+
+ statusSelection.add(_showPending);
+ statusSelection.add(_showDelivered);
+ statusSelection.add(_showBoth);
+ statusPanel.add(_showBoth);
+ statusPanel.add(_showPending);
+ statusPanel.add(_showDelivered);
+
+ JPanel actionPanel = new JPanel();
+ actionPanel.add(_deliver);
+
+ add(statusPanel, BorderLayout.NORTH);
+ add(_orders, BorderLayout.CENTER);
+
+ add(actionPanel, BorderLayout.SOUTH);
+
+ _showBoth.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ List<PurchaseOrder> selected = getOrders(null);
+ _orders.getDataModel().updateData(selected);
+ _title.setText(selected.size() + " PurchaseOrder");
+ }
+ });
+ _showPending.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ List<PurchaseOrder> selected = getOrders(PurchaseOrder.Status.PENDING);
+ _orders.getDataModel().updateData(selected);
+ _title.setText(selected.size() + " Pending PurchaseOrder");
+ }
+ });
+ _showDelivered.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ List<PurchaseOrder> selected = getOrders(PurchaseOrder.Status.DELEVERED);
+ _orders.getDataModel().updateData(selected);
+ _title.setText(selected.size() + " Delivered PurchaseOrder");
+ }
+ });
+
+ _deliver.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ new SwingWorker<List<PurchaseOrder>, Void>() {
+ @Override
+ protected List<PurchaseOrder> doInBackground() throws Exception {
+ List<PurchaseOrder> updated = new ArrayList<PurchaseOrder>();
+ EntityDataModel<PurchaseOrder> orders = _orders.getDataModel();
+ int n = orders.getRowCount();
+ for (int i = 0; i < n; i++) {
+ PurchaseOrder order = orders.getRow(i);
+ if (order.getStatus() == PurchaseOrder.Status.PENDING) {
+ updated.add(_service.deliver(order));
+ }
+ }
+ return updated;
+ }
+
+ @Override
+ public void done() {
+ try {
+ List<PurchaseOrder> updated = get(10, TimeUnit.SECONDS);
+ _orders.getDataModel().updateData(updated);
+ _title.setText(updated.size() + "" + " Updated PurchaseOrder");
+ } 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<PurchaseOrder> getOrders(final PurchaseOrder.Status status) {
+ SwingWorker<List<PurchaseOrder>, Void> worker = new SwingWorker<List<PurchaseOrder>, Void>() {
+ @Override
+ protected List<PurchaseOrder> doInBackground() throws Exception {
+ return _service.getOrders(status);
+ }
+ };
+ 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/DeliveryPage.java
------------------------------------------------------------------------------
svn:eol-style = native