You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by cb...@apache.org on 2010/09/15 12:57:37 UTC

svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Author: cbartlett
Date: Wed Sep 15 10:57:37 2010
New Revision: 997274

URL: http://svn.apache.org/viewvc?rev=997274&view=rev
Log:
Resolve PIVOT-634
New functionality for BeanAdapter and test files

Added:
    pivot/trunk/tests/src/org/apache/pivot/tests/EnumBean.java
    pivot/trunk/tests/src/org/apache/pivot/tests/EnumBeanTest.java
    pivot/trunk/tests/src/org/apache/pivot/tests/enum_bean.bxml
Modified:
    pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java

Modified: pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java
URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java?rev=997274&r1=997273&r2=997274&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java Wed Sep 15 10:57:37 2010
@@ -21,8 +21,10 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.NoSuchElementException;
 
 import org.apache.pivot.collections.Map;
@@ -148,6 +150,7 @@ public class BeanAdapter implements Map<
     public static final String SET_PREFIX = "set";
     public static final String FIELD_PREFIX = "~";
 
+    private static final String ENUM_VALUE_OF_METHOD_NAME = "valueOf";
     private static final String ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT =
         "Unable to access property \"%s\" for type %s.";
 
@@ -841,6 +844,8 @@ public class BeanAdapter implements Map<
             if (type.isAssignableFrom(value.getClass())) {
                 // Value doesn't need coercion
                 coercedValue = value;
+            } else if (type.isEnum() && value instanceof String) {
+                coercedValue = coerceEnum(value, type);
             } else {
                 // Coerce the value to the requested type
                 if (type == Boolean.class
@@ -902,4 +907,65 @@ public class BeanAdapter implements Map<
 
         return (T)coercedValue;
     }
+
+    /**
+     * Attempt to coerce a String to an instance of a supplied enum class.
+     * <p>
+     * The supplied String will be converted to upper case using
+     * <code>Locale.ENGLISH</code> before being used in an invocation of
+     * <code>T.valueOf(String)</code>.
+     * <p>
+     * Depends on the existence of a <code>public static T valueOf(String
+     * name)</code> method as defined in the <a href=
+     * "http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.9"
+     * >Java Language Specification</a>.
+     *
+     * @param <T> Coercion target type.
+     * @param value String to be coerced.
+     * @param type Target enum class.
+     * @return The coerced value.
+     */
+    @SuppressWarnings("unchecked")
+    private static <T> T coerceEnum(Object value, Class<? extends T> type) {
+        if (type == null || !type.isEnum()) {
+            throw new IllegalArgumentException(String.format(
+                "Supplied Class is not an Enum. Class=%s", (type == null ? null : type.getName())));
+        }
+        if (!(value instanceof String)) {
+            throw new IllegalArgumentException(String.format(
+                "Non-null String value must be supplied for enum coercion.  Value=%s",
+                (value == null ? null : value.getClass().getName())));
+        }
+
+        // Find and invoke the valueOf(String) method, with an upper case
+        // version of the supplied String
+        T coercedValue = null;
+        try {
+            Method valueOfMethod = type.getMethod(ENUM_VALUE_OF_METHOD_NAME, String.class);
+            if (valueOfMethod != null) {
+                String valueString = ((String) value).toUpperCase(Locale.ENGLISH);
+                    coercedValue = (T) valueOfMethod.invoke(null, valueString);
+            }
+        }
+        // Nothing to be gained by handling the getMethod() & invoke()
+        // Exceptions separately
+        catch (IllegalAccessException e) {
+            throwCoerceEnumException(value, type, e);
+        } catch (InvocationTargetException e) {
+            throwCoerceEnumException(value, type, e);
+        } catch (SecurityException e) {
+            throwCoerceEnumException(value, type, e);
+        } catch (NoSuchMethodException e) {
+            throwCoerceEnumException(value, type, e);
+        }
+
+        return coercedValue;
+    }
+
+    private static void throwCoerceEnumException(Object value, Class<?> type, Throwable cause) {
+        String message = String.format(
+            "Unable to coerce %s (\"%s\") to %s.\nValid enum constants - %s",
+            value.getClass().getName(), value, type, Arrays.toString(type.getEnumConstants()));
+        throw new IllegalArgumentException(message, cause);
+    }
 }

