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/08/24 20:11:27 UTC

svn commit: r988644 [2/3] - in /openjpa/trunk/openjpa-examples/opentrader: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/openjpa/ src/main/java/org/apache/openjpa/trader/ src/main/java/org/apache...

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/TradingWindow.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/TradingWindow.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/TradingWindow.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/TradingWindow.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client;
+
+import java.util.List;
+
+import org.apache.openjpa.trader.client.event.ServiceEvent;
+import org.apache.openjpa.trader.client.event.ServiceEventHandler;
+import org.apache.openjpa.trader.client.ui.GridCellRenderer;
+import org.apache.openjpa.trader.client.ui.ScrollableTable;
+import org.apache.openjpa.trader.domain.Ask;
+import org.apache.openjpa.trader.domain.Bid;
+import org.apache.openjpa.trader.domain.Match;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Trading Window allows the user to buy/sell a {@link Tradable tradable} or withdraw it.
+ * <br>
+ * This widget demonstrates combination of both read-only and updatable visual elements 
+ * as well as active widgets such as a button.
+ * <br>
+ * Both the user actions (such as when a tradable is withdrawn) or other events such
+ * as a Stock price change changes the expected gain/loss of a tradable,  
+ * <br>
+ * The complexity arises from the fact that a displayed tradable may have been consumed
+ * by a matching tradable in another session. A tradable undergoes a state transition when
+ * it is traded. Thus the displayed tradable can be an inconsistent state than its original
+ * state in the server. Though all the displayed tradables are periodically refreshed, the
+ * latency still exists.  
+ *   
+ *   
+ * @author Pinaki Poddar
+ *
+ */
+public class TradingWindow extends ScrollableTable<Tradable> 
+       implements ServiceEventHandler.AddTradableHandler,
+                  ServiceEventHandler.RemoveTradableHandler, 
+                  ServiceEventHandler.UpdateStockHandler {
+    private final OpenTrader session;
+    private Timer refreshTimer;
+    private int refreshInterval = 60*1000;
+
+    public TradingWindow(final OpenTrader session, final int w, final int h) {
+        super("Trading Window for " + session.getTrader().getName(), w, h, true);
+        this.session = session;
+
+        session.registerHandler(ServiceEvent.TradableAdded.TYPE, this);
+        session.registerHandler(ServiceEvent.TradableRemoved.TYPE, this);
+        session.registerHandler(ServiceEvent.StockUpdated.TYPE, this);
+
+        setColumnHeader(0, "Stock", "15%");
+        setColumnHeader(1, "Market", "15%");
+        setColumnHeader(2, "Price", "15%");
+        setColumnHeader(3, "Volume", "15%");
+        setColumnHeader(4, "Gain/Loss", "15%");
+        setColumnHeader(5, "Buy/Sell", "15%");
+        setColumnHeader(6, "Withdraw", "15%");
+
+        setRenderer(0, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable model) {
+                return new Label(model.getStock().getSymbol());
+            }
+        });
+
+        // Market Price as changing Label
+        setRenderer(1, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable model) {
+                return FormatUtil.formatPrice(model.getStock().getMarketPrice());
+            }
+        });
+
+        // Ask/Bid Price as Label
+        setRenderer(2, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable model) {
+                return FormatUtil.formatPrice(model.getPrice());
+            }
+        });
+
+        // Ask/Bid Volume as Label
+        setRenderer(3, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable model) {
+                return FormatUtil.formatVolume(model.getVolume());
+            }
+        });
+
+        // Gain or loss
+        setRenderer(4, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable t) {
+                return FormatUtil.formatChange(t.getGain());
+            }
+        });
+
+        // Buy/Sell Button
+        setRenderer(5, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable t) {
+                String action = t instanceof Ask ? "Sell" : "Buy";
+                Button button = new Button(action);
+                button.addClickHandler(new MatchCallback(t));
+                return button;
+            }
+        });
+
+        // Withdraw button
+        setRenderer(6, new GridCellRenderer<Tradable>() {
+            public Widget render(Tradable t) {
+                Button button = new Button("Withdraw");
+                button.addClickHandler(new WithdrawCallback(t));
+                return button;
+            }
+        });
+    }
+
+    /**
+     * Starts to run a period update of the tradables from the server.
+     */
+    public void startTradableRefresher() {
+        if (refreshTimer != null)
+            return;
+        // Setup timer to refresh list automatically.
+        Timer refreshTimer = new Timer() {
+            @Override
+            public void run() {
+                int n = getRowCount();
+                for (int i = 0; i < n; i++) {
+                    Tradable t = get(i);
+                    if (t != null) {
+                        session.getService().refresh(t, new RefreshTradableCallback(t));
+                    }
+                }
+            }
+        };
+        refreshTimer.run();
+        refreshTimer.scheduleRepeating(refreshInterval);
+    }
+
+    public void stopTradableRefresher() {
+        if (refreshTimer == null)
+            return;
+        refreshTimer.cancel();
+        refreshTimer = null;
+    }
+
+
+    @Override
+    public void onTradableAdded(ServiceEvent.TradableAdded event) {
+        insert(event.getPayload());
+    }
+
+    @Override
+    public void onTradableRemoved(ServiceEvent.TradableRemoved event) {
+        remove(event.getPayload());
+    }
+
+    @Override
+    public void onStockUpdated(ServiceEvent.StockUpdated event) {
+        int n = getRowCount();
+        Stock updatedStock = event.getPayload();
+        for (int i = 0; i < n; i++) {
+            Tradable t = get(i);
+            if (updatedStock.equals(t.getStock())) {
+                t.updateStock(updatedStock);
+                update(t, new Integer[]{1,4});
+            }
+        }
+    }
+
+    class WithdrawCallback implements AsyncCallback<Tradable>, ClickHandler {
+        private final Tradable tradable;
+
+        WithdrawCallback(Tradable source) {
+            tradable = source;
+        }
+
+        public void onFailure(Throwable caught) {
+            session.handleError(caught);
+        }
+
+        public void onSuccess(Tradable result) {
+            session.fireEvent(new ServiceEvent.TradableRemoved(result));
+        }
+
+        @Override
+        public void onClick(ClickEvent event) {
+            session.getService().withdraw(tradable, this);
+        }
+    }
+
+    public class MatchCallback implements AsyncCallback<List<Match>>, ClickHandler {
+        final Tradable tradable;
+
+        public MatchCallback(Tradable tradable) {
+            super();
+            this.tradable = tradable;
+        }
+
+        public void onFailure(Throwable caught) {
+            session.handleError(caught);
+        }
+
+        public void onSuccess(List<Match> result) {
+            new MatchWindow(session, tradable, result).center();
+        }
+
+        @Override
+        public void onClick(ClickEvent event) {
+            if (tradable instanceof Ask) {
+                session.getService().matchAsk((Ask) tradable, this);
+            } else {
+                session.getService().matchBid((Bid) tradable, this);
+            }
+        }
+    }
+
+    public class RefreshTradableCallback implements AsyncCallback<Tradable> {
+        final Tradable tradable;
+        public RefreshTradableCallback(Tradable tradable) {
+            super();
+            this.tradable = tradable;
+        }
+
+        @Override
+        public void onSuccess(Tradable result) {
+            if (result == null) {
+                remove(tradable);
+            } else if (result.isTraded()) {
+                remove(result);
+                session.fireEvent(new ServiceEvent.TradeCommitted(result.getTrade()));
+            } else {
+                update(result, new Integer[]{1,4});
+            }
+        }
+        
+        @Override
+        public void onFailure(Throwable t) {
+            session.handleError(t);
+        }
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/TradingWindow.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEvent.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEvent.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEvent.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEvent.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.event;
+
+import org.apache.openjpa.trader.client.OpenTrader;
+import org.apache.openjpa.trader.client.event.ServiceEventHandler.UpdateStockHandler;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trade;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+
+/**
+ * Specialization of GWTEvent (that represent mouse/keybord events and DOM events) 
+ * for service related events such as a new trade has been committed or a tradable
+ * is consumed. Each service event carries a payload and one or more handlers can
+ * register interest in that event via the 
+ * {@link OpenTrader#registerHandler(com.google.gwt.event.shared.GwtEvent.Type, EventHandler) 
+ * application controller}.
+ *   
+ * @author Pinaki Poddar
+ *
+ * @param <T>
+ * @param <H>
+ */
+public abstract class ServiceEvent<T, H extends EventHandler> extends GwtEvent<H> {
+    private final T payload;
+
+    protected ServiceEvent(T data) {
+        payload = data;
+    }
+
+    public final T getPayload() {
+        return payload;
+    }
+
+    public static class TradableAdded extends ServiceEvent<Tradable, ServiceEventHandler.AddTradableHandler> {
+        public static Type<ServiceEventHandler.AddTradableHandler> TYPE = new Type<ServiceEventHandler.AddTradableHandler>();
+
+        public TradableAdded(Tradable tradable) {
+            super(tradable);
+        }
+
+        @Override
+        protected void dispatch(ServiceEventHandler.AddTradableHandler handler) {
+
+            handler.onTradableAdded(this);
+        }
+
+        @Override
+        public com.google.gwt.event.shared.GwtEvent.Type<ServiceEventHandler.AddTradableHandler> getAssociatedType() {
+            return TYPE;
+        }
+    }
+
+    public static class TradableRemoved extends ServiceEvent<Tradable, ServiceEventHandler.RemoveTradableHandler> {
+        public static Type<ServiceEventHandler.RemoveTradableHandler> TYPE = new Type<ServiceEventHandler.RemoveTradableHandler>();
+
+        public TradableRemoved(Tradable tradable) {
+            super(tradable);
+        }
+
+        @Override
+        protected void dispatch(ServiceEventHandler.RemoveTradableHandler handler) {
+            handler.onTradableRemoved(this);
+        }
+
+        @Override
+        public com.google.gwt.event.shared.GwtEvent.Type<ServiceEventHandler.RemoveTradableHandler> getAssociatedType() {
+            return TYPE;
+        }
+    }
+
+    public static class StockUpdated extends ServiceEvent<Stock,UpdateStockHandler> {
+        public static Type<UpdateStockHandler> TYPE = new Type<UpdateStockHandler>();
+
+        public StockUpdated(Stock stock) {
+            super(stock);
+
+        }
+
+        @Override
+        protected void dispatch(UpdateStockHandler handler) {
+            handler.onStockUpdated(this);
+        }
+
+        @Override
+        public com.google.gwt.event.shared.GwtEvent.Type<UpdateStockHandler> getAssociatedType() {
+            return TYPE;
+        }
+    }
+    
+    public static class TradeCommitted extends ServiceEvent<Trade, ServiceEventHandler.AddTradeHandler> {
+        public static Type<ServiceEventHandler.AddTradeHandler> TYPE = new Type<ServiceEventHandler.AddTradeHandler>();
+
+        public TradeCommitted(Trade trade) {
+            super(trade);
+        }
+
+        @Override
+        protected void dispatch(ServiceEventHandler.AddTradeHandler handler) {
+
+            handler.onTradeCommitted(this);
+        }
+
+        @Override
+        public com.google.gwt.event.shared.GwtEvent.Type<ServiceEventHandler.AddTradeHandler> getAssociatedType() {
+            return TYPE;
+        }
+    }
+
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEventHandler.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEventHandler.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEventHandler.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEventHandler.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.event;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * The contract to handle {@link ServiceEvent service events}.
+ * 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public interface ServiceEventHandler {
+
+    public interface AddTradableHandler extends EventHandler {
+        public void onTradableAdded(ServiceEvent.TradableAdded event);
+    }
+    
+    public static interface AddTradeHandler extends EventHandler {
+        public void onTradeCommitted(ServiceEvent.TradeCommitted event);
+    }
+    
+    public static interface RemoveTradableHandler extends EventHandler {
+        public void onTradableRemoved(ServiceEvent.TradableRemoved event);
+    }
+    
+    public static interface UpdateStockHandler extends EventHandler {
+        public void onStockUpdated(ServiceEvent.StockUpdated event);
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/event/ServiceEventHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ErrorDialog.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ErrorDialog.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ErrorDialog.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ErrorDialog.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeItem;
+
+/**
+ * A singleton Error Dialog to show the main error message and optional stack traces.
+ * <br>
+ * CSS Style names
+ * <LI>errorDialog-caption:
+ * <LI>errorDialog-message:
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class ErrorDialog extends PopupPanel {
+    private FlexTable table;
+    private HTML header;
+    private Button close;
+    private Tree tree;
+    private static ErrorDialog _instance = new ErrorDialog();
+    private static final String STYLE_CAPTION = "errorDialog-caption";
+    private static final String STYLE_MESSAGE = "errorDialog-message";
+    
+    private ErrorDialog() {
+        super(false, true);
+        setAnimationEnabled(true);
+        setGlassEnabled(true);
+        setVisible(false);
+        
+        header = new HTML();
+        header.addStyleName(STYLE_CAPTION);
+        
+        close = new Button("x");
+        close.addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent event) {
+                hide();
+            }
+        });
+        tree = new Tree();
+        ScrollPanel scroll = new ScrollPanel();
+        scroll.setSize("600px", "200px");
+        scroll.add(tree);
+        DOM.setStyleAttribute(scroll.getElement(), "border", "1px");
+        
+        table = new FlexTable();
+        table.setWidget(0, 0, header);
+        table.setWidget(0, 1, close);
+        table.setWidget(1, 0, scroll);
+        table.getFlexCellFormatter().setColSpan(1, 0, 2);
+        table.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_RIGHT);
+        setWidget(table);
+   }
+    
+    public static void showError(Throwable t) {
+        _instance.populate(t);
+        _instance.center();
+    }
+    
+    private void populate(Throwable t) {
+        header.setHTML(t.getClass().getName());
+        tree.clear();
+        tree = addStackTrace(t);
+    }
+    
+    private Tree addStackTrace(Throwable t) {
+        TreeItem root = new TreeItem(t.getClass().getName());
+        root.addItem(createMessageLabel(t));
+        StackTraceElement[] traces = t.getStackTrace();
+        for (int i = 0; i < traces.length; i++) {
+            root.addItem(createStackTrace(traces[i]));
+        }
+        tree.addItem(root);
+        Throwable cause = t.getCause();
+        if (cause == null || cause == t) {
+            return tree;
+        }
+        return addStackTrace(cause);
+    }
+    
+    Label createMessageLabel(Throwable t) {
+        HTML label = new HTML(t.getMessage());
+        label.addStyleName(STYLE_MESSAGE);
+        return label;
+    }
+    
+    Label createStackTrace(StackTraceElement trace) {
+        HTML label = new HTML(trace.toString());
+        label.addStyleName(STYLE_MESSAGE);
+        return label;
+    }
+    
+}
\ No newline at end of file

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ErrorDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/FadeEffect.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/FadeEffect.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/FadeEffect.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/FadeEffect.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Fun stuff to fade-in, fade-out a changing label.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class FadeEffect extends Timer {
+    static final String OPACITY = "opacity";
+    final Element elem;
+    final Widget html;
+    double opacity = 0.0;
+    double delta = 0.01;
+    int sign = -1;
+
+    FadeEffect(Widget html, boolean appear) {
+        this.html = html;
+        elem = html.getElement();
+        sign = appear ? 1 : -1;
+        opacity = appear ? 0.0 : 1.0;
+    }
+
+    @Override
+    public void run() {
+        DOM.setStyleAttribute(elem, OPACITY, "" + opacity);
+        opacity = opacity + sign * delta;
+        if (ended()) {
+            cancel();
+        }
+    }
+    
+    boolean ended() {
+        if (sign == -1) {
+            return opacity <= 0.0;
+        } else {
+            return opacity >= 1.0;
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/FadeEffect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/GridCellRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/GridCellRenderer.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/GridCellRenderer.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/GridCellRenderer.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Protocol to render a Grid Cell.
+ *  
+ * @author Pinaki Poddar
+ *
+ * @param <T>
+ */
+public interface GridCellRenderer<T> {
+    /**
+     * Create an widget for the part of data this render is rendering.
+     * 
+     * @param data the entire data represented in this row.
+     * @return a widget such as a Label or HTML to represent a part of the data.
+     */
+    Widget render(T data);
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/GridCellRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/HelpLink.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/HelpLink.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/HelpLink.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/HelpLink.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Anchor;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Frame;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+/**
+ * An anchor that pops up a min-browser with some hopefully helpful text.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+public class HelpLink extends Anchor implements ClickHandler {
+    private final String url;
+    private static HelpWindow window; 
+   
+    public HelpLink(String url) {
+        super("Help", url, "Help");
+        this.url = url;
+        addClickHandler(this);
+        if (window == null) {
+            window = new HelpWindow();
+        }
+        addStyleName("help");
+    }
+    
+    @Override
+    public void onClick(ClickEvent event) {
+        window.showHelp(url);
+        event.preventDefault();
+    }
+    
+    
+    public class HelpWindow extends PopupPanel implements PopupPanel.PositionCallback {
+        private final Frame frame;
+        
+        
+        public HelpWindow() {
+            super(true);
+            setAnimationEnabled(true);
+            setAutoHideEnabled(true);
+            setModal(false);
+            
+            VerticalPanel panel = new VerticalPanel();
+            
+            frame = new Frame();
+            frame.setPixelSize(400, 300);
+            Button close = new Button("close");
+            close.addClickHandler(new ClickHandler() {
+                public void onClick(ClickEvent event) {
+                    hide();
+                }
+            });
+            panel.add(frame);
+            panel.add(close);
+            setWidget(panel);
+            setVisible(true);
+        }
+        
+        public void showHelp(String url) {
+            frame.setUrl(url);
+            super.setPopupPositionAndShow(this);
+        }
+        
+        public void setPosition(int offsetWidth, int offsetHeight) {
+               int left = Window.getClientWidth() - getWidget().getOffsetWidth() - 100;
+               int top  = 40;
+               setPopupPosition(left, top);
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/HelpLink.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/MessageBox.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/MessageBox.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/MessageBox.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/MessageBox.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.DockPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.PopupPanel;
+
+/**
+ * A non-modal, pop-up message box.
+ * <br>
+ * CSS Styles:
+ * <LI>messageBox 
+ * <LI>messageBox-content
+ * <LI>messageBox-caption 
+ * <LI>
+ * The 
+ * @author Pinaki Poddar
+ *
+ */
+public class MessageBox extends PopupPanel {
+    private static MessageBox _popup = new MessageBox();
+    
+    private final HTML header;
+    private final Label message;
+    private MessageBox() {
+        super(false, true);
+        setAnimationEnabled(true);
+        
+        DockPanel panel = new DockPanel();
+        panel.setStyleName("messageBox");
+        panel.setHorizontalAlignment(DockPanel.ALIGN_CENTER);
+
+        header = new HTML();
+        header.addStyleName("messageBox-caption");
+        
+        Button close = new Button("OK");
+        close.addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent event) {
+                hide();
+            }
+        });
+        close.setEnabled(true);
+        close.setFocus(true);
+        
+        message  = new Label();
+        message.addStyleName("messageBox-content");
+        
+        panel.add(header, DockPanel.NORTH);
+        panel.add(close, DockPanel.SOUTH);
+        panel.add(message, DockPanel.CENTER);
+        
+        setWidget(panel);
+    }
+    
+    public static void alert(String message) {
+        alert("Alert", message);
+    }
+    
+    public static void alert(String header, String message) {
+        _popup.header.setText(message);
+        _popup.message.setText(message);
+         _popup.center();
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/MessageBox.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ProgressMonitor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ProgressMonitor.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ProgressMonitor.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ProgressMonitor.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.PopupPanel;
+
+/**
+ * Fun stuff - a progress monitor.
+ * CSS Styles
+ * <LI>progressMonitor
+ * <LI>progressMonitor-caption
+ * @author Pinaki Poddar
+ *
+ */
+public class ProgressMonitor extends Timer {
+    static final String OPACITY = "opacity";
+    private final String highOpacity = "1.0";
+    private final String lowOpacity  = "0.2";
+    private volatile int current = 0;
+    private final FlexTable bar;
+    private final HTML header;
+    private final int N = 10;
+    private final  PopupPanel popup;
+    private final  static ProgressMonitor _instance = new ProgressMonitor();
+    
+    private ProgressMonitor() {
+        popup = new PopupPanel();
+        popup.addStyleName("progressMonitor");
+        
+        
+        header = new HTML();
+        bar = new FlexTable();
+        
+        bar.setCellSpacing(1);
+        bar.setWidget(0, 0, header);
+        header.addStyleName("progressMonitor-caption");
+        for (int i = 0; i < N; i++) {
+            Label box = new Label();
+            box.setSize("10px", "20px");
+            DOM.setStyleAttribute(box.getElement(), "backgroundColor", "black");
+            DOM.setStyleAttribute(box.getElement(), OPACITY, lowOpacity);
+            bar.setWidget(1, i, box);
+        }
+        bar.getFlexCellFormatter().setColSpan(0, 0, N);
+        
+        popup.add(bar);
+    }
+
+    public static void showProgress(String caption) {
+        _instance.header.setText(caption);
+        _instance.popup.center();
+        _instance.scheduleRepeating(10);
+        _instance.run();
+    }
+    
+    public static void stop() {
+        _instance.cancel();
+        _instance.popup.hide();
+    }
+    
+    @Override
+    public void run() {
+        Element elem = bar.getWidget(1, current).getElement();
+        DOM.setStyleAttribute(elem, OPACITY, lowOpacity);
+        current++;
+        current = current%N;
+        elem = bar.getWidget(1, current).getElement();
+        DOM.setStyleAttribute(elem, OPACITY, highOpacity);
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ProgressMonitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ScrollableTable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ScrollableTable.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ScrollableTable.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ScrollableTable.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.client.ui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A composite widget combines a data table, a table header, a scrollbar, 
+ * and a caption and a {@link HelpLink help anchor}. 
+ * <br>
+ * Each row of the data table displays an instance of type T. How the instance
+ * is displayed in controlled by a set of {@link GridCellRenderer renderers}
+ * attached to each column.
+ * <br>
+ * The styles used
+ * <LI>table-caption : for the caption
+ * <LI>column-header : for the column headers
+ * <LI>row-odd       : for odd numbered rows
+ * <LI>row-even      : for even numbered rows
+ * 
+ * 
+ * @author Pinaki Poddar
+ *
+ * @param <T> the type of data being displayed.
+ */
+public class ScrollableTable<T> extends Composite  {
+    private FlexTable _main;
+    private Grid _caption;
+    private FlexTable _header;
+    private ScrollPanel _scroll;
+    private List<GridCellRenderer<T>> _renderers;
+    private List<T> _rows;
+    private boolean _stripeRows;
+    
+    private static final String STYLE_CAPTION = "table-caption";
+    private static final String STYLE_HEADER  = "column-header";
+    private static final String STYLE_MAIN    = "table";
+    private static final String ROW_EVEN      = "row-even";
+    private static final String ROW_ODD       = "row-odd";
+    
+    /**
+     * Create a scrollable table with the given caption and given pixel dimension.
+     * The table will not be backed by a data  storage model.
+     * 
+     * @param caption of the table
+     * @param w width in pixel
+     * @param h height in pixel
+     */
+    public ScrollableTable(String caption, int w, int h) {
+        this(caption, w+"px", h+"px", false);
+    }
+    
+    /**
+     * Create a scrollable table with the given caption and given pixel dimension.
+     * The table will not be backed by a data  storage model.
+     * 
+     * @param caption of the table
+     * @param w width in pixel
+     * @param h height in pixel
+     * @param updatable whether the table data will be backed by a storage such
+     * that row can be updated rather than always inserted
+     */
+    public ScrollableTable(String caption, int w, int h, boolean updatable) {
+        this(caption, w+"px", h+"px", updatable);
+    }
+    
+    /**
+     * Create a scrollable table with the given caption and given dimension.
+     * 
+     * @param caption of the table
+     * @param w width in given unit
+     * @param h height in given unit
+     * @param updatable whether the table data will be backed by a storage such
+     * that row can be updated rather than always inserted
+     */
+    public ScrollableTable(String caption, String w, String h, boolean updatable) {
+        super();
+        _renderers = new ArrayList<GridCellRenderer<T>>();
+        
+        VerticalPanel vert = new VerticalPanel();
+        vert.setSpacing(0);
+        
+        _caption  = new Grid(1,2);
+        _caption.setWidth("100%");
+        setCaption(caption);
+        vert.add(_caption);
+        
+        
+        _header = new FlexTable();
+        _header.addStyleName(STYLE_HEADER);
+        _header.setWidth("100%");
+        
+        _main = new FlexTable();
+        _main.addStyleName(STYLE_MAIN);
+        
+        _main.setWidth("100%");
+        _main.setBorderWidth(0);
+        _scroll = new ScrollPanel();
+        _scroll.setSize(w, h);
+        _scroll.setAlwaysShowScrollBars(true);
+        _scroll.add(_main);
+        
+        
+        vert.add(_header);
+        vert.add(_scroll);
+        if (updatable) {
+            _rows = new ArrayList<T>();
+        }
+        
+        initWidget(vert);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public List<T> getModel() {
+        return _rows == null ? Collections.EMPTY_LIST : Collections.unmodifiableList(_rows);
+    }
+    
+    public void setCaption(String str) {
+        HTML caption = new HTML(str);
+        caption.addStyleName(STYLE_CAPTION);
+        _caption.setWidget(0, 0, caption);
+    }
+    
+    public void setSize(int w, int h) {
+        int dh = 0;
+        if (_caption != null) {
+           dh += _caption.getOffsetHeight();   
+        }
+        dh += _header.getOffsetHeight();
+        _scroll.setPixelSize(w, h-dh);
+    }
+    
+    
+    public void setRenderer(int column, GridCellRenderer<T> r) {
+        if (column > _renderers.size()) {
+            for (int i = _renderers.size(); i <= column; i++) {
+                _renderers.add(null);
+            }
+            _renderers.add(r);
+        } else if (column == _renderers.size()) {
+            _renderers.add(r);
+        } else {
+            _renderers.set(column, r);
+        }
+    }
+    
+    public void setColumnHeader(int column, String txt, String width) {
+        HTML header = new HTML(txt);
+        header.addStyleName(STYLE_HEADER);
+        _header.setWidget(0, column, header);
+        _main.getColumnFormatter().setWidth(column, width);
+    }
+    
+    public void setStripeRows(boolean stripe) {
+        _stripeRows = stripe;
+    }
+    
+    public boolean isStripeRows() {
+        return _stripeRows;
+    }
+     
+    public void insert(T data) {
+        setRow(_main.getRowCount(), data, null);
+    }
+    
+    public void remove(T data) {
+        int i = findRow(data);
+        if (i != -1) {
+            _main.removeRow(i);
+            _rows.remove(i);
+        }
+    }
+    
+    /**
+     * Update entire row.
+     */
+    public void update(T data, Integer[] columns) {
+        int i = findRow(data);
+        if (i != -1) {
+            setRow(i, data, columns);
+        } else {
+            insert(data);
+        }
+    }
+    
+    public void updateCell(int row, int column, Widget widget, boolean animate) {
+        if (animate) {
+            FadeEffect fadeOut = new FadeEffect(_main.getWidget(row, column), false);
+            fadeOut.scheduleRepeating(10);
+            DOM.setElementAttribute(widget.getElement(), "opacity", "0.0");
+            _main.setWidget(row, column, widget);
+            FadeEffect fadeIn = new FadeEffect(_main.getWidget(row, column), true);
+            fadeIn.scheduleRepeating(10);
+        } else {
+            _main.setWidget(row, column, widget);
+        }
+    }
+    
+    public int getRowCount() {
+        return _main.getRowCount();
+    }
+    
+    /**
+     * Sets the cells of an existing row.
+     * Calls each renderer. 
+     * @param row
+     * @param data
+     */
+    private void setRow(int row, T data, Integer[] columns) {
+        if (_rows != null) {
+            if (row < 0 || row >= _rows.size())
+                _rows.add(data);
+            else 
+                _rows.set(row, data);
+        }
+        for (int i = 0; i < _renderers.size(); i++) {
+            GridCellRenderer<T> r = _renderers.get(i);
+            if (r == null)
+                continue;
+            if (containsColumn(columns, i)) {
+                Widget widget = r.render(data);
+                if (widget != null)
+                    _main.setWidget(row, i, widget);
+            }
+        }
+        if (isStripeRows()) {
+            _main.getRowFormatter().setStylePrimaryName(row, row%2 == 0? ROW_EVEN : ROW_ODD);
+        }
+        _scroll.scrollToBottom();
+    }
+    
+    public int findRow(T data) {
+        
+        if (_rows == null || data == null)
+            return -1;
+        return _rows.indexOf(data);
+    }
+    
+    private boolean containsColumn(Integer[] columns, int i) {
+        if (columns == null)
+            return true;
+        for (int j = 0; j < columns.length; j++) {
+            if (columns[j] == i)
+                return true;
+        }
+        return false;
+    }
+    
+    public T get(int i) {
+        if (_rows == null || i < 0 || i >= _rows.size())
+            return null;
+        return _rows.get(i);
+    }
+    
+    public void scrollToBottom() {
+        _scroll.scrollToBottom();
+    }
+    
+    public void addHelp(final String url) {
+        if (_caption == null) {
+            return;
+        }
+        _caption.getColumnFormatter().setWidth(0, "95%");
+        HelpLink help = new HelpLink(url);
+        _caption.setWidget(0, 1, help);
+        _caption.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_RIGHT);
+    }
+    
+    
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/client/ui/ScrollableTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Ask.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Ask.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Ask.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Ask.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+
+/**
+ * An offer to sell a financial instrument.
+ * The only mutable state of an offer is its expiration.
+ * But that state is also mutable only once and is not reversible.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+
+@SuppressWarnings("serial")
+@Entity
+public class Ask  extends Tradable {
+    /**
+     * The trader who has made the offer.
+     * Must never be null.
+     */
+    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH},optional=false)
+    private Trader seller;
+    
+    /**
+     * A no-arg constructor to comply to both GWT compiler and OpenJPA 
+     * bytecode enhancer.
+     */
+    protected Ask() {
+        super();
+    }
+    
+    /**
+     * Real constructor populates the essential properties.
+     * 
+     * @param trader the trader who made this offer. Must not be null.
+     * @param stock the underlying instrument. Must not be null.
+     * @param price the offered price to sell. Must be positive.
+     * @param volume the number of instruments to sell. Must be positive.
+     */
+    public Ask(Trader trader, Stock stock, double price, int volume) {
+        super(stock, price, volume);
+        if (trader == null)
+            throw new NullPointerException("Can not create Ask with null trader");
+        this.seller = trader;
+    }
+
+    /**
+     * Gets the trader who made this offer to sell.
+     * 
+     * @return the trader who made this offer. Never null.
+     */
+    public Trader getSeller() {
+        return seller;
+    }
+    
+    public double getGain() {
+        return (getPrice() - getStock().getMarketPrice())*getVolume(); 
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Ask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Bid.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Bid.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Bid.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Bid.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+/**
+ * An offer to buy a financial instrument.
+ * The only mutable state of an offer is its expiration.
+ * But that state is also mutable only once and is not reversible.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+
+@SuppressWarnings("serial")
+@Entity
+public class Bid extends Tradable {
+    /**
+     * The trader who has made the offer.
+     * Must never be null.
+     */
+    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH},optional=false)
+    private Trader buyer;
+    
+    /**
+     * A no-arg constructor to comply to both GWT compiler and OpenJPA 
+     * bytecode enhancer.
+     */
+    protected Bid() {
+        super();
+    }
+    
+    /**
+     * Real constructor populates the essential properties.
+     * 
+     * @param trader the trader who made this offer. Must not be null.
+     * @param stock the underlying instrument. Must not be null.
+     * @param price the offered price to buy. Must be positive.
+     * @param volume the number of instruments to buy. Must be positive.
+     */
+    public Bid(Trader trader, Stock stock, double price, int volume) {
+        super(stock, price, volume);
+        if (trader == null)
+            throw new NullPointerException("Can not create Bid with null trader");
+        this.buyer = trader;
+    }
+    
+    /**
+     * Gets the trader who made this offer.
+     * 
+     * @return the trader who made this offer. Never null.
+     */
+    public Trader getBuyer() {
+        return buyer;
+    }   
+    
+    public double getGain() {
+        return (getStock().getMarketPrice() - getPrice())*getVolume(); 
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Bid.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/LogStatement.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/LogStatement.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/LogStatement.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/LogStatement.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+@SuppressWarnings("serial")
+public class LogStatement implements Serializable {
+    private String level;
+    private String context;
+    private String thread;
+    private String channel;
+    private String message;
+    
+    protected LogStatement() {
+        
+    }
+    
+    public LogStatement(String level, String context, String thread, String channel, String message) {
+        super();
+        this.level = level;
+        this.context = context;
+        this.thread = thread;
+        this.channel = channel;
+        this.message = message;
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    public String getThread() {
+        return thread;
+    }
+
+    public String getChannel() {
+        return channel;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+    
+    public String toString() {
+        return level + " [" + context + "] [" + thread + "] [" + channel + "] :" + message;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/LogStatement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Match.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Match.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Match.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Match.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+/**
+ * A pair of matching offer to {@linkplain Bid buy} and {@linkplain Ask sell}.
+ * This is <em>not</em> a persistent entity. But it is in the persistent domain 
+ * because it is often is the result of query.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class Match implements Serializable {
+    private Ask ask;
+    private Bid bid;
+    
+    /**
+     * A no-arg constructor to comply to GWT compiler.
+     */
+    protected Match() {
+    }
+    
+    /**
+     * Constructs a pair with matching offers.
+     * @param a the offer to sell. Must not be null.
+     * @param b the offer to buy. Must not be null.
+     */
+    public Match(Ask a, Bid b) {
+        if (a == null)
+            throw new NullPointerException("Can not create Match with null Ask");
+        if (b == null)
+            throw new NullPointerException("Can not create Match with null Bid");
+        if (a.getSeller().equals(b.getBuyer())) {
+            throw new NullPointerException("Can not create Match with same Trader " 
+                    + a.getSeller() + " for Ask and Bid");
+        }
+        if (a.getPrice() > b.getPrice()) {
+            throw new IllegalArgumentException("Ask price " + a.getPrice() + " is greater than "
+                    + " Bid price " + b.getPrice());
+        }
+        ask = a;
+        bid = b;
+    }
+    
+    /**
+     * Gets the matching offer to sell. 
+     * 
+     * @return the matching offer to sell. Never null. 
+     */
+    public Ask getAsk() {
+        return ask;
+    }
+    
+    /**
+     * Gets the matching offer to buy.
+     * 
+     * @return the matching offer to buy. Never null. 
+     */
+    public Bid getBid() {
+        return bid;
+    }
+    
+    
+    public String toString() {
+        return "Match ["+ ask + " and " + bid + "]";
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Match.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Sector.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Sector.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Sector.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Sector.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+/**
+ * Designates the business sector of a financial instrument.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+public enum Sector {
+    HEALTHCARE,
+    FINACE,
+    INFRASTRUCTURE
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Sector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Stock.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Stock.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Stock.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Stock.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * A stock is a typical financial instrument that is bought and sold by {@linkplain Trader}.
+ * A stock is mostly an immutable entity, except its price. 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@Entity
+public class Stock implements Serializable {
+    /**
+     * The primary identity of a Stock.
+     * The uniqueness of the primary keys are often warranted by the persistence provider.
+     * In this case, unique of a Stock symbol is ensured by an external agency.   
+     */
+    @Id
+    private String symbol;
+    
+    /**
+     * The name of the company represented by this financial instrument.
+     */
+    private String company;
+    
+    private Sector sector;
+    
+    @Column(precision=10,scale=2)
+    private double price;
+    
+    @Column(precision=10,scale=2)
+    private double lastPrice;
+    
+    /**
+     * A no-arg constructor to comply to both GWT compiler and OpenJPA 
+     * bytecode enhancer.
+     */
+    protected Stock() {
+        
+    }
+    
+    public Stock(String symbol, String company, Sector sector, double price) {
+        super();
+        this.symbol = symbol;
+        this.company = company;
+        this.sector = sector;
+        this.price  = price;
+        this.lastPrice = price;
+    }
+    
+    public String getSymbol() {
+        return symbol;
+    }
+    
+    public String getCompany() {
+        return company;
+    }
+    
+    public Sector getSector() {
+        return sector;
+    }
+    
+    public double getMarketPrice() {
+        return price;
+    }
+    
+    public void setMarketPrice(double newPrice) {
+        this.lastPrice = this.price;
+        this.price     = newPrice;
+    }
+    
+    public double getLastPrice() {
+        return lastPrice;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((symbol == null) ? 0 : symbol.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;
+        Stock other = (Stock) obj;
+        if (symbol == null) {
+            if (other.symbol != null)
+                return false;
+        } else if (!symbol.equals(other.symbol))
+            return false;
+        return true;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Stock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Tradable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Tradable.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Tradable.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Tradable.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.OneToOne;
+import javax.persistence.Version;
+
+/**
+ * An abstract root for domain objects in OpenTrader designates a {@link Stock financial instrument}
+ * that can be traded. An abstract state of a tradable entity is immutable by the application. 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+@MappedSuperclass
+public abstract class Tradable implements Serializable {
+    /**
+     * Primary identity of a traded entity.
+     * Its value is generated by the persistence provider.
+     * The application must not set or change this value.
+     * Hence no setter method is provided. 
+     */
+    @Id
+    @GeneratedValue
+    private Long id;
+    
+    /**
+     * The price at which the underlying instrument be traded.
+     * Must always be positive.
+     */
+    @Column(precision=10,scale=2)
+    private double price;
+    
+    
+    /**
+     * The volume or discreet number of underlying instrument be traded.
+     * Must always be positive.
+     */
+    private int volume;
+
+    /**
+     * The underlying instrument.
+     * Must never be null.
+     */
+    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH,CascadeType.REFRESH},optional=false)
+    private Stock stock;
+    
+    @OneToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=true, fetch=FetchType.LAZY) 
+    private Trade trade; 
+    
+   
+    /**
+     * A version identifier.
+     * Important (and almost mandatory) for any persistent entity to be part of
+     * simultaneous transaction. The persistence provider uses/updates the
+     * version to detect concurrent modification of an entity in simultaneous
+     * transaction.
+     */
+    @Version
+    private int version;
+    
+    /**
+     * A no-arg constructor to comply to both GWT compiler and OpenJPA 
+     * bytecode enhancer.
+     */
+    protected Tradable() {
+        
+    }
+    
+    /**
+     * Real constructor to be used by the concrete derivations.
+     * 
+     * @param stock the underlying instrument. Must not be null.
+     * @param price the price. Must be positive.
+     * @param volume the volume. Must be positive.
+     */
+    protected Tradable(Stock stock, double price, int volume) {
+        if (stock == null)
+            throw new IllegalArgumentException("Can not create Tradable with null stock");
+        if (price <= 0.0)
+            throw new IllegalArgumentException("Can not create Tradable with non-positive price " + price);
+        if (volume <= 0)
+            throw new IllegalArgumentException("Can not create Tradable with non-positive volume " + volume);
+        
+        this.stock  = stock;
+        this.price  = price;
+        this.volume = volume;
+    }
+    
+    /**
+     * Gets the identifier of this entity.
+     * 
+     * @return identifier generated by the persistence provider.
+     */
+    public long getId() {
+        return id;
+    }
+    
+    /**
+     * Gets the underlying instrument.
+     * 
+     * @return the underlying instrument. Never null.
+     */
+    public Stock getStock() {
+        return stock;
+    }
+
+    /**
+     * Gets the price at which the underlying instrument be traded.
+     * 
+     * @return the price of the underlying instrument for trading. Always greater than zero.
+     */
+    public double getPrice() {
+        return price;
+    }
+
+    /**
+     * Gets the volume of the underlying instrument be traded.
+     * 
+     * @return the volume of the underlying instrument for trading. Always greater than zero.
+     */
+    public int getVolume() {
+        return volume;
+    }
+    
+    public abstract double getGain();
+    
+    /**
+     * Affirms if this offer has expired.
+     */
+    public boolean isTraded() {
+        return trade != null;
+    }
+    
+    public void updateStock(Stock updated) {
+        if (this.stock.equals(updated)) {
+            this.stock = updated;
+        } else {
+            throw new IllegalArgumentException(this + " can not change Stock from " + this.stock 
+                    + " to " + updated);
+        }
+    }
+    
+    public void setTrade(Trade t) {
+        if (trade != null)
+            throw new IllegalStateException(this + " has already been traded");
+        this.trade = t;
+    }
+    
+    public Trade getTrade() {
+        if (trade == null)
+            throw new IllegalStateException(this + " is not yet traded");
+        return trade;
+    }
+
+    /**
+     * The version of the entity. Updated by the persistence provider.
+     * 
+     * @return the current version of this entity. 
+     */
+    public int getVersion() {
+        return version;
+    }
+    
+    /**
+     * It is important for persistence entity to overwrite the equals()
+     * method, preferably based only on its primary key attribute(s). 
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        return result;
+    }
+    /**
+     * It is important for persistence entity to overwrite the hashCode()
+     * method, preferably based only on its primary key attribute(s). 
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Tradable other = (Tradable) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        return true;
+    }
+    
+    public String toString() {
+        String type = this.getClass().getName();
+        return  type.substring(type.lastIndexOf('.'))+ ":" + id;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Tradable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trade.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trade.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trade.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trade.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@SuppressWarnings("serial")
+@Entity
+public class Trade implements Serializable {
+    /**
+     * Primary identity of a committed trade.
+     * Its value is generated by the persistence provider.
+     * The application must not set or change this value.
+     * Hence no setter method is provided. 
+     */
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    @Column(precision=10,scale=2)
+    private double price;
+    private int volume;
+
+//    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=false)
+//    private Stock stock;
+//    
+//    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=false)
+//    private Trader buyer;
+//    
+//    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=false)
+//    private Trader seller;
+    
+    @OneToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=false)
+    private Ask ask;
+    
+    @OneToOne(cascade={CascadeType.MERGE,CascadeType.DETACH}, optional=false)
+    private Bid bid;
+    
+    protected Trade() {
+        
+    }
+    
+    public Trade(Ask a, Bid b) {
+        if (a == null)
+            throw new NullPointerException("Can not create Trade with null Ask");
+        if (b == null)
+            throw new NullPointerException("Can not create Trade with null Bid");
+        if (a.getSeller() == null) 
+            throw new NullPointerException("Can not create Trade with null trader for Ask");
+        if (b.getBuyer() == null) 
+            throw new NullPointerException("Can not create Trade with null trader for Bid");
+        if (a.getSeller().equals(b.getBuyer()))
+            throw new IllegalArgumentException("Ask and Bid have same trader " + a.getSeller());
+        if (!a.getStock().equals(b.getStock())) {
+            throw new IllegalArgumentException("Stock (ask) " + a.getStock() 
+                    + " does not match Stock (bid) " + b.getStock());
+        }
+//        buyer  = b.getBuyer();
+//        seller = a.getSeller();
+//        stock  = a.getStock();
+        ask = a;
+        bid = b;
+        ask.setTrade(this);
+        bid.setTrade(this);
+        price  = Math.max(a.getPrice(), b.getPrice());
+        volume = Math.min(a.getVolume(), b.getVolume());
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public Trader getBuyer() {
+        return bid.getBuyer();
+    }
+
+    public Trader getSeller() {
+        return ask.getSeller();
+    }
+    
+    public Stock getStock() {
+        return ask.getStock();
+    }
+    
+    public double getPrice() {
+        return price;
+    }
+
+    public int getVolume() {
+        return volume;
+    }
+    
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.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;
+        Trade other = (Trade) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        return true;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trade.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trader.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trader.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trader.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trader.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.openjpa.trader.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import javax.persistence.Version;
+
+@SuppressWarnings("serial")
+@Entity
+@Table(name="TRADER",
+       uniqueConstraints= @UniqueConstraint(columnNames={"NAME"}))
+
+public class Trader implements Serializable {
+    @Id
+    private String name;
+    
+    @Version
+    private int version;
+    
+    protected Trader() {
+        super();
+    }
+    
+    public Trader(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public int getVersion() {
+        return version;
+    }
+    
+    public String toString() {
+        return name;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.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;
+        Trader other = (Trader) obj;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        return true;
+    }
+
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/Trader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/package.html
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/package.html?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/package.html (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/package.html Tue Aug 24 18:11:25 2010
@@ -0,0 +1,10 @@
+<HTML>
+<BODY>
+Persistent Domain Model for OpenTrader.
+
+The domain model is designed to be a operable in the client-side Java runtime environment (JRE) provided by 
+Google Web Toolkit (GWT). Because <A HREF="http://www.gwtapps.com/doc/html/jre.html">JRE Emulation Library GWT</A>
+allows a subset of standard Java library classes, these domain classes are defined to use only that subset so that 
+they can be translated by GWT Compiler.
+</BODY>
+</HTML>
\ No newline at end of file

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/domain/package.html
------------------------------------------------------------------------------
    svn:eol-style = native