0

I'm trying to use an enum to wrap certain error codes in my application.

public enum ErrorStatus
{
    PAGE_NOT_FOUND("http 404", "lorem ipsum")
    private final String code;
    private final String description;
        private ErrorStatus(String code, String description)
            {
            this.code = code;
            this.description = description;
        }
    public String getDescription()
    {
        return description;
    }
}

When I receive an error, it is a String with the code e.g. "http 404".

"http 404" (or any other error code) doesn't seem to be a clear and readable enum name:

http_404("page not found", "lorem ipsum")

I found the valueOf() and name() methods can't be overridden, and I want to prevent other from mistakenly using the valueOf() on the String value instead of a custom implementation with a different name.

What is the cleanest way to map the enum from and to that String value?

2 Answers 2

2

Edit: After reading your comment I think you are looking for something like this.

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


public enum ErrorStatus {

    PAGE_NOT_FOUND("404", "Description for error 404");

    private static final HashMap<String, ErrorStatus> ERRORS_BY_CODE;
    private static final HashMap<String, ErrorStatus> ERRORS_BY_DESCR;
    static {
        ERRORS_BY_CODE = new HashMap<String, ErrorStatus>();
        ERRORS_BY_CODE.put("404", PAGE_NOT_FOUND);
        ERRORS_BY_DESCR = new HashMap<String, ErrorStatus>();
        ERRORS_BY_DESCR.put("Description for error 404", PAGE_NOT_FOUND);
    }

So the most important thing here is the use of HashMaps, much like ZouZou suggested. If you want to efficiently look for a description by a givwn code you'll need a map for that, if you want to efficiently look for a code by a given description you'll need a map for that too.

If you have a string like "404" or "500" and want to get the corresponding description you can use

public static ErrorStatus getErrorByCode(String code) {
    return ERRORS_BY_CODE.get(code);
}

If you have the description like "Description for error 404" and want to get the corresponding error code you can use

public static ErrorStatus getErrorByDescr(String descr) {
    return ERRORS_BY_DESCR.get(descr);
}

If you only have a string containing the description it gets a bit nasty. This is not the most efficient way to do it but assuming you wont have that many error codes it's all right. So if we have a string like "Here is the description of the page not found error 'Description for error 404'" then you can use

public static ErrorStatus getErrorByString(String str) {
    for (Entry<String, ErrorStatus> entry : ERRORS_BY_DESCR.entrySet()){
        if (str.contains(entry.getKey())) {
            return entry.getValue();
        }
    }
    return null;
}

Be carefull about the last method as it returns null if nothing was found and also only gives only the first error object it succeeds (while there can be more than one error description in a code).

Sign up to request clarification or add additional context in comments.

1 Comment

I'm sorry, It might have been a bit confusing that I omitted part of my enum, the fike already looked quite much like the solution you suggested. My problem is not to retrieve the code or description value of the enum, but I am searching for a 'clean' way to convert a string containing the code to the corresponding enum value and back.
1

You can use a map to hold the mapping code-enum.

enum ErrorStatus {    

    PAGE_NOT_FOUND("404", "lorem ipsum");

    private static class Holder {
        private static Map<String, ErrorStatus> MAP = new HashMap<>();
    }

    private String code;
    private String description;

    private ErrorStatus(String code, String description) {
        this.code = code;
        this.description = description;
        Holder.MAP.put(code, this);
    }

    public static ErrorStatus fromCode(String code) {
        ErrorStatus error =  Holder.MAP.get(code);
        if(error == null) {
            throw new IllegalArgumentException();
        }
        return error;
    }
}

and then call it like:

ErrorStatus status = ErrorStatus.fromCode("404"); //PAGE_NOT_FOUND

The trick is that the class loader initializes the static inner class before the enum class so that you can use the map in the enum constructor, which implies minimal code.

For mapping the enum to its code, you can just add a method that will give the code value:

public String code() { return this.code; }

There seems no way to prevent valueof or override it.

No it's right you cannot. But you can create a class with public static final fields.

class ErrorStatus {    

    public static final ErrorStatus PAGE_NOT_FOUND = new ErrorStatus("404", "lorem ipsum");
    //override toString, hashCode and equals

    //same code as in the enum

}

6 Comments

@downvoter Can you explain what's wrong with my answer?
I didn't downvote you, but I'd imagine its because this doesn't compile.
@Obicere Ah yes sorry I mixed up the holder class and enum declaration, I didn't pay intention when writing the answer. Well the principle was there. Thanks for pointing this out.
I didn't downvote either and there is nothing wrong with your answer. Here, have my upvote.
I could also use the following method instead of an additional list: for(ErrorStatus status: this.values()){ if(status.getCode().equals(code)) return status; } The issue is that the following programmer could try to use valueOf (instead of fromCode()) in my enum and fail doing so. There seems no way to prevent valueof or override it.
|

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.