2

I have a Java question about the best method to work with the following enum file that has been provided to me.

public enum Foo{

    PLANE(1, "Plane", "plane"),
    CASTLE(2, "Castle", "castle"),
    FEILD(3, "Feild", "field"),
    ROAD(4, "Road", new String[] {"road", "pavement"});
}

There are roughly 100ish entries of the above formats

/**
* Stores a map of the names for fast access. Stores a map of the IDs for fast access.
*/
    private static final Map<Integer,BlockType> ids = new HashMap<Integer,BlockType>();

    private static final Map<String,BlockType> lookup = new HashMap<String,BlockType>();

    private final int id;
    private final String name;
    private final String[] lookupKeys;

    static {
        for(Foo type : EnumSet.allOf(Foo.class)) {
            ids.put(type.id, type);
            for (String key : type.lookupKeys) {
                lookup.put(key, type);
            }
        }
    }


    /**
* Construct the type.
*
* @param id
* @param name
*/
    Foo(int id, String name, String lookupKey) {
        this.id = id;
        this.name = name;
        this.lookupKeys = new String[]{lookupKey};
    }

    /**
* Construct the type.
*
* @param id
* @param name
*/
    Foo(int id, String name, String[] lookupKeys) {
        this.id = id;
        this.name = name;
        this.lookupKeys = lookupKeys;
    }

    /**
* Return type from ID. May return null.
*
* @param id
* @return
*/
    public static Foo fromID(int id) {
        return ids.get(id);
    }

    /**
* Return type from name. May return null.
*
* @param name
* @return
*/
    public static Foo lookup(String name) {
        return lookup.get(name.toLowerCase());
    }

    /**
* Get block numeric ID.
*
* @return
*/
    public int getID() {
        return id;
    }

    /**
* Get user-friendly name.
*
* @return
*/
    public String getName() {
        return name;
    }   

So what I am trying to do with this enum is the following: A user issues a command, for example: /bounce 1

The program recognizes bounce as a command and looks for the following argument. Since 1 follows the command it now checks that 1 is a valid id# in the enum. If it is it performs the command.

A user issues a command for example 2 in the following form: /bounce plane. This time it checks to see if the string is a valid string name in the enum and if it is grab the id# associated with it to perform the command.

How can I check for these criteria that either the id or one of the string id's exist and always return the id# for later usage. Any help would be appreciated.

It should also be noted that this enum file is it's own independent class file being called from the main.

Thanks to all who helped me get on the right track I have awarded Wolfcastle the correct answer, here was what I got to work for me but I am still open to any critiques on logic or performance flaws with my method.

String s = null;
        try {
            s = in.readLine();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            id = Integer.parseInt(s);
        } catch (NumberFormatException nfe) {

        }
        if (BlockType.lookup(s) != null
                || BlockType.fromID(id) != null) {
            if (BlockType.lookup(s)!= null) {
                blockname = BlockType.lookup(s).getName();
                blockid = BlockType.lookup(s).getID();
            } else {
                blockname = BlockType.fromID(id).getName();
                blockid = BlockType.fromID(id).getID();
            }
        }
4
  • It's not clear to me what your problem is. Your code looks like it should do what you want it to. Can you expand on the actual problem you are having? Commented Apr 20, 2011 at 19:07
  • This is a file that is provided to me via a collaborative team for making plugins. My package uses the enum in this file to validate that the "item" a user attempts to create actually exists in the enum either via the items id# or it's string name. If the user sends the command using string name I need to get the item id based on the string name so that the item can then be created. (hopefully this makes more sense) Commented Apr 20, 2011 at 20:36
  • Is BlockType the same as Foo? Commented Apr 20, 2011 at 21:13
  • Yes Paŭlo BlockType is the actual enum I'm using. Commented Apr 20, 2011 at 21:28

2 Answers 2

2

So if I understand you correctly, the code you have posted is not your code, but rather code you must use, and you are wondering how you can use it.

    String param = getParam(); // get the '1' or 'plane' string from your input
    BlockType type = null;
    try {
        // Check for an integer
        int id = Integer.parseInt(param);
        type = BlockType.getFromId(id);
    } catch( NumberFormatException e ) {
        // Okay, not an integer, check the lookup value
        type = BlockType.lookup(param);
    }

    if( type != null ) {
                int blockid = type.getID();
                String blockname = type.getName();
                // continue on
    } else {
    // else the input parameter was invalid and we can't get a BlockType for it
    // return some kind of error
    }
Sign up to request clarification or add additional context in comments.

6 Comments

Correct Wolfcastle here is what I was about to attempt let me know your opinions please: try { id = Integer.parseInt(s); }catch (NumberFormatException nfe) { } if(BlockType.lookup(s).getName() != null || BlockType.fromID(id) != null) { if(BlockType.lookup(s).getName() != null) { String blockname = BlockType.lookup(s).getName(); int blockid = BlockType.lookup(s).getID(); }else{ String blockname = BlockType.fromID(id).getName(); int blockid = BlockType.fromID(id).getID(); } }
@JDD: please don't put code in a comment, it gets unreadable. Add it to the question instead (it has an edit-link).
Paulo is right, try to put it in the question. What you did write, however, is wrong, as you are trying to check if the getName is null from the result of calling lookup. This will result in a NPE for invalid input. The javadoc of the BlockType class clearly says that the lookup method can return null. This is the check you need to do (and what my example does). Assuming the enums are defined correctly, getName() will NEVER return null, so don't bother checking it.
Ya i was going to but the edit time frame had already passed =P sorry about that guys.
@JDD have another look at my answer, I tweaked it a bit based on your first comment.
|
1

In this case you could just check if the returned value is null. Or what exactly do you want to check?

Also note that you don't need the EnumSet:

static {
    for(Foo type : values()) {
        ids.put(type.id, type);
        for (String key : type.lookupKeys) {
            lookup.put(key, type);
        }
    }
}

3 Comments

maybe I am simply confused but I was told that if I returned null I would get a Null Pointer Exception that would crash my plugin? As for the part you said that I don't need, you are correct however several plugins are accessing this file. What I am wanting to check exactly is... user sends /create 1 or /create plane the program should check to make sure that 1 is a valid id or that plane is a valid string name attached to an id and then return to us that id.
As I said, either check in the client code that the returned value != null (which is safe here, as your Map will never contain null values), or provide a contains/isSupportedId/isSupportedName method, which calls the contains method of Map. I didn't get the plugin & NPE part of your comment. Maybe you could provide a small sample which shows the problem?
The problem that arises is that what I am writing accepts a user input and then checks if the id / string the user entered is in the enum. If it's not in the enum it can return an npe which would then crash the program but I got it all figured out and working correctly using the code that was added to the bottom of my initial post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.