简体   繁体   中英

How to pass class-name as arguments and invoke common static methods in GWT jsni?

I have lot of enum class and all having one common method. I want to invoke that common method and return dynamically using GWT jsni method.

Let say I have following enum classes in different packages.

package A;

enum WidgetType{

   TEXT_BOX("A"),SVG("B");

   String type;

   WidgetType(String type){
      this.type = type;
   }

   public static WidgetType getDescriptiveValue( String type ){
        for(WidgetType widgetType : WidgetType.values()){
            if(widgetType.type.equalsIgnoreCase(type) ) return widgetType;
        }
        return null;
  }
}
package B;

enum MessageType{

   INFO("I"),WARN("W"),ERROR("E");

   String type;

   MessageType(String type){
      this.type = type;
   }

   public static MessageType getDescriptiveValue( String type ){
        for(MessageType messageType : MessageType.values()){
            if(messageType.type.equalsIgnoreCase(type) ) return messageType;
        }
        return null;
  }
}

Somewhat I will get enum full qualified names in string like [A.WidgetType,B.MessageType].

Based on this value I want to invoke enum class getDescriptiveValue method using JSNI.

So How to achieve this in GWT jsni.

When I try to pass class name as arguments like below I am getting compile time error.

Approach 1:

native void enumValue(String enumClass,String value) /*-{
                console.log($entry(@enumClass::getDescriptiveValue(Ljava/lang/String;)(value)) );
            }-*/;

Approach 2:

native void enumValue(String enumClass,String value) /*-{
                console.log(@enumClass::getDescriptiveValue(Ljava/lang/String;)(value));
            }-*/;

I don't know is there any way to use Java Reflection in GWT client side?

Please suggest me how to achieve this?

Put simply, this will not work - the JSNI syntax for java types/members is only a way to write plain code which will be evaluated at compile time into the JS equivalent of the member you are describing. You cannot simply turn a string into a class literal.

Instead, depending on how many enums you may wish to support in this way, consider constructing a Map<String, Map<String, Object>> of the enum types and param types you are looking for. This will require either manual code to list each enum type, or code generation to do this for you, and has the added advantage of not including JSNI.

Consider a type like this, which requires that each Enum you give it implements some HasType interface, which ensures that all have a getType() method, so they can be reflected on in the same way.

public class EnumLookup {
  private final Map<String, Map<String, Object>> enumCache = new HashMap<>();

  /** Helper that you can call internally or externally to build up the cache */
  public <E extends HasType> void register(Class<E> type, E[] values) {
    Map<String, Object> values = enumCache.computeIfAbsent(type.toString(), classname -> new HashMap<>());
    for (E enumValue : values) {
      values.put(enumValue.getType().toLowerCase(), enumValue);
    }
  }
  /** And now the method you are trying to write */
  public <E extends HasType> void enumValue(String enumClass, String value) {
    // use of toLowerCase here and above ensures that type strings will match like
    // in your original java
    return (E) enumCache.get(enumClass).get(value.toLowerCase());
  }
}

and then populate the cache somewhere

EnumCache cache = new EnumCache();

cache.register(WidgetType.class, WidgetType.values());
cache.register(MessageType.class, MessageType.values());
//...

Another way would be for the map to contain a Function<String, Object> , and use that to point at the getDescriptiveValue via a method reference. Then the registration would look like this:

cache.register(WidgetType.class, WidgetType::getDescriptiveValue);
cache.register(MessageType.class, MessageType::getDescriptiveValue);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM