4

My Enum original java code is:

public enum CarModel {
    NOMODEL("NOMODEL");
    X("X"),
    XS("XS"),
    XSI("XS-I"); //NOTE the special - character. Can't be declared XS-I
    XSI2("XS-I.2"); //NOTE the special . character. Can't be declared XS-I.2
    private final String carModel;
    CarModel(String carModel) { 
        this.carModel = carModel;
    }

    public String getCarModel() { return carModel; }

    public static CarModel fromString(String text) {
        if (text != null) {
            for (CarModel c : CarModel.values()) {
                if (text.equals(c.carModel)) {
                    return c;
                }
            }
        }
        return NOMODEL; //default
    }
}

Now if I use protobuf I get in the .proto file:

enum CarModel {
    NOMODEL = 0;
    X = 1;
    XS = 2;
    XSI = 3;
    XSI2 = 4;
}

from my earlier question I know I can call the enum generated by protoc and remove my own class (and thus avoid the duplicate value definitions) but I still need to define somewhere (In a wrapper class? wrapper enum class?) the alternate fromString() method that will return the right string per the enum. How do I do that?

EDIT: How do I implement the following:

String carModel = CarModel.XSI.toString(); This will return "XS-I"

and:

CarModel carModel = CarModel.fromString("XS-I.2");

2 Answers 2

11

You can accomplish this using Protobuf's "custom options".

import "google/protobuf/descriptor.proto";

option java_outer_classname = "MyProto";
// By default, the "outer classname" is based on the proto file name.
// I'm declaring it explicitly here because I use it in the example
// code below.  Note that even if you use the java_multiple_files
// option, you will need to use the outer classname in order to
// reference the extension since it is not declared in a class.

extend google.protobuf.EnumValueOptions {
  optional string car_name = 50000;
  // Be sure to read the docs about choosing the number here.
}

enum CarModel {
  NOMODEL = 0 [(car_name) = "NOMODEL"];
  X = 1 [(car_name) = "X"];
  XS = 2 [(car_name) = "XS"];
  XSI = 3 [(car_name) = "XS-I"];
  XSI2 = 4 [(car_name) = "XS-I.2"];
}

Now in Java you can do:

String name =
    CarModel.XSI.getValueDescriptor()
    .getOptions().getExtension(MyProto.carName);
assert name.equals("XS-I");

https://developers.google.com/protocol-buffers/docs/proto#options (Scroll down slightly to the section on custom options.)

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

6 Comments

I've tried your code and it seems the protoc doesn't create the getProto() method I need to call in order to translate the ValueDescriptor to Extension. Any Ideas ?
one more thing - when looking in the generated java code the only place where the "XS-I" and "XS-I.2" strings appear are in the last field that is defined as: "static {java.lang.String[] descriptorData = {" and basically holds my .proto source
Oops, sorry, the method is called toProto, not getProto. I'll edit my answer. Yes, the annotations all go into descriptorData. The code I gave actually fetches them out of there.
toProto indeed exists but still no getExtension... Any ideas?
Sorry, I forgot that extensions hang off the options proto, not the descriptor proto. So I guess you need getOptions() rather than toProto(). Updated example again.
|
-1
CarModel carmodel =  Enum.valueOf(CarModel.class, "XS")

or

CarModel carmodel =  CarModel.valueOf("XS");

1 Comment

I need the other direction: String model = CarModel.XSI.toString(); but to be able to tell it that XSI translates to "XS-I". And also the following CarModel carModel = CarModel.fromString("XS-I");

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.