Thank you Marko,

I did pretty much the same yesterday, but I am only using one class for all my type 
safe enumeration classes.
It involves using a lot reflection so it may be very slow. Tell me what you think 
about this solution.

/**
 * The class EnumStringFieldHandler is a generic <code>FieldHandler</code> for
 * <i>type safe enumeration</i>.
 * This <i>type safe enumeration</i> class <b>must</b> have a <code>public String 
toString()</code> method.
 *
 * @alias EnumStringFieldHandler
 */
public class EnumStringFieldHandler extends AbstractFieldHandler
{
    /**
     * Returns the value of the field from the object. The object should have a method 
named
     * <code>"get" + getFieldDescriptor().getFieldName()</code>.<br>
     * <b>Example</b> : Field name = <code>identification</code>, method name = 
<code>getIdentification()</code>.
     * This getter should return the <i>typesafe enum</i> static instance.
     * @param o The object
     * @return The value of the field
     * @throws IllegalStateException The Java object has changed and is no longer 
supported by this handler,
     *                               or the handler is not compatible with the Java 
object
     */
    public Object getValue(final Object o) throws IllegalStateException
    {
        final FieldDescriptor fd = getFieldDescriptor();
        final String name = fd.getFieldName();
        final String methodName = "get".concat(name.substring(0, 
1).toUpperCase()).concat(name.substring(1,
                name.length()));

        try
        {
            final Method method = o.getClass().getMethod(methodName, new Class[]{});
            return (method.invoke(o, new Object[]{})).toString();
        }
        catch (NoSuchMethodException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Class " + o.getClass() + " must have 
method " + methodName);
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Method " + methodName + " from class " + 
o.getClass() + " must be public");
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Method " + methodName + " from class " + 
o.getClass() +
                                            " threw an exception");
        }
    }

    /**
     * Sets the value of the field on the object.
     * The object should have a field name <code>"_" + 
getFieldDescriptor().getFieldName()</code>.<br>
     * <b>Example</b> : Field name = <code>identification</code>, object field name = 
<code>_identification</code>.
     * @param o The object
     * @param o1 The new value
     * @throws IllegalStateException The Java object has changed and is no longer 
supported by this handler, or the
     *                               handler is not compatible with the Java object
     * @throws IllegalArgumentException
     */
    public void setValue(final Object o, final Object o1) throws 
IllegalStateException, IllegalArgumentException
    {
        final FieldDescriptor fd = getFieldDescriptor();
        String name = fd.getFieldName();
        final String methodName = "set".concat(name.substring(0, 
1).toUpperCase()).concat(name.substring(1,
                name.length()));
        name = "_".concat(name);

        Class fieldClass = null;
        try
        {
            fieldClass = o.getClass().getDeclaredField(name).getType();
            final Field[] fields = fieldClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++)
            {
                if (fields[i].get(null).toString().equals(o1.toString()))
                {
                    final Method method = o.getClass().getMethod(methodName, new 
Class[]{fields[i].getType()});
                    method.invoke(o, new Object[]{fields[i].get(null)});
                    break;
                }
            }
        }
        catch (NoSuchFieldException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Field " + name + " must exist in " + 
o.getClass());
        }
        catch (NoSuchMethodException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Method " + methodName + " must exist in " 
+ o.getClass());
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Class " + fieldClass.getClass() + " must 
be accessible");
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
            throw new IllegalStateException("Method " + methodName + " from class " + 
fieldClass.getClass() +
                                            " threw an exception");
        }
    }

    /**
     * Creates a new instance of the object described by this field.
     * @param o The object for which the field is created
     * @return A new instance of the field's value
     * @throws IllegalStateException This field is a simple type and cannot be 
instantiated
     */
    public Object newInstance(final Object o) throws IllegalStateException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Creates a new instance of the object described by this field.
     * @param o The object for which the field is created
     * @param objects The set of constructor arguments
     * @return A new instance of the field's value
     * @throws IllegalStateException This field is a simple type and cannot be 
instantiated
     */
    public Object newInstance(final Object o, final Object[] objects) throws 
IllegalStateException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Sets the value of the field to a default value.
     * Reference fields are set to null, primitive fields are set to their default 
value,
     * collection fields are emptied of all elements.
     * @param o The object
     * @throws IllegalStateException The Java object has changed and is no longer 
supported by this handler,
     *                               or the handler is not compatiale with the Java 
object
     * @throws IllegalArgumentException
     */
    public void resetValue(final Object o) throws IllegalStateException, 
IllegalArgumentException
    {
        throw new UnsupportedOperationException();
    }
}

-----Original Message-----
From: Marko Topolnik [mailto:[EMAIL PROTECTED]
Sent: 9 mars, 2004 08:16
To: [EMAIL PROTECTED]
Subject: Re: [castor-dev] typesafe enum in mapping file - how to?



Hi Carl, 

I have the same problem as you. I have worked out a solution, but it is
not very elegant. It involves writing a custom ...FieldHandler class for
each typesafe enum field and for each class where such a field occurs.

For each enumField of type EnumClass in your class MyClass, you write a
field handler class like this:

public class MyEnumFieldHandler extends EnumFieldHandler
{
  public Object getValue( Object object ) 
  {
    return ( (MyClass) object ).getEnumField();
  }

  public void setValue( Object object, Object value )
  {
    EnumClass enumValue = EnumClass.valueOf( (String) value );
    if ( enumValue != null )
      ( (MyClass) object ).setEnumField( enumValue );
    else
      throw new RuntimeException( "Invalid value '" + value + "'" );
  }
}


The base class EnumFieldHandler is derived from Castor's
AbstractFieldHandler and can be reused for all enum field handlers:


import org.exolab.castor.mapping.AbstractFieldHandler;

public abstract class EnumFieldHandler extends AbstractFieldHandler
{
  public abstract void setValue( Object object, Object value );

  public abstract Object getValue( Object object ); 

  
  public Object newInstance( Object parent ) 
  {
    throw new UnsupportedOperationException();
  }
  public Object newInstance( Object parent, Object[] args )
  {
    throw new UnsupportedOperationException();
  }
  public void resetValue( Object object ) 
  {
    throw new UnsupportedOperationException();
  }
}

In the mapping file, you specify:

<field name="enumField" type="EnumClass"
handler="MyEnumFieldHandler">...</field>


If anyone knows how to improve on this solution, I'd sure appreciate
their sharing it with this group!


Marko 

>-----Original Message-----
>From: Letourneau, Carl [mailto:[EMAIL PROTECTED] 
>Subject: Re: [castor-dev] typesafe enum in mapping file - how to?
>
>Is this possible to use a "type safe enum class" in a Mapping 
>file? It keeps giving me error because I don't have a public 
>default constructor on the class.

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

Reply via email to