Added: pivot/trunk/tests/src/org/apache/pivot/tests/EnumBean.java
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/EnumBean.java?rev=997274&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/EnumBean.java (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/EnumBean.java Wed Sep 15 10:57:37 2010
@@ -0,0 +1,410 @@
+/*
+ * 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.pivot.tests;
+
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.util.Vote;
+import org.apache.pivot.web.Query;
+import org.apache.pivot.wtk.BindType;
+import org.apache.pivot.wtk.Button;
+import org.apache.pivot.wtk.Cursor;
+import org.apache.pivot.wtk.DropAction;
+import org.apache.pivot.wtk.FileBrowserSheet;
+import org.apache.pivot.wtk.FocusTraversalDirection;
+import org.apache.pivot.wtk.GraphicsUtilities;
+import org.apache.pivot.wtk.HorizontalAlignment;
+import org.apache.pivot.wtk.ImageView;
+import org.apache.pivot.wtk.Keyboard;
+import org.apache.pivot.wtk.ListView;
+import org.apache.pivot.wtk.MessageType;
+import org.apache.pivot.wtk.Mouse;
+import org.apache.pivot.wtk.Orientation;
+import org.apache.pivot.wtk.ScrollPane;
+import org.apache.pivot.wtk.SortDirection;
+import org.apache.pivot.wtk.SplitPane;
+import org.apache.pivot.wtk.TableView;
+import org.apache.pivot.wtk.TableViewHeader;
+import org.apache.pivot.wtk.TextArea;
+import org.apache.pivot.wtk.TextDecoration;
+import org.apache.pivot.wtk.TreeView;
+import org.apache.pivot.wtk.VerticalAlignment;
+import org.apache.pivot.wtk.media.BufferedImageSerializer;
+import org.apache.pivot.wtk.media.Picture;
+import org.apache.pivot.wtk.media.drawing.Arc;
+import org.apache.pivot.wtk.media.drawing.Path;
+import org.apache.pivot.wtk.skin.CardPaneSkin;
+import org.apache.pivot.wtk.text.BulletedList;
+import org.apache.pivot.wtk.text.NumberedList;
+
+/**
+ * Simple bean for testing String to enum coercion.
+ * {@link BeanAdapter#coerceEnum(Object, Class)}.
+ * <p>
+ * All accessors were created using Eclipse's 'Generate Getters & Setters"
+ * source generation.  No addtional code has been added to them, so they
+ * can safely be deleted and regenerated if required.
+ */
+public class EnumBean {
+
+    // Public non-static field for testing BeanAdapter#get("~orientationField");
+    public Orientation orientationField;
+
+    private Arc.Type arcType;
+    private BindType bindType;
+    private BufferedImageSerializer.Format bufferedImageSerializerFormat;
+    private BulletedList.Style bulletedListStyle;
+    private Button.State buttonState;
+    private CardPaneSkin.SelectionChangeEffect selectionChangeEffect;
+    private Cursor cursor;
+    private DropAction dropAction;
+    private FileBrowserSheet.Mode fileBrowserSheetMode;
+    private FocusTraversalDirection focusTraversalDirection;
+    private GraphicsUtilities.PaintType paintType;
+    private HorizontalAlignment horizontalAlignment;
+    private ImageView.ImageBindMapping.Type imageBindMappingType;
+    private Keyboard.KeyLocation keyLocation;
+    private Keyboard.Modifier modifier;
+    private ListView.SelectMode listViewSelectMode;
+    private MessageBusTest.TestMessage testMessage;
+    private MessageType messageType;
+    private Mouse.Button mouseButton;
+    private Mouse.ScrollType mouseScrollType;
+    private NumberedList.Style numberedListStyle;
+    private Orientation orientation;
+    private Path.WindingRule windingRule;
+    private Picture.Interpolation interpolation;
+    private Query.Method queryMethod;
+    private ScrollPane.Corner.Placement placement;
+    private ScrollPane.ScrollBarPolicy scrollBarPolicy;
+    private SortDirection sortDirection;
+    private SplitPane.Region splitPaneRegion;
+    private SplitPane.ResizeMode splitPaneResizeMode;
+    private TableView.SelectMode tableViewSelectMode;
+    private TableViewHeader.SortMode sortMode;
+    private TextDecoration textDecoration;
+    private TextArea.ScrollDirection scrollDirection;
+    private TreeView.NodeCheckState nodeCheckState;
+    private TreeView.SelectMode treeViewSelectMode;
+    private VerticalAlignment verticalAlignment;
+    private Vote vote;
+
+    public Arc.Type getArcType() {
+        return arcType;
+    }
+
+    public void setArcType(Arc.Type arcType) {
+        this.arcType = arcType;
+    }
+
+    public BindType getBindType() {
+        return bindType;
+    }
+
+    public void setBindType(BindType bindType) {
+        this.bindType = bindType;
+    }
+
+    public BufferedImageSerializer.Format getBufferedImageSerializerFormat() {
+        return bufferedImageSerializerFormat;
+    }
+
+    public void setBufferedImageSerializerFormat(
+        BufferedImageSerializer.Format bufferedImageSerializerFormat) {
+        this.bufferedImageSerializerFormat = bufferedImageSerializerFormat;
+    }
+
+    public BulletedList.Style getBulletedListStyle() {
+        return bulletedListStyle;
+    }
+
+    public void setBulletedListStyle(BulletedList.Style bulletedListStyle) {
+        this.bulletedListStyle = bulletedListStyle;
+    }
+
+    public Button.State getButtonState() {
+        return buttonState;
+    }
+
+    public void setButtonState(Button.State buttonState) {
+        this.buttonState = buttonState;
+    }
+
+    public CardPaneSkin.SelectionChangeEffect getSelectionChangeEffect() {
+        return selectionChangeEffect;
+    }
+
+    public void setSelectionChangeEffect(CardPaneSkin.SelectionChangeEffect selectionChangeEffect) {
+        this.selectionChangeEffect = selectionChangeEffect;
+    }
+
+    public Cursor getCursor() {
+        return cursor;
+    }
+
+    public void setCursor(Cursor cursor) {
+        this.cursor = cursor;
+    }
+
+    public DropAction getDropAction() {
+        return dropAction;
+    }
+
+    public void setDropAction(DropAction dropAction) {
+        this.dropAction = dropAction;
+    }
+
+    public FileBrowserSheet.Mode getFileBrowserSheetMode() {
+        return fileBrowserSheetMode;
+    }
+
+    public void setFileBrowserSheetMode(FileBrowserSheet.Mode fileBrowserSheetMode) {
+        this.fileBrowserSheetMode = fileBrowserSheetMode;
+    }
+
+    public FocusTraversalDirection getFocusTraversalDirection() {
+        return focusTraversalDirection;
+    }
+
+    public void setFocusTraversalDirection(FocusTraversalDirection focusTraversalDirection) {
+        this.focusTraversalDirection = focusTraversalDirection;
+    }
+
+    public GraphicsUtilities.PaintType getPaintType() {
+        return paintType;
+    }
+
+    public void setPaintType(GraphicsUtilities.PaintType paintType) {
+        this.paintType = paintType;
+    }
+
+    public HorizontalAlignment getHorizontalAlignment() {
+        return horizontalAlignment;
+    }
+
+    public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) {
+        this.horizontalAlignment = horizontalAlignment;
+    }
+
+    public ImageView.ImageBindMapping.Type getImageBindMappingType() {
+        return imageBindMappingType;
+    }
+
+    public void setImageBindMappingType(ImageView.ImageBindMapping.Type imageBindMappingType) {
+        this.imageBindMappingType = imageBindMappingType;
+    }
+
+    public Keyboard.KeyLocation getKeyLocation() {
+        return keyLocation;
+    }
+
+    public void setKeyLocation(Keyboard.KeyLocation keyLocation) {
+        this.keyLocation = keyLocation;
+    }
+
+    public Keyboard.Modifier getModifier() {
+        return modifier;
+    }
+
+    public void setModifier(Keyboard.Modifier modifier) {
+        this.modifier = modifier;
+    }
+
+    public ListView.SelectMode getListViewSelectMode() {
+        return listViewSelectMode;
+    }
+
+    public void setListViewSelectMode(ListView.SelectMode listViewSelectMode) {
+        this.listViewSelectMode = listViewSelectMode;
+    }
+
+    public MessageBusTest.TestMessage getTestMessage() {
+        return testMessage;
+    }
+
+    public void setTestMessage(MessageBusTest.TestMessage testMessage) {
+        this.testMessage = testMessage;
+    }
+
+    public MessageType getMessageType() {
+        return messageType;
+    }
+
+    public void setMessageType(MessageType messageType) {
+        this.messageType = messageType;
+    }
+
+    public Mouse.Button getMouseButton() {
+        return mouseButton;
+    }
+
+    public void setMouseButton(Mouse.Button mouseButton) {
+        this.mouseButton = mouseButton;
+    }
+
+    public Mouse.ScrollType getMouseScrollType() {
+        return mouseScrollType;
+    }
+
+    public void setMouseScrollType(Mouse.ScrollType mouseScrollType) {
+        this.mouseScrollType = mouseScrollType;
+    }
+
+    public NumberedList.Style getNumberedListStyle() {
+        return numberedListStyle;
+    }
+
+    public void setNumberedListStyle(NumberedList.Style numberedListStyle) {
+        this.numberedListStyle = numberedListStyle;
+    }
+
+    public Orientation getOrientation() {
+        return orientation;
+    }
+
+    public void setOrientation(Orientation orientation) {
+        this.orientation = orientation;
+    }
+
+    public Path.WindingRule getWindingRule() {
+        return windingRule;
+    }
+
+    public void setWindingRule(Path.WindingRule windingRule) {
+        this.windingRule = windingRule;
+    }
+
+    public Picture.Interpolation getInterpolation() {
+        return interpolation;
+    }
+
+    public void setInterpolation(Picture.Interpolation interpolation) {
+        this.interpolation = interpolation;
+    }
+
+    public Query.Method getQueryMethod() {
+        return queryMethod;
+    }
+
+    public void setQueryMethod(Query.Method queryMethod) {
+        this.queryMethod = queryMethod;
+    }
+
+    public ScrollPane.Corner.Placement getPlacement() {
+        return placement;
+    }
+
+    public void setPlacement(ScrollPane.Corner.Placement placement) {
+        this.placement = placement;
+    }
+
+    public ScrollPane.ScrollBarPolicy getScrollBarPolicy() {
+        return scrollBarPolicy;
+    }
+
+    public void setScrollBarPolicy(ScrollPane.ScrollBarPolicy scrollBarPolicy) {
+        this.scrollBarPolicy = scrollBarPolicy;
+    }
+
+    public SortDirection getSortDirection() {
+        return sortDirection;
+    }
+
+    public void setSortDirection(SortDirection sortDirection) {
+        this.sortDirection = sortDirection;
+    }
+
+    public SplitPane.Region getSplitPaneRegion() {
+        return splitPaneRegion;
+    }
+
+    public void setSplitPaneRegion(SplitPane.Region splitPaneRegion) {
+        this.splitPaneRegion = splitPaneRegion;
+    }
+
+    public SplitPane.ResizeMode getSplitPaneResizeMode() {
+        return splitPaneResizeMode;
+    }
+
+    public void setSplitPaneResizeMode(SplitPane.ResizeMode splitPaneResizeMode) {
+        this.splitPaneResizeMode = splitPaneResizeMode;
+    }
+
+    public TableView.SelectMode getTableViewSelectMode() {
+        return tableViewSelectMode;
+    }
+
+    public void setTableViewSelectMode(TableView.SelectMode tableViewSelectMode) {
+        this.tableViewSelectMode = tableViewSelectMode;
+    }
+
+    public TableViewHeader.SortMode getSortMode() {
+        return sortMode;
+    }
+
+    public void setSortMode(TableViewHeader.SortMode sortMode) {
+        this.sortMode = sortMode;
+    }
+
+    public TextDecoration getTextDecoration() {
+        return textDecoration;
+    }
+
+    public void setTextDecoration(TextDecoration textDecoration) {
+        this.textDecoration = textDecoration;
+    }
+
+    public TextArea.ScrollDirection getScrollDirection() {
+        return scrollDirection;
+    }
+
+    public void setScrollDirection(TextArea.ScrollDirection scrollDirection) {
+        this.scrollDirection = scrollDirection;
+    }
+
+    public TreeView.NodeCheckState getNodeCheckState() {
+        return nodeCheckState;
+    }
+
+    public void setNodeCheckState(TreeView.NodeCheckState nodeCheckState) {
+        this.nodeCheckState = nodeCheckState;
+    }
+
+    public TreeView.SelectMode getTreeViewSelectMode() {
+        return treeViewSelectMode;
+    }
+
+    public void setTreeViewSelectMode(TreeView.SelectMode treeViewSelectMode) {
+        this.treeViewSelectMode = treeViewSelectMode;
+    }
+
+    public VerticalAlignment getVerticalAlignment() {
+        return verticalAlignment;
+    }
+
+    public void setVerticalAlignment(VerticalAlignment verticalAlignment) {
+        this.verticalAlignment = verticalAlignment;
+    }
+
+    public Vote getVote() {
+        return vote;
+    }
+
+    public void setVote(Vote vote) {
+        this.vote = vote;
+    }
+}

