You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/03/16 17:36:28 UTC

svn commit: r754936 [3/38] - in /incubator/pivot/tags/v1.0.1: ./ charts-test/ charts-test/src/ charts-test/src/pivot/ charts-test/src/pivot/charts/ charts-test/src/pivot/charts/test/ charts/ charts/lib/ charts/src/ charts/src/pivot/ charts/src/pivot/ch...

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/HighLowChartViewSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/HighLowChartViewSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/HighLowChartViewSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/HighLowChartViewSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.entity.ChartEntity;
+import org.jfree.chart.entity.XYItemEntity;
+
+import pivot.charts.ChartView;
+import pivot.charts.HighLowChartView;
+import pivot.collections.List;
+
+/**
+ * High/low chart view skin.
+ *
+ * @author gbrown
+ */
+public class HighLowChartViewSkin extends ChartViewSkin {
+    private boolean candlestick = false;
+
+    public ChartView.Element getElementAt(int x, int y) {
+        ChartView.Element element = null;
+
+        ChartEntity chartEntity = getChartEntityAt(x, y);
+        if (chartEntity instanceof XYItemEntity) {
+            XYItemEntity xyItemEntity = (XYItemEntity)chartEntity;
+            element = new ChartView.Element(xyItemEntity.getSeriesIndex(),
+                xyItemEntity.getItem());
+        }
+
+        return element;
+    }
+
+    @Override
+    protected JFreeChart createChart() {
+        HighLowChartView chartView = (HighLowChartView)getComponent();
+
+        String title = chartView.getTitle();
+        String horizontalAxisLabel = chartView.getHorizontalAxisLabel();
+        String verticalAxisLabel = chartView.getVerticalAxisLabel();
+        boolean showLegend = chartView.getShowLegend();
+
+        String seriesNameKey = chartView.getSeriesNameKey();
+        List<?> chartData = chartView.getChartData();
+
+        JFreeChart chart;
+        OHLCSeriesDataset dataset = new OHLCSeriesDataset(seriesNameKey, chartData);
+
+        if (candlestick) {
+            chart = ChartFactory.createCandlestickChart(title,
+                horizontalAxisLabel, verticalAxisLabel, dataset, showLegend);
+        } else {
+            chart = ChartFactory.createHighLowChart(title,
+                horizontalAxisLabel, verticalAxisLabel, dataset, showLegend);
+        }
+
+        return chart;
+    }
+
+    public boolean isCandlestick() {
+        return candlestick;
+    }
+
+    public void setCandlestick(boolean candlestick) {
+        this.candlestick = candlestick;
+        repaintComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/IntervalSeriesDataset.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/IntervalSeriesDataset.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/IntervalSeriesDataset.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/IntervalSeriesDataset.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import org.jfree.data.xy.IntervalXYDataset;
+
+import pivot.collections.Dictionary;
+import pivot.collections.List;
+
+/**
+ * Implementation of JFreeChart IntervalXYDataset.
+ *
+ * @author gbrown
+ */
+public class IntervalSeriesDataset extends XYSeriesDataset implements IntervalXYDataset {
+    public static final String WIDTH_KEY = "width";
+    public static final String HEIGHT_KEY = "height";
+
+    public IntervalSeriesDataset(String seriesNameKey, List<?> chartData) {
+        super(seriesNameKey, chartData);
+    }
+
+    public Number getStartX(int seriesIndex, int itemIndex) {
+        return getX(seriesIndex, itemIndex);
+    }
+
+    public double getStartXValue(int seriesIndex, int itemIndex) {
+        return getX(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getEndX(int seriesIndex, int itemIndex) {
+        return getXValue(seriesIndex, itemIndex) + getWidthValue(seriesIndex, itemIndex);
+    }
+
+    public double getEndXValue(int seriesIndex, int itemIndex) {
+        return getEndX(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getStartY(int seriesIndex, int itemIndex) {
+        return getY(seriesIndex, itemIndex);
+    }
+
+    public double getStartYValue(int seriesIndex, int itemIndex) {
+        return getY(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getEndY(int seriesIndex, int itemIndex) {
+        return getYValue(seriesIndex, itemIndex) + getWidthValue(seriesIndex, itemIndex);
+    }
+
+    public double getEndYValue(int seriesIndex, int itemIndex) {
+        return getEndY(seriesIndex, itemIndex).doubleValue();
+    }
+
+    protected double getWidthValue(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(WIDTH_KEY);
+        if (value == null) {
+            throw new NullPointerException(WIDTH_KEY + " is null.");
+        }
+
+        if (value instanceof String) {
+            value = Double.parseDouble((String)value);
+        }
+
+        Number width = (Number)value;
+        return width.doubleValue();
+    }
+
+    protected double getHeightValue(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(HEIGHT_KEY);
+        if (value == null) {
+            throw new NullPointerException(HEIGHT_KEY + " is null.");
+        }
+
+        if (value instanceof String) {
+            value = Double.parseDouble((String)value);
+        }
+
+        Number height = (Number)value;
+        return height.doubleValue();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/LineChartViewSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/LineChartViewSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/LineChartViewSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/LineChartViewSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.entity.CategoryItemEntity;
+import org.jfree.chart.entity.ChartEntity;
+import org.jfree.chart.entity.XYItemEntity;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.category.CategoryDataset;
+
+import pivot.charts.ChartView;
+import pivot.charts.LineChartView;
+import pivot.collections.List;
+
+/**
+ * Line chart view skin.
+ *
+ * @author gbrown
+ */
+public class LineChartViewSkin extends ChartViewSkin {
+    private boolean threeDimensional = false;
+
+    public ChartView.Element getElementAt(int x, int y) {
+        ChartView.Element element = null;
+
+        ChartEntity chartEntity = getChartEntityAt(x, y);
+
+        if (chartEntity instanceof CategoryItemEntity) {
+            CategoryItemEntity categoryItemEntity = (CategoryItemEntity)chartEntity;
+            CategoryDataset dataset = categoryItemEntity.getDataset();
+
+            String columnKey = (String)categoryItemEntity.getColumnKey();
+            int columnIndex = dataset.getColumnIndex(columnKey);
+
+            String rowKey = (String)categoryItemEntity.getRowKey();
+            int rowIndex = dataset.getRowIndex(rowKey);
+
+            element = new ChartView.Element(rowIndex, columnIndex);
+        } else if (chartEntity instanceof XYItemEntity) {
+            XYItemEntity xyItemEntity = (XYItemEntity)chartEntity;
+            element = new ChartView.Element(xyItemEntity.getSeriesIndex(),
+                xyItemEntity.getItem());
+        }
+
+        return element;
+    }
+
+    protected JFreeChart createChart() {
+        LineChartView chartView = (LineChartView)getComponent();
+
+        String title = chartView.getTitle();
+        String horizontalAxisLabel = chartView.getHorizontalAxisLabel();
+        String verticalAxisLabel = chartView.getVerticalAxisLabel();
+        boolean showLegend = chartView.getShowLegend();
+
+        String seriesNameKey = chartView.getSeriesNameKey();
+        List<?> chartData = chartView.getChartData();
+
+        JFreeChart chart;
+        ChartView.CategorySequence categories = chartView.getCategories();
+        if (categories.getLength() > 0) {
+            CategorySeriesDataset dataset = new CategorySeriesDataset(categories, seriesNameKey, chartData);
+
+            if (threeDimensional) {
+                chart = ChartFactory.createLineChart3D(title, horizontalAxisLabel, verticalAxisLabel,
+                    dataset, PlotOrientation.VERTICAL, showLegend, false, false);
+            } else {
+                chart = ChartFactory.createLineChart(title, horizontalAxisLabel, verticalAxisLabel,
+                    dataset, PlotOrientation.VERTICAL, showLegend, false, false);
+            }
+        } else {
+            chart = ChartFactory.createXYLineChart(title, horizontalAxisLabel, verticalAxisLabel,
+                new XYSeriesDataset(seriesNameKey, chartData),
+                PlotOrientation.VERTICAL, showLegend, false, false);
+        }
+
+        return chart;
+    }
+
+    public boolean isThreeDimensional() {
+        return threeDimensional;
+    }
+
+    public void setThreeDimensional(boolean threeDimensional) {
+        this.threeDimensional = threeDimensional;
+        repaintComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/OHLCSeriesDataset.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/OHLCSeriesDataset.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/OHLCSeriesDataset.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/OHLCSeriesDataset.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,146 @@
+package pivot.charts.skin;
+
+import java.util.Date;
+
+import org.jfree.data.xy.OHLCDataset;
+
+import pivot.collections.Dictionary;
+import pivot.collections.List;
+
+/**
+ * Implementation of JFreeChart OHLCDataset.
+ *
+ * @author gbrown
+ */
+public class OHLCSeriesDataset extends XYSeriesDataset implements OHLCDataset {
+    public static final String DATE_KEY = "date";
+    public static final String OPEN_KEY = "open";
+    public static final String HIGH_KEY = "high";
+    public static final String LOW_KEY = "low";
+    public static final String CLOSE_KEY = "close";
+    public static final String VOLUME_KEY = "volume";
+
+    public OHLCSeriesDataset(String seriesNameKey, List<?> chartData) {
+        super(seriesNameKey, chartData);
+    }
+
+    @Override
+    public Number getX(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(X_KEY);
+        if (value == null) {
+            value = itemDictionary.get(DATE_KEY);
+
+            if (value instanceof Date) {
+                value = ((Date)value).getTime();
+            }
+        }
+
+        if (value == null) {
+            throw new NullPointerException(X_KEY + " and " + DATE_KEY + " are null.");
+        }
+
+        return (Number)value;
+    }
+
+    @Override
+    public Number getY(int seriesIndex, int itemIndex) {
+        return getClose(seriesIndex, itemIndex);
+    }
+
+    public Number getOpen(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(OPEN_KEY);
+        if (value == null) {
+            value = Double.NaN;
+        } else {
+            if (value instanceof String) {
+                value = Double.parseDouble((String)value);
+            }
+        }
+
+        return (Number)value;
+    }
+
+    public double getOpenValue(int seriesIndex, int itemIndex) {
+        return getOpen(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getHigh(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(HIGH_KEY);
+        if (value == null) {
+            value = Double.NaN;
+        } else {
+            if (value instanceof String) {
+                value = Double.parseDouble((String)value);
+            }
+        }
+
+        return (Number)value;
+    }
+
+    public double getHighValue(int seriesIndex, int itemIndex) {
+        return getHigh(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getLow(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(LOW_KEY);
+        if (value == null) {
+            value = Double.NaN;
+        } else {
+            if (value instanceof String) {
+                value = Double.parseDouble((String)value);
+            }
+        }
+
+        return (Number)value;
+    }
+
+    public double getLowValue(int seriesIndex, int itemIndex) {
+        return getLow(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getClose(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(CLOSE_KEY);
+        if (value == null) {
+            value = Double.NaN;
+        } else {
+            if (value instanceof String) {
+                value = Double.parseDouble((String)value);
+            }
+        }
+
+        return (Number)value;
+    }
+
+    public double getCloseValue(int seriesIndex, int itemIndex) {
+        return getClose(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getVolume(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(VOLUME_KEY);
+        if (value == null) {
+            value = Double.NaN;
+        } else {
+            if (value instanceof String) {
+                value = Double.parseDouble((String)value);
+            }
+        }
+
+        return (Number)value;
+    }
+
+    public double getVolumeValue(int seriesIndex, int itemIndex) {
+        return getVolume(seriesIndex, itemIndex).doubleValue();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieChartViewSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieChartViewSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieChartViewSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieChartViewSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.entity.ChartEntity;
+import org.jfree.chart.entity.PieSectionEntity;
+import org.jfree.chart.plot.PiePlot;
+import org.jfree.chart.plot.PiePlot3D;
+import org.jfree.util.TableOrder;
+
+import pivot.charts.PieChartView;
+import pivot.charts.ChartView;
+import pivot.collections.HashMap;
+import pivot.collections.List;
+import pivot.collections.Map;
+
+/**
+ * Pie chart view skin.
+ *
+ * @author gbrown
+ */
+public class PieChartViewSkin extends ChartViewSkin {
+    private Map<String, Number> explodePercentages = new HashMap<String, Number>();
+
+    private boolean threeDimensional = false;
+    private boolean darkerSides = false;
+    private double depthFactor = 0.10d;
+
+    public ChartView.Element getElementAt(int x, int y) {
+        ChartView.Element element = null;
+
+        ChartEntity chartEntity = getChartEntityAt(x, y);
+        if (chartEntity instanceof PieSectionEntity) {
+            PieSectionEntity pieSectionEntity = (PieSectionEntity)chartEntity;
+            int sectionIndex = pieSectionEntity.getSectionIndex();
+            int seriesIndex = pieSectionEntity.getPieIndex();
+
+            element = new ChartView.Element(seriesIndex, sectionIndex);
+        }
+
+        return element;
+    }
+
+    protected JFreeChart createChart() {
+        PieChartView chartView = (PieChartView)getComponent();
+
+        String title = chartView.getTitle();
+        boolean showLegend = chartView.getShowLegend();
+
+        ChartView.CategorySequence categories = chartView.getCategories();
+        String seriesNameKey = chartView.getSeriesNameKey();
+        List<?> chartData = chartView.getChartData();
+
+
+        JFreeChart chart;
+        if (threeDimensional) {
+            if (chartData.getLength() > 1) {
+                CategorySeriesDataset dataset = new CategorySeriesDataset(categories,
+                    seriesNameKey, chartData);
+
+                chart = ChartFactory.createMultiplePieChart3D(title, dataset, TableOrder.BY_ROW,
+                    showLegend, false, false);
+            } else {
+                PieSeriesDataset dataset = new PieSeriesDataset(categories, chartData.get(0));
+                chart = ChartFactory.createPieChart3D(title, dataset, showLegend, false, false);
+
+                PiePlot3D plot = (PiePlot3D)chart.getPlot();
+                plot.setDarkerSides(darkerSides);
+                plot.setDepthFactor(depthFactor);
+            }
+        } else {
+            if (chartData.getLength() > 1) {
+                CategorySeriesDataset dataset = new CategorySeriesDataset(categories,
+                    seriesNameKey, chartData);
+
+                chart = ChartFactory.createMultiplePieChart(title, dataset, TableOrder.BY_ROW,
+                    showLegend, false, false);
+            } else {
+                PieSeriesDataset dataset = new PieSeriesDataset(categories, chartData.get(0));
+                chart = ChartFactory.createPieChart(title, dataset, showLegend, false, false);
+
+                HashMap<String, String> categoryLabels = new HashMap<String, String>();
+                for (int i = 0, n = categories.getLength(); i < n; i++) {
+                    ChartView.Category category = categories.get(i);
+                    categoryLabels.put(category.getKey(), category.getLabel());
+                }
+
+                PiePlot plot = (PiePlot)chart.getPlot();
+                for (String categoryKey : explodePercentages) {
+                    plot.setExplodePercent(categoryLabels.get(categoryKey),
+                        explodePercentages.get(categoryKey).doubleValue());
+                }
+            }
+        }
+
+        return chart;
+    }
+
+    public boolean isThreeDimensional() {
+        return threeDimensional;
+    }
+
+    public void setThreeDimensional(boolean threeDimensional) {
+        this.threeDimensional = threeDimensional;
+        repaintComponent();
+    }
+
+    public Map<String, Number> getExplodePercentages() {
+        return explodePercentages;
+    }
+
+    public void setExplodePercentages(Map<String, Number> explodePercentages) {
+        this.explodePercentages = explodePercentages;
+        repaintComponent();
+    }
+
+    public boolean getDarkerSides() {
+        return darkerSides;
+    }
+
+    public void setDarkerSides(boolean darkerSides) {
+        this.darkerSides = darkerSides;
+        repaintComponent();
+    }
+
+    public double getDepthFactor() {
+        return depthFactor;
+    }
+
+    public void setDepthFactor(double depthFactor) {
+        if (depthFactor < 0) {
+            throw new IllegalArgumentException("depthFactor is negative.");
+        }
+
+        this.depthFactor = depthFactor;
+        repaintComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieSeriesDataset.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieSeriesDataset.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieSeriesDataset.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/PieSeriesDataset.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import java.util.List;
+
+import org.jfree.data.general.DatasetChangeListener;
+import org.jfree.data.general.DatasetGroup;
+import org.jfree.data.general.PieDataset;
+
+import pivot.beans.BeanDictionary;
+import pivot.charts.ChartView;
+import pivot.collections.Dictionary;
+
+/**
+ * Implementation of JFreeChart PieDataset.
+ *
+ * @author gbrown
+ */
+@SuppressWarnings("unchecked")
+public class PieSeriesDataset implements PieDataset {
+    private ChartView.CategorySequence categories;
+    private Object series;
+
+    private DatasetGroup datasetGroup = null;
+
+    public PieSeriesDataset(ChartView.CategorySequence categories, Object series) {
+        if (categories == null) {
+            throw new IllegalArgumentException("categories is null.");
+        }
+
+        if (series == null) {
+            throw new IllegalArgumentException("series is null.");
+        }
+
+        this.categories = categories;
+        this.series = series;
+    }
+
+    public DatasetGroup getGroup() {
+        return datasetGroup;
+    }
+
+    public void setGroup(DatasetGroup datasetGroup) {
+        this.datasetGroup = datasetGroup;
+    }
+
+    public int getItemCount() {
+        return categories.getLength();
+    }
+
+    public int getIndex(Comparable categoryLabel) {
+        if (categoryLabel == null) {
+            throw new IllegalArgumentException("categoryLabel is null.");
+        }
+
+        int index = -1;
+        for (int i = 0, n = categories.getLength(); i < n && index == -1; i++) {
+            ChartView.Category category = categories.get(i);
+
+            if (categoryLabel.compareTo(category.getLabel()) == 0) {
+                index = i;
+            }
+        }
+
+        return index;
+    }
+
+    public Comparable getKey(int categoryIndex) {
+        if (categoryIndex < 0
+            || categoryIndex > categories.getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        return categories.get(categoryIndex).getLabel();
+    }
+
+    public List getKeys() {
+        java.util.ArrayList columnKeys = new java.util.ArrayList(categories.getLength());
+        for (int i = 0, n = categories.getLength(); i < n; i++) {
+            columnKeys.add(categories.get(i).getLabel());
+        }
+
+        return columnKeys;
+    }
+
+    public Number getValue(int categoryIndex) {
+        if (categoryIndex < 0
+            || categoryIndex > categories.getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        ChartView.Category category = categories.get(categoryIndex);
+        String categoryKey = category.getKey();
+
+        Dictionary<String, ?> seriesDictionary;
+        if (series instanceof Dictionary<?, ?>) {
+            seriesDictionary = (Dictionary<String, ?>)series;
+        } else {
+            seriesDictionary = new BeanDictionary(series);
+        }
+
+        Object value = seriesDictionary.get(categoryKey);
+        if (value instanceof String) {
+            value = Double.parseDouble((String)value);
+        }
+
+        return (Number)value;
+    }
+
+    public Number getValue(Comparable categoryLabel) {
+        return getValue(getIndex(categoryLabel));
+    }
+
+    public void addChangeListener(DatasetChangeListener listener) {
+        // No-op
+    }
+
+    public void removeChangeListener(DatasetChangeListener listener) {
+        // No-op
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/XYSeriesDataset.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/XYSeriesDataset.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/XYSeriesDataset.java (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/XYSeriesDataset.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.charts.skin;
+
+import org.jfree.data.DomainOrder;
+import org.jfree.data.general.DatasetChangeListener;
+import org.jfree.data.general.DatasetGroup;
+import org.jfree.data.xy.XYDataset;
+
+import pivot.beans.BeanDictionary;
+import pivot.collections.Dictionary;
+import pivot.collections.List;
+
+/**
+ * Implementation of JFreeChart XYDataset.
+ *
+ * @author gbrown
+ */
+@SuppressWarnings("unchecked")
+public class XYSeriesDataset implements XYDataset {
+    private String seriesNameKey;
+    private List<?> chartData;
+
+    private DatasetGroup datasetGroup = null;
+
+    public static final String X_KEY = "x";
+    public static final String Y_KEY = "y";
+
+    public XYSeriesDataset(String seriesNameKey, List<?> chartData) {
+        if (seriesNameKey == null) {
+            throw new IllegalArgumentException("seriesNameKey is null.");
+        }
+
+        if (chartData == null) {
+            throw new IllegalArgumentException("chartData is null.");
+        }
+
+        this.seriesNameKey = seriesNameKey;
+        this.chartData = chartData;
+    }
+
+    public DatasetGroup getGroup() {
+        return datasetGroup;
+    }
+
+    public void setGroup(DatasetGroup datasetGroup) {
+        this.datasetGroup = datasetGroup;
+    }
+
+    public int getSeriesCount() {
+        return chartData.getLength();
+    }
+
+    public Comparable getSeriesKey(int seriesIndex) {
+        Dictionary<String, ?> seriesDictionary = getSeriesDictionary(seriesIndex);
+        return (String)seriesDictionary.get(seriesNameKey);
+    }
+
+    public int indexOf(Comparable seriesName) {
+        if (seriesName == null) {
+            throw new IllegalArgumentException("seriesName is null.");
+        }
+
+        int index = -1;
+        for (int i = 0, n = chartData.getLength(); i < n && index == -1; i++) {
+            Dictionary<String, ?> seriesDictionary = getSeriesDictionary(i);
+
+            if (seriesName.compareTo(seriesDictionary.get(seriesNameKey)) == 0) {
+                index = i;
+            }
+        }
+
+        return index;
+    }
+
+    public DomainOrder getDomainOrder() {
+        return DomainOrder.NONE;
+    }
+
+    public int getItemCount(int seriesIndex) {
+        List<?> series = getSeries(seriesIndex);
+        return series.getLength();
+    }
+
+    public Number getX(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(X_KEY);
+        if (value == null) {
+            throw new NullPointerException(X_KEY + " is null.");
+        }
+
+        if (value instanceof String) {
+            value = Double.parseDouble((String)value);
+        }
+
+        return (Number)value;
+    }
+
+    public double getXValue(int seriesIndex, int itemIndex) {
+        return getX(seriesIndex, itemIndex).doubleValue();
+    }
+
+    public Number getY(int seriesIndex, int itemIndex) {
+        Dictionary<String, ?> itemDictionary = getItemDictionary(seriesIndex, itemIndex);
+
+        Object value = itemDictionary.get(Y_KEY);
+        if (value == null) {
+            throw new NullPointerException(Y_KEY + " is null.");
+        }
+
+        if (value instanceof String) {
+            value = Double.parseDouble((String)value);
+        }
+
+        return (Number)value;
+    }
+
+    public double getYValue(int seriesIndex, int itemIndex) {
+        return getY(seriesIndex, itemIndex).doubleValue();
+    }
+
+    private List<?> getSeries(int seriesIndex) {
+        if (seriesIndex < 0
+            || seriesIndex > chartData.getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        List<?> series = (List<?>)chartData.get(seriesIndex);
+        return series;
+    }
+
+    protected Dictionary<String, ?> getSeriesDictionary(int seriesIndex) {
+        List<?> series = getSeries(seriesIndex);
+
+        Dictionary<String, ?> seriesDictionary;
+        if (series instanceof Dictionary<?, ?>) {
+            seriesDictionary = (Dictionary<String, ?>)series;
+        } else {
+            seriesDictionary = new BeanDictionary(series);
+        }
+
+        return seriesDictionary;
+    }
+
+    protected Dictionary<String, ?> getItemDictionary(int seriesIndex, int itemIndex) {
+        List<?> series = getSeries(seriesIndex);
+
+        if (itemIndex < 0
+            || itemIndex > series.getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        Object item = series.get(itemIndex);
+
+        Dictionary<String, ?> itemDictionary;
+        if (item instanceof Dictionary<?, ?>) {
+            itemDictionary = (Dictionary<String, ?>)item;
+        } else {
+            itemDictionary = new BeanDictionary(item);
+        }
+
+        return itemDictionary;
+    }
+
+    public void addChangeListener(DatasetChangeListener listener) {
+        // No-op
+    }
+
+    public void removeChangeListener(DatasetChangeListener listener) {
+        // No-op
+    }
+}

Added: incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/package.html?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/package.html (added)
+++ incubator/pivot/tags/v1.0.1/charts/src/pivot/charts/skin/package.html Mon Mar 16 16:36:10 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains skin classes for charting components.</p>
+</body>
+</html>

Added: incubator/pivot/tags/v1.0.1/core-test/.classpath
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/.classpath?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/.classpath (added)
+++ incubator/pivot/tags/v1.0.1/core-test/.classpath Mon Mar 16 16:36:10 2009
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/core"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: incubator/pivot/tags/v1.0.1/core-test/.project
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/.project?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/.project (added)
+++ incubator/pivot/tags/v1.0.1/core-test/.project Mon Mar 16 16:36:10 2009
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>core-test</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/BinarySerializerTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/BinarySerializerTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/BinarySerializerTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/BinarySerializerTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.core.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import pivot.serialization.Serializer;
+import pivot.serialization.BinarySerializer;
+
+public class BinarySerializerTest {
+
+    public static void main(String[] args) {
+        Serializer serializer = new BinarySerializer();
+
+        Object[] testData = {
+            "Hello World",
+            123.456,
+            true
+        };
+
+        ByteArrayOutputStream outputStream = null;
+        try {
+            try {
+                outputStream = new ByteArrayOutputStream();
+                serializer.writeObject(testData, outputStream);
+            } finally {
+                outputStream.close();
+            }
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+
+        ByteArrayInputStream inputStream = null;
+        try {
+            try {
+                inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+                testData = (Object[])serializer.readObject(inputStream);
+
+                for (int i = 0, n = testData.length; i < n; i++) {
+                    System.out.println("[" + i + "] " + testData[i]);
+                }
+            } finally {
+                inputStream.close();
+            }
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/CSVSerializerTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/CSVSerializerTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/CSVSerializerTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/CSVSerializerTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.core.test;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import pivot.serialization.CSVSerializer;
+
+public class CSVSerializerTest {
+    public static String[] testStrings = {
+        "\"Y\"\"HO,O\",26.11,-0.33,X",
+        "0,1,2,3\nQ,5,6,7\n8,9,10,11",
+        "a,b,c,d",
+        "hello,world",
+        "2,4,6,8,10"
+    };
+
+    public static void main(String[] args) {
+        CSVSerializer csvSerializer = new CSVSerializer();
+        csvSerializer.getKeys().add("A");
+        csvSerializer.getKeys().add("B");
+        csvSerializer.getKeys().add("C");
+        csvSerializer.getKeys().add("D");
+
+        for (int i = 0, n = testStrings.length; i < n; i++) {
+            try {
+                System.out.println("Input: " + testStrings[i]);
+                Object object = csvSerializer.readObject(new StringReader(testStrings[i]));
+
+                StringWriter writer = new StringWriter();
+                csvSerializer.writeObject(object, writer);
+                System.out.println("Output: " + writer);
+            } catch(Exception exception) {
+                System.out.println(exception);
+            }
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/JSONSerializerTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/JSONSerializerTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/JSONSerializerTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/JSONSerializerTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.core.test;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import pivot.collections.HashMap;
+import pivot.collections.List;
+import pivot.collections.Map;
+import pivot.serialization.JSONSerializer;
+
+public class JSONSerializerTest {
+    public static String[] testStrings = {
+        "  null",
+        "\"Hello\\\" World\"",
+        "'Hello\\\' \"World'",
+        "\"ABCD",
+        " 10",
+        "+10",
+        " -10",
+        "10.1",
+        "+10.1",
+        "-1s0.1",
+        "true",
+        "false",
+        " [  0, 1, 2, [3, 4]",
+        " [ \"A\", \"B\", \t\"C\", [\t0, 1, 2, 'abc', true]]",
+        "['A', 'B', 'C']",
+        "{   }",
+        "{null: 'foo'}",
+        "{: 'foo'}",
+        "{\"\": \"foo\"}",
+        "{ my0: 'ABCD\"ABCD' , 'my' : '\"My \\ example 3\"', null: null}",
+        "{a:null}",
+        "{a:''}",
+        "{a:1, b:2",
+        "{\"1a\" : 0, bc : 'hello', n:-100.56, c:true, d:{e:10, f:20}, g:{aa:10, bb:20, cc:30}, m:[1,2, 4]}",
+        "{\"a#b\" : '#ff'}"
+    };
+
+    public static void main(String[] args) {
+        test0();
+        test1();
+        // test2();
+    }
+
+    public static void test0() {
+        HashMap<String, Object> a = new HashMap<String, Object>();
+        a.put("b", 100);
+
+        HashMap<String, Object> c = new HashMap<String, Object>();
+        c.put("d", "Hello World");
+        a.put("c", c);
+
+        StringWriter writer = new StringWriter();
+        JSONSerializer jsonSerializer = new JSONSerializer();
+        try {
+            jsonSerializer.writeObject(a, writer);
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+
+        System.out.println("Output: " + writer);
+    }
+
+    public static void test1() {
+        JSONSerializer jsonSerializer = new JSONSerializer();
+
+        for (int i = 0, n = testStrings.length; i < n; i++) {
+            try {
+                System.out.println("Input: " + testStrings[i]);
+                Object object = jsonSerializer.readObject(new StringReader(testStrings[i]));
+
+                StringWriter writer = new StringWriter();
+                jsonSerializer.writeObject(object, writer);
+
+                System.out.println("Output: " + writer);
+            } catch(Exception exception) {
+                System.out.println(exception);
+            }
+        }
+
+        int i = Integer.MAX_VALUE;
+        long l1 = (long)i + 1;
+        long l2 = Long.MAX_VALUE;
+        float f = Float.MAX_VALUE;
+        double d1 = (double)f + 1;
+        double d2 = Double.MAX_VALUE;
+        String listString = "[" + i + ", " + l1 + ", " + l2 + ", "
+            + f + ", " + d1 + ", " + d2 + "]";
+        List<?> list = JSONSerializer.parseList(listString);
+        for (Object item : list) {
+            System.out.println(item);
+        }
+
+        Map<String, ?> map = JSONSerializer.parseMap("{a:100, b:200, c:300}");
+        for (String key : map) {
+            System.out.println(key + ":" + map.get(key));
+        }
+    }
+
+    public static void test2() {
+        testMap("{a: {b: [{cd:'hello'}, {c:'world'}]}}", "a.b[0].cd");
+        testMap("{a: {b: [{c:'hello'}, {c:'world'}]}}", "['a'].b[0].c");
+        testMap("{a: {b: [{c:'hello'}, {c:'world'}]}}", "a[\"b\"][0]['c']");
+        testMap("{a: {b: [{c:'hello'}, {c:'world'}]}}", "a.");
+        testMap("{a: {b: [{c:'hello', d:[0, 1, 2, 3, 4]}, {c:'world'}]}}", "a.b[0].d[2]");
+        testMap("{a: {b: [{c:'hello', d:[0, 1, 2, 3, 4]}, {c:'world'}]}}", "a.....");
+        testMap("{abc: {def: [{ghi:'hello', d:[0, 1, 2, 3, 4]}, {c:'world'}]}}", "abc.def[0].ghi");
+
+        testList("[[0, 1, 2], [3, 4, 5]]", "[1]");
+        testList("[[0, 1, 2], [3, 4, 5]]", "[1][0]");
+        testList("[[0, 1, 2], [3, 4, 5]]", "[1][0].c");
+        testList("[[0, 1, 2], [3, 4, 5]]", "[1][]");
+        testList("[[0, 1, 2], [3, 4, 5]]", "[1][0][0]");
+    }
+
+    private static void testList(String list, String path) {
+        JSONSerializer jsonSerializer = new JSONSerializer();
+
+        try {
+            jsonSerializer.writeObject(JSONSerializer.getValue(JSONSerializer.parseList(list), path),
+                System.out);
+            System.out.println();
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+    }
+
+    private static void testMap(String map, String path) {
+        JSONSerializer jsonSerializer = new JSONSerializer();
+
+        try {
+            jsonSerializer.writeObject(JSONSerializer.getValue(JSONSerializer.parseMap(map), path),
+                System.out);
+            System.out.println();
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/PropertiesSerializerTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/PropertiesSerializerTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/PropertiesSerializerTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/PropertiesSerializerTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.core.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import pivot.collections.HashMap;
+import pivot.collections.Map;
+import pivot.serialization.PropertiesSerializer;
+import pivot.serialization.Serializer;
+
+public class PropertiesSerializerTest
+{
+    @SuppressWarnings("unchecked")
+    public static void main(String[] args) {
+        Serializer serializer = new PropertiesSerializer();
+
+        Map<String, Object> testMap = new HashMap<String, Object>();
+        testMap.put("hello",   "Hello World");
+        testMap.put("number",  123.456);
+        testMap.put("boolean", true);
+        testMap.put("i18n",    "€ & אטלעש");  // test some chars to encode ...
+        testMap.put("object",  new Object());
+
+        ByteArrayOutputStream outputStream = null;
+        try {
+            try {
+                outputStream = new ByteArrayOutputStream();
+                serializer.writeObject(testMap, outputStream);
+            } finally {
+                outputStream.close();
+
+                String dump = new String(outputStream.toByteArray());
+                System.out.println("Succesfully Written");
+                System.out.println(dump);
+            }
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+
+        ByteArrayInputStream inputStream = null;
+        Map<String, Object> readData = null;
+        try {
+            try {
+                inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+                readData = (Map<String, Object>) serializer.readObject(inputStream);
+
+                System.out.println("Succesfully Read");
+                for (String key : readData) {
+                    System.out.println(key + "=" + readData.get(key));
+                }
+            } finally {
+                inputStream.close();
+            }
+        } catch(Exception exception) {
+            System.out.println(exception);
+        }
+    }
+
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/ResourcesTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/ResourcesTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/ResourcesTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/ResourcesTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,134 @@
+package pivot.core.test;
+
+import java.util.MissingResourceException;
+
+import junit.framework.TestCase;
+import pivot.collections.List;
+import pivot.collections.Map;
+import pivot.serialization.SerializationException;
+import pivot.util.Resources;
+
+public class ResourcesTest extends TestCase {
+
+    public void testReadDefaultLocale() throws Exception {
+
+        Resources res = new Resources("resources.test1");
+        assertResources(res, "SGML", "Standard Generalized Markup Language");
+    }
+
+    /**
+     * The resource overrides the term for the country.
+     *
+     * @throws Exception
+     */
+    public void testRead_GB_Locale() throws Exception {
+        Resources res = new Resources("resources.test2");
+        assertResources(res, "SGML",
+                "How Do, Youth, Standard Generalized Markup Language");
+
+    }
+
+    /**
+     * The resource overrides the term for the country and the acronym for the
+     * language.
+     *
+     * @throws Exception
+     */
+    public void testRead_GB_en_Locale() throws Exception {
+        Resources res = new Resources("resources.test3");
+        assertResources(res, "XSGML",
+                "How Do, Youth, Standard Generalized Markup Language");
+
+    }
+
+    /**
+     * The resource overrides the term and the acronym for the country.
+     *
+     * @throws Exception
+     */
+    public void testRead_GB_en_LocaleExtraOverride() throws Exception {
+        Resources res = new Resources("resources.test6");
+        assertResources(res, "XSGML",
+                "eXtra Standard Generalized Markup Language");
+
+    }
+
+    public void testSerialisationException() throws Exception {
+
+        try {
+            new Resources("resources.test4");
+            fail("Expected SerialisationException");
+        } catch (SerializationException e) {
+        }
+
+    }
+
+    public void testMissingResource() throws Exception {
+
+        // resource doesn't exist...
+        try {
+            new Resources("resources.test5");
+            fail("Expected IllegalArgumentException");
+        } catch (MissingResourceException e) {
+        }
+
+    }
+
+    public void testNullLocale() throws Exception {
+        // resource exists, but locale is null
+        try {
+            new Resources("resources.test1");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void testNullBaseName() throws Exception {
+        try {
+            new Resources(null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void assertResources(Resources res, String acronym,
+            String term) {
+        assertTrue(res.containsKey("glossary"));
+
+        Map<String, Object> glossary = (Map<String, Object>) res
+                .get("glossary");
+        assertNotNull(glossary);
+        assertTrue(glossary.containsKey("GlossDiv"));
+
+        Map<String, Object> glossDiv = (Map<String, Object>) glossary
+                .get("GlossDiv");
+        assertNotNull(glossDiv);
+
+        assertEquals("S", glossDiv.get("title"));
+
+        assertTrue(glossDiv.containsKey("GlossList"));
+        Map<String, Object> glossList = (Map<String, Object>) glossDiv
+                .get("GlossList");
+        assertNotNull(glossList);
+
+        assertTrue(glossList.containsKey("GlossEntry"));
+        Map<String, Object> glossEntry = (Map<String, Object>) glossList
+                .get("GlossEntry");
+        assertNotNull(glossEntry);
+
+        assertEquals(acronym, glossEntry.get("Acronym"));
+        assertEquals(term, glossEntry.get("GlossTerm"));
+
+        assertTrue(glossEntry.containsKey("GlossDef"));
+        Map<String, Object> glossDef = (Map<String, Object>) glossEntry
+                .get("GlossDef");
+        assertNotNull(glossDef);
+
+        assertTrue(glossDef.containsKey("GlossSeeAlso"));
+        List<String> list = (List<String>) glossDef.get("GlossSeeAlso");
+        assertNotNull(list);
+        assertEquals(2, list.getLength());
+    }
+
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/TaskTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/TaskTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/TaskTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/TaskTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,101 @@
+package pivot.core.test;
+
+import pivot.util.concurrent.Task;
+import pivot.util.concurrent.TaskGroup;
+import pivot.util.concurrent.TaskListener;
+import pivot.util.concurrent.TaskSequence;
+
+public class TaskTest {
+    public static class SleepTask extends Task<Void> {
+        private long timeout = 0;
+
+        public SleepTask(long timeout) {
+            this.timeout = timeout;
+        }
+
+        @Override
+        public Void execute() {
+            System.out.println("Starting task " + this + "...");
+
+            try {
+                Thread.sleep(timeout);
+            } catch (InterruptedException exception) {
+                System.out.println(exception);
+            }
+
+            System.out.println("...done");
+
+            return null;
+        }
+
+        @Override
+        public String toString() {
+            return Long.toString(timeout);
+        }
+    }
+
+    public static void main(String[] args) {
+        TaskListener<Void> taskListener = new TaskListener<Void>() {
+            public synchronized void taskExecuted(Task<Void> task) {
+                System.out.println("EXECUTED");
+                notify();
+            }
+
+            public synchronized void executeFailed(Task<Void> task) {
+                System.out.println("FAILED: " + task.getFault());
+                notify();
+            }
+        };
+
+        testTaskSequence(taskListener);
+        testTaskGroup(taskListener);
+    }
+
+    private static void testTaskSequence(TaskListener<Void> taskListener) {
+        System.out.println("Testing task sequence");
+
+        TaskSequence<Void> taskSequence = new TaskSequence<Void>();
+
+        SleepTask task1 = new SleepTask(2000);
+        taskSequence.add(task1);
+
+        SleepTask task2 = new SleepTask(500);
+        taskSequence.add(task2);
+
+        SleepTask task3 = new SleepTask(1000);
+        taskSequence.add(task3);
+
+        synchronized (taskListener) {
+            taskSequence.execute(taskListener);
+
+            try {
+                taskListener.wait();
+            } catch (InterruptedException exception) {
+            }
+        }
+    }
+
+    private static void testTaskGroup(TaskListener<Void> taskListener) {
+        System.out.println("Testing task group");
+
+        TaskGroup<Void> taskGroup = new TaskGroup<Void>();
+
+        SleepTask task1 = new SleepTask(2000);
+        taskGroup.add(task1);
+
+        SleepTask task2 = new SleepTask(500);
+        taskGroup.add(task2);
+
+        SleepTask task3 = new SleepTask(1000);
+        taskGroup.add(task3);
+
+        synchronized (taskListener) {
+            taskGroup.execute(taskListener);
+
+            try {
+                taskListener.wait();
+            } catch (InterruptedException exception) {
+            }
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/VersionTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/VersionTest.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/VersionTest.java (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/pivot/core/test/VersionTest.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,22 @@
+package pivot.core.test;
+
+import pivot.util.Version;
+
+public class VersionTest {
+    public static void main(String[] args) {
+        Version version = Version.decode(System.getProperty("java.version"));
+        System.out.println(version);
+
+        Version version_1_5_0_13 = new Version(1, 5, 0, 13);
+        System.out.println(version.compareTo(version_1_5_0_13));
+
+        Version version_1_4_1_5 = new Version(1, 4, 1, 5);
+        System.out.println(version.compareTo(version_1_4_1_5));
+
+        Version version_1_6_0_10 = new Version(1, 6, 0, 10);
+        System.out.println(version.compareTo(version_1_6_0_10));
+
+        Version maxVersion = new Version(0x7f, 0xff, 0xff, 0xff);
+        System.out.println(maxVersion.compareTo(version));
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test1.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test1.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test1.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test1.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,24 @@
+
+{
+    "glossary": {
+        "title": "example glossary",
+		"GlossDiv": {
+            "title": "S",
+			"GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+					"SortAs": "SGML",
+					"GlossTerm": "Standard Generalized Markup Language",
+					"Acronym": "SGML",
+					"Abbrev": "ISO 8879:1986",
+					"GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+						"GlossSeeAlso": ["GML", "XML"]
+                    },
+					"GlossSee": "markup"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test2.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test2.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test2.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test2.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,24 @@
+
+{
+    "glossary": {
+        "title": "example glossary",
+		"GlossDiv": {
+            "title": "S",
+			"GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+					"SortAs": "SGML",
+					"GlossTerm": "Standard Generalized Markup Language",
+					"Acronym": "SGML",
+					"Abbrev": "ISO 8879:1986",
+					"GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+						"GlossSeeAlso": ["GML", "XML"]
+                    },
+					"GlossSee": "markup"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test2_en.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test2_en.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test2_en.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test2_en.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,13 @@
+
+{
+    "glossary": {
+		"GlossDiv": {
+			"GlossList": {
+                "GlossEntry": {
+					"GlossTerm": "How Do, Youth, Standard Generalized Markup Language",
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test3.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test3.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test3.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test3.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,24 @@
+
+{
+    "glossary": {
+        "title": "example glossary",
+		"GlossDiv": {
+            "title": "S",
+			"GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+					"SortAs": "SGML",
+					"GlossTerm": "Standard Generalized Markup Language",
+					"Acronym": "SGML",
+					"Abbrev": "ISO 8879:1986",
+					"GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+						"GlossSeeAlso": ["GML", "XML"]
+                    },
+					"GlossSee": "markup"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,13 @@
+
+{
+    "glossary": {
+		"GlossDiv": {
+			"GlossList": {
+                "GlossEntry": {
+					"GlossTerm": "How Do, Youth, Standard Generalized Markup Language",
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en_GB.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en_GB.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en_GB.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test3_en_GB.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,13 @@
+
+{
+    "glossary": {
+		"GlossDiv": {
+			"GlossList": {
+                "GlossEntry": {
+					"Acronym": "XSGML"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test4.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test4.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test4.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test4.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,24 @@
+
+{
+    "glossary"x: {
+        "title": "example glossary",
+		"GlossDiv": {
+            "title": "S",
+			"GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+					"SortAs": "SGML",
+					"GlossTerm": "Standard Generalized Markup Language",
+					"Acronym": "SGML",
+					"Abbrev": "ISO 8879:1986",
+					"GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+						"GlossSeeAlso": ["GML", "XML"]
+                    },
+					"GlossSee": "markup"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test6.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test6.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test6.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test6.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,24 @@
+
+{
+    "glossary": {
+        "title": "example glossary",
+		"GlossDiv": {
+            "title": "S",
+			"GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+					"SortAs": "SGML",
+					"GlossTerm": "Standard Generalized Markup Language",
+					"Acronym": "SGML",
+					"Abbrev": "ISO 8879:1986",
+					"GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+						"GlossSeeAlso": ["GML", "XML"]
+                    },
+					"GlossSee": "markup"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,13 @@
+
+{
+    "glossary": {
+		"GlossDiv": {
+			"GlossList": {
+                "GlossEntry": {
+					"GlossTerm": "How Do, Youth, Standard Generalized Markup Language",
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en_GB.json
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en_GB.json?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en_GB.json (added)
+++ incubator/pivot/tags/v1.0.1/core-test/src/resources/test6_en_GB.json Mon Mar 16 16:36:10 2009
@@ -0,0 +1,14 @@
+
+{
+    "glossary": {
+		"GlossDiv": {
+			"GlossList": {
+                "GlossEntry": {
+					"Acronym": "XSGML",
+					"GlossTerm": "eXtra Standard Generalized Markup Language"
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/pivot/tags/v1.0.1/core/.classpath
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core/.classpath?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core/.classpath (added)
+++ incubator/pivot/tags/v1.0.1/core/.classpath Mon Mar 16 16:36:10 2009
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: incubator/pivot/tags/v1.0.1/core/.project
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core/.project?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core/.project (added)
+++ incubator/pivot/tags/v1.0.1/core/.project Mon Mar 16 16:36:10 2009
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: incubator/pivot/tags/v1.0.1/core/src/pivot/beans/BeanDictionary.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core/src/pivot/beans/BeanDictionary.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core/src/pivot/beans/BeanDictionary.java (added)
+++ incubator/pivot/tags/v1.0.1/core/src/pivot/beans/BeanDictionary.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import pivot.collections.Dictionary;
+
+/**
+ * Exposes Java bean properties of an object via the {@link Dictionary}
+ * interface. A call to {@link Dictionary#get(Object)} invokes the getter for
+ * the corresponding property, and a call to
+ * {@link Dictionary#put(Object, Object)} invokes the property's setter.
+ * <p>
+ * Properties may provide multiple setters; the appropriate setter to invoke
+ * is determined by the type of the value being set. If the value is
+ * <tt>null</tt>, the return type of the getter method is used.
+ *
+ * @author gbrown
+ */
+public class BeanDictionary implements Dictionary<String, Object>, Iterable<String> {
+    /**
+     * Property iterator. Walks the list of methods defined by the bean and
+     * returns a value for each getter method.
+     */
+    private class PropertyIterator implements Iterator<String> {
+        private Method[] methods = null;
+
+        int i = 0;
+        private String nextProperty = null;
+
+        public PropertyIterator() {
+            Class<?> type = bean.getClass();
+            methods = type.getMethods();
+            nextProperty();
+        }
+
+        public boolean hasNext() {
+            return (nextProperty != null);
+        }
+
+        public String next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            String nextProperty = this.nextProperty;
+            nextProperty();
+
+            return nextProperty;
+        }
+
+        private void nextProperty() {
+            nextProperty = null;
+
+            while (i < methods.length
+                && nextProperty == null) {
+                Method method = methods[i++];
+
+                if (method.getParameterTypes().length == 0
+                    && (method.getModifiers() & Modifier.STATIC) == 0) {
+                    String methodName = method.getName();
+
+                    String prefix = null;
+                    if (methodName.startsWith(GET_PREFIX)) {
+                        prefix = GET_PREFIX;
+                    } else {
+                        if (methodName.startsWith(IS_PREFIX)) {
+                            prefix = IS_PREFIX;
+                        }
+                    }
+
+                    if (prefix != null) {
+                        int propertyOffset = prefix.length();
+                        nextProperty = Character.toLowerCase(methodName.charAt(propertyOffset))
+                            + methodName.substring(propertyOffset + 1);
+                    }
+
+                    if (nextProperty != null
+                        && ignoreReadOnlyProperties
+                        && isReadOnly(nextProperty)) {
+                        nextProperty = null;
+                    }
+                }
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private Object bean;
+    private boolean ignoreReadOnlyProperties;
+
+    public static final String GET_PREFIX = "get";
+    public static final String IS_PREFIX = "is";
+    public static final String SET_PREFIX = "set";
+    public static final String LISTENERS_SUFFIX = "Listeners";
+
+    /**
+     * Creates a new bean dictionary.
+     *
+     * @param bean
+     * The bean object to wrap.
+     */
+    public BeanDictionary(Object bean) {
+        this(bean, false);
+    }
+
+    /**
+     * Creates a new bean dictionary.
+     *
+     * @param bean
+     * The bean object to wrap.
+     */
+    public BeanDictionary(Object bean, boolean ignoreReadOnlyProperties) {
+        if (bean == null) {
+            throw new IllegalArgumentException("bean is null.");
+        }
+
+        this.bean = bean;
+        this.ignoreReadOnlyProperties = ignoreReadOnlyProperties;
+    }
+
+    /**
+     * Invokes the getter method for the given property.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * The value returned by the method, or <tt>null</tt> if no such method
+     * exists.
+     */
+    public Object get(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        Object value = null;
+
+        Method getterMethod = getGetterMethod(key);
+
+        if (getterMethod != null) {
+            try {
+                value = getterMethod.invoke(bean, new Object[] {});
+            } catch(IllegalAccessException exception) {
+                // No-op
+            } catch(InvocationTargetException exception) {
+                // No-op
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * Invokes the a setter method for the given property. The method
+     * signature is determined by the type of the value. If the value is
+     * <tt>null</tt>, the return type of the getter method is used.
+     *
+     * @param key
+     * The property name.
+     *
+     * @param value
+     * The new property value.
+     *
+     * @return
+     * Returns <tt>null</tt>, since returning the previous value would require
+     * a call to the getter method, which may not be an efficient operation.
+     *
+     * @throws PropertyNotFoundException
+     * If the given property does not exist or is read-only.
+     */
+    public Object put(String key, Object value) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        Class<?> valueType = null;
+
+        if (value == null) {
+            Method getterMethod = getGetterMethod(key);
+            if (getterMethod == null) {
+                throw new PropertyNotFoundException("Property \"" + key + "\"" +
+                    " does not exist.");
+            }
+
+            valueType = getterMethod.getReturnType();
+        } else {
+            valueType = value.getClass();
+        }
+
+        Method setterMethod = getSetterMethod(key, valueType);
+
+        if (setterMethod == null) {
+            throw new PropertyNotFoundException("Property \"" + key + "\""
+                + " of type " + valueType.getName()
+                + " does not exist or is read-only.");
+        }
+
+        try {
+            setterMethod.invoke(bean, new Object[] {value});
+        } catch(IllegalAccessException exception) {
+            throw new IllegalArgumentException(exception);
+        } catch(InvocationTargetException exception) {
+            throw new IllegalArgumentException(exception);
+        }
+
+        return null;
+    }
+
+    /**
+     * @throws UnsupportedOperationException
+     * This method is not supported.
+     */
+    public Object remove(String key) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Verifies the existence of a property. The property must have a getter
+     * method; write-only properties are not supported.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * <tt>true</tt> if the property exists; <tt>false</tt>, otherwise.
+     */
+    public boolean containsKey(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        return (getGetterMethod(key) != null);
+    }
+
+    /**
+     * Verifies that the bean contains at least one property.
+     */
+    public boolean isEmpty() {
+        return !iterator().hasNext();
+    }
+
+    /**
+     * Tests the read-only state of a property.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * <tt>true</tt> if the property is read-only; <tt>false</tt>, otherwise.
+     */
+    public boolean isReadOnly(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        return (getSetterMethod(key, getType(key)) == null);
+    }
+
+    /**
+     * Returns the type of a property.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * The type of the property.
+     */
+    public Class<?> getType(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        Method getterMethod = getGetterMethod(key);
+
+        if (getterMethod == null) {
+            throw new PropertyNotFoundException("Property \"" + key
+                + "\" does not exist.");
+        }
+
+        return getterMethod.getReturnType();
+    }
+
+    /**
+     * Returns an iterator over the bean's properties.
+     *
+     * @return
+     * A property iterator for this bean.
+     */
+    public Iterator<String> iterator() {
+        return new PropertyIterator();
+    }
+
+    /**
+     * Returns the getter method for a property.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * The getter method, or <tt>null</tt> if the method does not exist.
+     */
+    private Method getGetterMethod(String key) {
+        Class<?> type = bean.getClass();
+
+        // Upper-case the first letter
+        key = Character.toUpperCase(key.charAt(0)) + key.substring(1);
+        Method method = null;
+
+        try {
+            method = type.getMethod(GET_PREFIX + key, new Class<?>[] {});
+        } catch(NoSuchMethodException exception) {
+            // No-op
+        }
+
+        if (method == null) {
+            try {
+                method = type.getMethod(IS_PREFIX + key, new Class<?>[] {});
+            } catch(NoSuchMethodException exception) {
+                // No-op
+            }
+        }
+
+        return method;
+    }
+
+    /**
+     * Returns the setter method for a property.
+     *
+     * @param key
+     * The property name.
+     *
+     * @return
+     * The getter method, or <tt>null</tt> if the method does not exist.
+     */
+    private Method getSetterMethod(String key, Class<?> valueType) {
+        Class<?> type = bean.getClass();
+        Method method = null;
+
+        if (valueType != null) {
+            // Upper-case the first letter and prepend the "set" prefix to
+            // determine the method name
+            key = Character.toUpperCase(key.charAt(0)) + key.substring(1);
+            final String methodName = SET_PREFIX + key;
+
+            try {
+                method = type.getMethod(methodName, new Class<?>[] {valueType});
+            } catch(NoSuchMethodException exception) {
+                // No-op
+            }
+
+            if (method == null) {
+                // Look for a match on the value's super type
+                Class<?> superType = valueType.getSuperclass();
+                method = getSetterMethod(key, superType);
+            }
+
+            if (method == null) {
+                // If value type is a primitive wrapper, look for a method
+                // signature with the corresponding primitive type
+                try {
+                    Field primitiveTypeField = valueType.getField("TYPE");
+                    Class<?> primitiveValueType = (Class<?>)primitiveTypeField.get(this);
+
+                    try {
+                        method = type.getMethod(methodName, new Class<?>[] {primitiveValueType});
+                    } catch(NoSuchMethodException exception) {
+                        // No-op
+                    }
+                } catch(NoSuchFieldException exception) {
+                    // No-op; not a wrapper type
+                } catch(IllegalAccessException exception) {
+                    // No-op
+                }
+            }
+
+            if (method == null) {
+                // Walk the interface graph to find a matching method
+                Class<?>[] interfaces = valueType.getInterfaces();
+
+                int i = 0, n = interfaces.length;
+                while (method == null
+                    && i < n) {
+                    Class<?> interfaceType = interfaces[i++];
+                    method = getSetterMethod(key, interfaceType);
+                }
+            }
+        }
+
+        return method;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core/src/pivot/beans/PropertyNotFoundException.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core/src/pivot/beans/PropertyNotFoundException.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core/src/pivot/beans/PropertyNotFoundException.java (added)
+++ incubator/pivot/tags/v1.0.1/core/src/pivot/beans/PropertyNotFoundException.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.beans;
+
+/**
+ * Thrown when a caller attempts to set the value of a non-existent bean
+ * property.
+ *
+ * @author gbrown
+ */
+public class PropertyNotFoundException extends RuntimeException {
+    public static final long serialVersionUID = 0;
+
+    public PropertyNotFoundException() {
+        this(null, null);
+    }
+
+    public PropertyNotFoundException(String message) {
+        this(message, null);
+    }
+
+    public PropertyNotFoundException(Throwable cause) {
+        this(null, cause);
+    }
+
+    public PropertyNotFoundException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/core/src/pivot/beans/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/core/src/pivot/beans/package.html?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/core/src/pivot/beans/package.html (added)
+++ incubator/pivot/tags/v1.0.1/core/src/pivot/beans/package.html Mon Mar 16 16:36:10 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains classes that provide access to the Java bean properties of an object via a dictionary interface.</p>
+</body>
+</html>