Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2005

Tip: Looking for answers? Try searching our database.

enum aliases

Thread view: 
Roedy Green - 26 Jun 2005 23:21 GMT
IT would be nice if there were an easy way to have both valueOf and
toString aliases for enums.

Why?

To allow you to use reserved words like true, false, default, null as
your enum string constants.

to allow additional variants on input e.g. for "yes" also allow "true"
"t" "f".

To change the way the enum displays e.g. to change the language. to
change default/usual to whatever the default value actually is.

Any ideas on how to implement that cleanly?

Signature

Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes

Lasse Reichstein Nielsen - 27 Jun 2005 01:02 GMT
> IT would be nice if there were an easy way to have both valueOf and
> toString aliases for enums.

> Why?
>
> To allow you to use reserved words like true, false, default, null as
> your enum string constants.

You can overwrite toString if you want to. There can obviosuly only be
one default string representation, so if you want both the enum name
and its alias, you need two functions, so just write your own myToString().

> to allow additional variants on input e.g. for "yes" also allow "true"
> "t" "f".

The valueOf method is implicitly defined on all enum classes, and you
are not allowed to overwrite it. But then, you can just create your
own.

> To change the way the enum displays e.g. to change the language. to
> change default/usual to whatever the default value actually is.

You should not depend on the name of the enum constant for its
display.  If you need to display it in a way that might change, then
it is a display concern, and should be kept closer to the display
code than to the enum itself. I would just make a map from enum
name to presentation.

What is a default in this scenarios?

Anyway:
---
public enum EnumTest {
  TEST("test","trial","query"),
  SUCCESS("success","yes","true"),
  FAILURE("failure","fail","no","false");

  private static Map<String,EnumTest> aliasMap;

  private final String defaultName;

  EnumTest(String... aliases) {
     if (aliasMap == null) {
        aliasMap = new HashMap<String,EnumTest>();
     }
     for (String alias : aliases) {
        aliasMap.put(alias, this);
     }
     if (aliases.length > 0) {
        defaultName = aliases[0];
     } else {
        defaultName = name();
     }
  }

  static EnumTest valueOfAlias(String alias) {
     EnumTest value = aliasMap.get(alias);  
     if (value == null) {
       throw new IllegalArgumentException(alias + " not an alias");
     }
     return value;
  }

  public String toString() {
     return defaultName;
  }
}
---

I think that qualifies as an "easy way" :)
/L
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Roedy Green - 28 Jun 2005 07:11 GMT
>         aliasMap.put(alias, this);
then will generate an errormessage

illegal reference to static field from initializer

I don't understand why.

import java.util.HashMap;
import java.util.Map;

/**
 * enum with aliases for string input to valueOf
 * @author Roedy Green, added comments.
 * based on posted code by Lasse Reichstein Nielsen lrn@hotpop.com
 */

public enum Outcome {
  SUCCESS( "success", "yes", "true" ),
  FAILURE( "failure", "fail", "no", "false" ),
  UNDECIDED( "undecided", "maybe" );

  /**
   * maps from alias name to matching enum constant
   */
  private static Map<String, Outcome> aliasMap = new
HashMap<String,Outcome>();

  /**
   *the preferred alias to use as the canonical name
   */
  private final String defaultName;

  /**
   * constructor for an enum constant
   * @param aliases takes String[] specified as a variable length
list of strings
   *                representing alternate input values for the
aliases.
   */
  Outcome( String... aliases )
     {

     for ( String alias : aliases )
        {
        aliasMap.put( alias, this );
        }
     if ( aliases.length > 0 )
        {
        defaultName = aliases[0];
        }
     else
        {
        // allow some enum constants to have no aliases, work as
normal enum constants
        defaultName = name();
        }
     }