Added: pivot/trunk/tests/src/org/apache/pivot/tests/EnumBeanTest.java
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/EnumBeanTest.java?rev=997274&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/EnumBeanTest.java (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/EnumBeanTest.java Wed Sep 15 10:57:37 2010
@@ -0,0 +1,61 @@
+/*
+ * 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.pivot.tests;
+
+import java.io.IOException;
+
+import org.apache.pivot.beans.BXMLSerializer;
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.serialization.SerializationException;
+import org.apache.pivot.wtk.Orientation;
+
+public class EnumBeanTest {
+    public static void main(String[] args) {
+
+        BXMLSerializer bxmlSerializer = new BXMLSerializer();
+        try {
+            EnumBean enumBean = (EnumBean) bxmlSerializer.readObject(EnumBeanTest.class,
+                "enum_bean.bxml");
+            System.out.println("Bean read OK - " + enumBean);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (SerializationException e) {
+            e.printStackTrace();
+        }
+
+        // Test BeanAdapter get/put using field access prefix '~'
+        EnumBean enumBean = new EnumBean();
+        BeanAdapter ba = new BeanAdapter(enumBean);
+
+        ba.put("~orientationField", Orientation.HORIZONTAL);
+        dump(enumBean, ba);
+
+        ba.put("~orientationField", "vertical");
+        dump(enumBean, ba);
+    }
+
+    private static void dump(EnumBean enumBean, BeanAdapter ba) {
+        Object value = enumBean.orientationField;
+        System.out.println(String.format("\n%-40s %-20s %s", "Direct field access", value,
+            (value == null) ? "[null]" : value.getClass().getName()));
+
+        value = ba.get("~orientationField");
+        System.out.println(String.format("%-40s %-20s %s", "~orientationField", value,
+            (value == null) ? "[null]" : value.getClass().getName()));
+    }
+}

Added: pivot/trunk/tests/src/org/apache/pivot/tests/enum_bean.bxml
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/enum_bean.bxml?rev=997274&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/enum_bean.bxml (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/enum_bean.bxml Wed Sep 15 10:57:37 2010
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<!--
+Tests the setting of bean enum properties without requiring the enum
+constant name to be specified in a case sensitive manner.
+
+There is also no requirement for the bean itself to have anything other
+than a standard setter methods. ie, No overloaded String setter method is
+required in order to handle the Enum.valueOf(String) aspect of the coercion.
+-->
+<EnumBean
+    xmlns="org.apache.pivot.tests"
+    xmlns:bxml="http://pivot.apache.org/bxml"
+
+    arcType="chord"
+    bindType="load"
+    bufferedImageSerializerFormat="png"
+    bulletedListStyle="circle"
+    buttonState="mixed"
+    cursor="crosshair"
+    dropAction="copy"
+    fileBrowserSheetMode="open"
+    focusTraversalDirection="backward"
+    horizontalAlignment="center"
+    imageBindMappingType="image"
+    interpolation="bicubic"
+    keyLocation="keypad"
+    listViewSelectMode="multi"
+    messageType="error"
+    modifier="alt"
+    mouseButton="left"
+    mouseScrollType="block"
+    nodeCheckState="checked"
+    numberedListStyle="decimal"
+    orientation="horizontal"
+    paintType="gradient"
+    placement="bottom_left"
+    queryMethod="delete"
+    scrollBarPolicy="always"
+    selectionChangeEffect="crossfade"
+    scrollDirection="down"
+    sortDirection="ascending"
+    sortMode="multi_column"
+    splitPaneRegion="bottom_right"
+    splitPaneResizeMode="primary_region"
+    tableViewSelectMode="multi"
+    testMessage="goodbye"
+    textDecoration="strikethrough"
+    treeViewSelectMode="multi"
+    verticalAlignment="bottom"
+    vote="approve">
+
+    <arcType>chord</arcType>
+    <arcType>open</arcType>
+    <arcType>pie</arcType>
+
+    <bindType>load</bindType>
+    <bindType>store</bindType>
+    <bindType>both</bindType>
+
+    <bufferedImageSerializerFormat>png</bufferedImageSerializerFormat>
+    <bufferedImageSerializerFormat>jpeg</bufferedImageSerializerFormat>
+    <bufferedImageSerializerFormat>bmp</bufferedImageSerializerFormat>
+    <bufferedImageSerializerFormat>wbmp</bufferedImageSerializerFormat>
+    <bufferedImageSerializerFormat>gif</bufferedImageSerializerFormat>
+
+    <bulletedListStyle>circle</bulletedListStyle>
+    <bulletedListStyle>circle_outline</bulletedListStyle>
+
+    <buttonState>mixed</buttonState>
+    <buttonState>selected</buttonState>
+    <buttonState>unselected</buttonState>
+
+    <cursor>crosshair</cursor>
+    <cursor>default</cursor>
+    <cursor>hand</cursor>
+    <cursor>move</cursor>
+    <cursor>resize_east</cursor>
+    <cursor>resize_north</cursor>
+    <cursor>resize_north_east</cursor>
+    <cursor>resize_north_west</cursor>
+    <cursor>resize_south</cursor>
+    <cursor>resize_south_east</cursor>
+    <cursor>resize_south_west</cursor>
+    <cursor>resize_west</cursor>
+    <cursor>text</cursor>
+    <cursor>wait</cursor>
+
+    <dropAction>copy</dropAction>
+    <dropAction>link</dropAction>
+    <dropAction>move</dropAction>
+
+    <fileBrowserSheetMode>open</fileBrowserSheetMode>
+    <fileBrowserSheetMode>open_multiple</fileBrowserSheetMode>
+    <fileBrowserSheetMode>save_as</fileBrowserSheetMode>
+    <fileBrowserSheetMode>save_to</fileBrowserSheetMode>
+
+    <focusTraversalDirection>backward</focusTraversalDirection>
+    <focusTraversalDirection>forward</focusTraversalDirection>
+
+    <horizontalAlignment>center</horizontalAlignment>
+    <horizontalAlignment>left</horizontalAlignment>
+    <horizontalAlignment>right</horizontalAlignment>
+
+    <imageBindMappingType>image</imageBindMappingType>
+    <imageBindMappingType>name</imageBindMappingType>
+    <imageBindMappingType>url</imageBindMappingType>
+
+    <interpolation>bicubic</interpolation>
+    <interpolation>bilinear</interpolation>
+    <interpolation>nearest_neighbor</interpolation>
+
+    <keyLocation>keypad</keyLocation>
+    <keyLocation>left</keyLocation>
+    <keyLocation>right</keyLocation>
+    <keyLocation>standard</keyLocation>
+
+    <listViewSelectMode>multi</listViewSelectMode>
+    <listViewSelectMode>none</listViewSelectMode>
+    <listViewSelectMode>single</listViewSelectMode>
+
+    <messageType>error</messageType>
+    <messageType>info</messageType>
+    <messageType>question</messageType>
+    <messageType>warning</messageType>
+
+    <modifier>alt</modifier>
+    <modifier>ctrl</modifier>
+    <modifier>meta</modifier>
+    <modifier>shift</modifier>
+
+    <mouseButton>left</mouseButton>
+    <mouseButton>middle</mouseButton>
+    <mouseButton>right</mouseButton>
+
+    <mouseScrollType>block</mouseScrollType>
+    <mouseScrollType>unit</mouseScrollType>
+
+    <nodeCheckState>checked</nodeCheckState>
+    <nodeCheckState>mixed</nodeCheckState>
+    <nodeCheckState>unchecked</nodeCheckState>
+
+    <numberedListStyle>decimal</numberedListStyle>
+    <numberedListStyle>lower_alpha</numberedListStyle>
+    <numberedListStyle>upper_alpha</numberedListStyle>
+    <numberedListStyle>lower_roman</numberedListStyle>
+    <numberedListStyle>upper_roman</numberedListStyle>
+
+    <orientation>horizontal</orientation>
+    <orientation>vertical</orientation>
+
+    <paintType>gradient</paintType>
+    <paintType>linear_gradient</paintType>
+    <paintType>radial_gradient</paintType>
+    <paintType>solid_color</paintType>
+
+    <placement>bottom_left</placement>
+    <placement>bottom_right</placement>
+    <placement>top_left</placement>
+    <placement>top_right</placement>
+
+    <queryMethod>delete</queryMethod>
+    <queryMethod>get</queryMethod>
+    <queryMethod>post</queryMethod>
+    <queryMethod>put</queryMethod>
+
+    <scrollBarPolicy>always</scrollBarPolicy>
+    <scrollBarPolicy>auto</scrollBarPolicy>
+    <scrollBarPolicy>fill</scrollBarPolicy>
+    <scrollBarPolicy>fill_to_capacity</scrollBarPolicy>
+    <scrollBarPolicy>never</scrollBarPolicy>
+
+    <selectionChangeEffect>crossfade</selectionChangeEffect>
+    <selectionChangeEffect>horizontal_flip</selectionChangeEffect>
+    <selectionChangeEffect>horizontal_slide</selectionChangeEffect>
+    <selectionChangeEffect>vertical_flip</selectionChangeEffect>
+    <selectionChangeEffect>vertical_slide</selectionChangeEffect>
+    <selectionChangeEffect>zoom</selectionChangeEffect>
+
+    <scrollDirection>down</scrollDirection>
+    <scrollDirection>up</scrollDirection>
+
+    <sortDirection>ascending</sortDirection>
+    <sortDirection>descending</sortDirection>
+
+    <sortMode>multi_column</sortMode>
+    <sortMode>none</sortMode>
+    <sortMode>single_column</sortMode>
+
+    <splitPaneRegion>bottom_right</splitPaneRegion>
+    <splitPaneRegion>top_left</splitPaneRegion>
+
+    <splitPaneResizeMode>primary_region</splitPaneResizeMode>
+    <splitPaneResizeMode>split_ratio</splitPaneResizeMode>
+
+    <tableViewSelectMode>multi</tableViewSelectMode>
+    <tableViewSelectMode>none</tableViewSelectMode>
+    <tableViewSelectMode>single</tableViewSelectMode>
+
+    <testMessage>goodbye</testMessage>
+    <testMessage>hello</testMessage>
+
+    <textDecoration>strikethrough</textDecoration>
+    <textDecoration>underline</textDecoration>
+
+    <treeViewSelectMode>multi</treeViewSelectMode>
+    <treeViewSelectMode>none</treeViewSelectMode>
+    <treeViewSelectMode>single</treeViewSelectMode>
+
+    <verticalAlignment>bottom</verticalAlignment>
+    <verticalAlignment>center</verticalAlignment>
+    <verticalAlignment>top</verticalAlignment>
+
+    <vote>approve</vote>
+    <vote>defer</vote>
+    <vote>deny</vote>
+
+    <windingRule>even_odd</windingRule>
+    <windingRule>non_zero</windingRule>
+
+</EnumBean>
\ No newline at end of file



Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Chris Bartlett <cb...@gmail.com>.
Changes made in r997330

On 15 September 2010 19:35, Greg Brown <gk...@mac.com> wrote:

> >>> +    private static <T> T coerceEnum(Object value, Class<? extends T>
> type) {
> >>
> >> Was there a reason you put this in a separate method? I imagined we'd
> just
> >> inline it in the coerce method.
> >>
> > I was thinking it might be useful in its own right & the logic is
> different
> > enough from the primitives coercion.
>
> Since the same functionality is available by calling coerce() directly, I
> think it would be best to simply inline it there.
>
>
>

Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Greg Brown <gk...@mac.com>.
>>> +    private static <T> T coerceEnum(Object value, Class<? extends T> type) {
>> 
>> Was there a reason you put this in a separate method? I imagined we'd just
>> inline it in the coerce method.
>> 
> I was thinking it might be useful in its own right & the logic is different
> enough from the primitives coercion.

Since the same functionality is available by calling coerce() directly, I think it would be best to simply inline it there.



Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Greg Brown <gk...@mac.com>.
> One other thing I was wondering about is whether I should have deprecated
> the setXXX(String) methods that I removed.

If we made this change between 1.5 and a hypothetical 1.6 release, it might make sense to deprecate them. However, since we're moving to 2.0, I think it is OK to simply remove them (we expect to see major API changes across major releases).


Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Chris Bartlett <cb...@gmail.com>.
One other thing I was wondering about is whether I should have deprecated
the setXXX(String) methods that I removed.
I've noticed past API changes that might have deprecated methods but didn't
(generally renaming methods).
Obviously it would be less imposing on users to keep the deprecated methods
for at least a single release.

I can back out the change & deprecate the methods if preferred.

Chris


On 15 September 2010 19:14, Chris Bartlett <cb...@gmail.com> wrote:

> Greg,
>
> Replies below
>
> Chris
>
> On 15 September 2010 18:38, Greg Brown <gk...@mac.com> wrote:
>
>> Hi Chris,
>>
>> Looks good - thanks for tackling this one. Comments below:
>>
>> > Modified: pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java
>> > @@ -841,6 +844,8 @@ public class BeanAdapter implements Map<
>> >             if (type.isAssignableFrom(value.getClass())) {
>> >                 // Value doesn't need coercion
>> >                 coercedValue = value;
>> > +            } else if (type.isEnum() && value instanceof String) {
>> > +                coercedValue = coerceEnum(value, type);
>>
>> Since this is a coercion method, it might be more flexible to check for
>> value != null and call toString() on it.
>>
>> OK, will do.
>
> > +    @SuppressWarnings("unchecked")
>> > +    private static <T> T coerceEnum(Object value, Class<? extends T>
>> type) {
>>
>> Was there a reason you put this in a separate method? I imagined we'd just
>> inline it in the coerce method.
>>
> I was thinking it might be useful in its own right & the logic is different
> enough from the primitives coercion.
> If you'd rather have it inline, I can make the change.
>
>
>>  > +        }
>> > +        if (!(value instanceof String)) {
>> > +            throw new IllegalArgumentException(String.format(
>> > +                "Non-null String value must be supplied for enum
>> coercion.  Value=%s",
>> > +                (value == null ? null : value.getClass().getName())));
>> > +        }
>>
>> Same comment here as above - it would probably be more flexible to call
>> toString() rather than cast to String. Also, null is a valid enum value, so
>> we should allow it.
>>
>> Will make the change.
>
>
>> > +
>> > +        // Find and invoke the valueOf(String) method, with an upper
>> case
>> > +        // version of the supplied String
>> > +        T coercedValue = null;
>> > +        try {
>> > +            Method valueOfMethod =
>> type.getMethod(ENUM_VALUE_OF_METHOD_NAME, String.class);
>> > +            if (valueOfMethod != null) {
>> > +                String valueString = ((String)
>> value).toUpperCase(Locale.ENGLISH);
>> > +                    coercedValue = (T) valueOfMethod.invoke(null,
>> valueString);
>> > +            }
>> > +        }
>> > +        // Nothing to be gained by handling the getMethod() & invoke()
>> > +        // Exceptions separately
>> > +        catch (IllegalAccessException e) {
>> > +            throwCoerceEnumException(value, type, e);
>>
>> In general, we don't define "thrower" methods. You could instead define a
>> constant for your exception message and re-use that in each catch block.
>> Later, when we (hopefully) get multi-catch in JDK 7, we can consolidate
>> blocks like this.
>>
>> Just trying to reduce code repetition, but I know it is clunky.
> I should have removed it earlier actually, as I simplified the exception
> message so it can just as easily be created using a constant as you
> suggested.  I blame delays between writing, testing and checking in for not
> catching it. :)
>
>
>

Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Chris Bartlett <cb...@gmail.com>.
Greg,

Replies below

Chris

On 15 September 2010 18:38, Greg Brown <gk...@mac.com> wrote:

> Hi Chris,
>
> Looks good - thanks for tackling this one. Comments below:
>
> > Modified: pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java
> > @@ -841,6 +844,8 @@ public class BeanAdapter implements Map<
> >             if (type.isAssignableFrom(value.getClass())) {
> >                 // Value doesn't need coercion
> >                 coercedValue = value;
> > +            } else if (type.isEnum() && value instanceof String) {
> > +                coercedValue = coerceEnum(value, type);
>
> Since this is a coercion method, it might be more flexible to check for
> value != null and call toString() on it.
>
> OK, will do.

> +    @SuppressWarnings("unchecked")
> > +    private static <T> T coerceEnum(Object value, Class<? extends T>
> type) {
>
> Was there a reason you put this in a separate method? I imagined we'd just
> inline it in the coerce method.
>
I was thinking it might be useful in its own right & the logic is different
enough from the primitives coercion.
If you'd rather have it inline, I can make the change.


>  > +        }
> > +        if (!(value instanceof String)) {
> > +            throw new IllegalArgumentException(String.format(
> > +                "Non-null String value must be supplied for enum
> coercion.  Value=%s",
> > +                (value == null ? null : value.getClass().getName())));
> > +        }
>
> Same comment here as above - it would probably be more flexible to call
> toString() rather than cast to String. Also, null is a valid enum value, so
> we should allow it.
>
> Will make the change.


> > +
> > +        // Find and invoke the valueOf(String) method, with an upper
> case
> > +        // version of the supplied String
> > +        T coercedValue = null;
> > +        try {
> > +            Method valueOfMethod =
> type.getMethod(ENUM_VALUE_OF_METHOD_NAME, String.class);
> > +            if (valueOfMethod != null) {
> > +                String valueString = ((String)
> value).toUpperCase(Locale.ENGLISH);
> > +                    coercedValue = (T) valueOfMethod.invoke(null,
> valueString);
> > +            }
> > +        }
> > +        // Nothing to be gained by handling the getMethod() & invoke()
> > +        // Exceptions separately
> > +        catch (IllegalAccessException e) {
> > +            throwCoerceEnumException(value, type, e);
>
> In general, we don't define "thrower" methods. You could instead define a
> constant for your exception message and re-use that in each catch block.
> Later, when we (hopefully) get multi-catch in JDK 7, we can consolidate
> blocks like this.
>
> Just trying to reduce code repetition, but I know it is clunky.
I should have removed it earlier actually, as I simplified the exception
message so it can just as easily be created using a constant as you
suggested.  I blame delays between writing, testing and checking in for not
catching it. :)

Re: svn commit: r997274 - in /pivot/trunk: core/src/org/apache/pivot/beans/BeanAdapter.java tests/src/org/apache/pivot/tests/EnumBean.java tests/src/org/apache/pivot/tests/EnumBeanTest.java tests/src/org/apache/pivot/tests/enum_bean.bxml

Posted by Greg Brown <gk...@mac.com>.
Hi Chris,

Looks good - thanks for tackling this one. Comments below:

> Modified: pivot/trunk/core/src/org/apache/pivot/beans/BeanAdapter.java
> @@ -841,6 +844,8 @@ public class BeanAdapter implements Map<
>             if (type.isAssignableFrom(value.getClass())) {
>                 // Value doesn't need coercion
>                 coercedValue = value;
> +            } else if (type.isEnum() && value instanceof String) {
> +                coercedValue = coerceEnum(value, type);

Since this is a coercion method, it might be more flexible to check for value != null and call toString() on it.

> +    @SuppressWarnings("unchecked")
> +    private static <T> T coerceEnum(Object value, Class<? extends T> type) {

Was there a reason you put this in a separate method? I imagined we'd just inline it in the coerce method.

> +        }
> +        if (!(value instanceof String)) {
> +            throw new IllegalArgumentException(String.format(
> +                "Non-null String value must be supplied for enum coercion.  Value=%s",
> +                (value == null ? null : value.getClass().getName())));
> +        }

Same comment here as above - it would probably be more flexible to call toString() rather than cast to String. Also, null is a valid enum value, so we should allow it.

> +
> +        // Find and invoke the valueOf(String) method, with an upper case
> +        // version of the supplied String
> +        T coercedValue = null;
> +        try {
> +            Method valueOfMethod = type.getMethod(ENUM_VALUE_OF_METHOD_NAME, String.class);
> +            if (valueOfMethod != null) {
> +                String valueString = ((String) value).toUpperCase(Locale.ENGLISH);
> +                    coercedValue = (T) valueOfMethod.invoke(null, valueString);
> +            }
> +        }
> +        // Nothing to be gained by handling the getMethod() & invoke()
> +        // Exceptions separately
> +        catch (IllegalAccessException e) {
> +            throwCoerceEnumException(value, type, e);

In general, we don't define "thrower" methods. You could instead define a constant for your exception message and re-use that in each catch block. Later, when we (hopefully) get multi-catch in JDK 7, we can consolidate blocks like this.

Greg