  /**
   * convert string to enum constant
   * @param alias string representing one of the aliases of one of
the enum constants.
   * @returns enum constant matching String.
   * @throws IllegalArgumentExeption if alias is not a legal one.
   */
  static Outcome valueOfAlias( String alias )
     {
     Outcome value = aliasMap.get( alias );
     if ( value == null )
        {
        throw new IllegalArgumentException( alias + " not a legal
Outcome alias" );
        }
     return value;
     }

  /**
   * The canonical name of this enum constant/variable.
   */
  public String toString()
     {
     return defaultName;
     }

  private static final boolean DEBUGGING = true;

  /**
   * test harness
   *
   * @param args not used
   */
  public static void main ( String[] args )
     {
     if ( DEBUGGING )
        {
        Outcome o = Outcome.valueOfAlias( "no" );
        System.out.println( o ); // prints "failure"
        }
     }

Signature

Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes

Lasse Reichstein Nielsen - 28 Jun 2005 20:17 GMT
>>         aliasMap.put(alias, this);
> then will generate an errormessage
>
> illegal reference to static field from initializer

The error message I get from your code is:
---
java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
    at Outcome.<init>(Outcome.java:41)
    at Outcome.<clinit>(Outcome.java:17)
Exception in thread "main"
---

> I don't understand why.

You are initializing the static variable "aliasMap" *after* creating
the instances of Outcome. Remember that enum values are really static
final fields, and they are assigned earlier in the static
initialization than other static fields. That means that the
"aliasMap" field is null when the constructors try to put values into
the map.

If you compare it to my original code, I initialized the map the first
time I needed it, to make sure it was not null. That was deliberate :)

/L
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Roedy Green - 30 Jun 2005 04:05 GMT
>>>         aliasMap.put(alias, this);
>> then will generate an errormessage
[quoted text clipped - 23 lines]
>
>/L

when I do it your way, I get even more of those static initialiser
errors.

You are doing things in the logical order, but Java does not trust
you.

Signature

Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes

Roedy Green - 30 Jun 2005 16:09 GMT
>when I do it your way, I get even more of those static initialiser
>errors.

here is my code that works, but is not very smart. It just does a
linear search.
package com.mindprod.pricelist;

/**
* constants for Application categories
*/
public enum AppCat {

  /* short name, description, aliases */

  APPLET( "Applet", "Java Applet", "applet" ),
  APPLICATION( "application", "Java application", "application"),
  DOCUMENTATION( "documentation", "documentation" , "documentation"
),
  HYBRID( "hybrid", "Java Applet that can also be run as an
application", "hybrid" ),
  JWS( "Java Web Start" ,"Java Web Start", "jws", "weblet",
"webstart", "jaws" ),
  LIBRARY( "Class" , "Class library", "class", "classes", "library"
),
  SERVLET( "servlet", "Java Servlet", "servlet" ),
  UTILITY( "Utility", "non-Java Utility", "utility" );

  /**
   * constructor for an enum constant
   * @param human output description.
   * @param ShorName for display
   * @param description long description
   * @param aliases other names for string input
   */
  AppCat( String shortName, String description, String... aliases )
     {
     this.shortName = shortName;
     this.description = description;
     this.aliases = aliases;
     }

 private String shortName;

 private String description;

  /**
   * cannot use String... here, only in parm list
   * alterate input names for the alias
   */
 private String[] aliases;

  public String getShortName()
     {
     return shortName;
     }

  public String getDescription()
     {
     return description;
     }

  public String[] getAliases()
     {
     return aliases;
     }
  // you may not redefine valueOf since has been covertly defined in
this class

  public static AppCat valueOfAlias ( String s )
     {
     try
        {
        return valueOf( AppCat.class, s );
        }
     catch ( IllegalArgumentException e )
        {
        // usual method failed, try looking up alias
        // This seems long winded, why no HashSet?
        // Because Java won't let me access a static common
        // lookup in the enum constructors.
        for ( AppCat candidateEnum : AppCat.values() )
           {

           for ( String candidateString : candidateEnum.getAliases()
)
              {
              if ( candidateString.equalsIgnoreCase( s ) )
                 {
                 return candidateEnum;
                 }
              }
           }
        // fell out the bottom of search over all enums and aliases
        // give up

        throw new IllegalArgumentException( "unknown Application
Category: " + s);

        }

     }
}

Signature

Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.