0

I am trying to create a scenario where by an enum constant in enum class A has associated sub enum class B and enum class C containing their own constants. The constants in enum class B and enum class C group subsets of constants from enum class D. Below is a basically what I am trying to achieve:

enum A {
    CONST_1 ("const_1", B), // B is the associated enum
    CONST_2 ("const_2", C); // C in the associated enum

    private final String strVal;
    private final Enum associatedEnum;

    private A (String strVal, Enum associatedEnum) {
        this.strVal = strVal;
        this.associatedEnum = associatedEnum;
    }

    public Enum getAssociatedEnum() {
        return this.associatedEnum;
    }

    public String toString() {
        return this.strVal;
    }       

    // Associated Enum contained subset of grouped constants
    enum B {
        CONST_3 (D.CONST_7.toString()),
        CONST_4 (D.CONST_8.toString()); 

        private final String strVal;

        private B (String strVal) {
            this.strVal = strVal;
        }

        public String toString() {
            return this.strVal;
        }       
    }

    // Associated Enum contained subset of grouped constants
    enum C {
        CONST_5 (D.CONST_9.toString()),
        CONST_6 (D.CONST_10.toString()); 

        private final String strVal;

        private C (String strVal) {
            this.strVal = strVal;
        }

        public String toString() {
            return this.strVal;
        }              
    }
}

// Separate Enum containing all ungrouped constants
enum D {
    CONST_7 ("const_7"),
    CONST_8 ("const_8");
    CONST_9 ("const_9"),
    CONST_10 ("const_10");

    private final String strVal;

    private D (String strVal) {
        this.strVal = strVal;
    }

    public String toString() {
        return this.strVal;
    }    
}

Obviously this syntax doesn't work OOTB because you cannot pass classes in Java this way. But can anyone suggest a way in which I could achieve this?

I am hoping to use it to validate static structured groupings in a client-side application.

starblue
  • 55,348
  • 14
  • 97
  • 151
travega
  • 8,284
  • 16
  • 63
  • 91

3 Answers3

3

This should hopefully do what you want. I've included an example usage where it'll list the sub enum type values.

package a.b.c;


public class EnumsTest {

  public enum A {
    A1( B.class ),
    A2( C.class );

    private final Class<? extends Enum<?>> enumClazz;

    A( final Class<? extends Enum<?>> enumClazz  ) {
      this.enumClazz = enumClazz;
    }

    public Enum<?>[] getSubEnumConstants() {
      return enumClazz.getEnumConstants();
    }

   /**
    * @param value
    * @return Never null
    * @throws IllegalArgumentException To be consistent with Enum.valueOf()
    */
   public <T> Enum<?> valueOfSubEnum( final String value ) throws IllegalArgumentException {
     for( Enum<?> enumInstance : getSubEnumConstants() ) {
       if( enumInstance.name().equals( value ) ) {
         return enumInstance;
       }
     }
     throw new IllegalArgumentException( "valueOf for " + enumClazz.getName() + " could not be resoled with the value of " + value );
   }

  }

  public enum B {
    B1,
    B2;
  }

  public enum C {
    C1,
    C2;
  }

  public static void main( String[] args ) {

    for( A a : A.values() ) {
      for( Enum<?> enumInstance : a.getSubEnumConstants() ) {
        System.out.println( a.name() + ":" +  enumInstance.name() );  
      }
    }
    Enum<?> valueOfSubEnum = A.A1.valueOfSubEnum( "B2" );
    System.out.println( valueOfSubEnum.name() );
  }
}

Note: If you want to lock the subtypes down to a specific set, you can make them implement an interface.

Roadkillnz
  • 773
  • 1
  • 6
  • 14
  • Forgot to add.. this is the output... A1:B1 A1:B2 A2:C1 A2:C2 – Roadkillnz Jul 30 '12 at 23:59
  • This is very close to what I'm trying to do... Ultimately I would like to be able to varify a value in a sub Enum something like this: A.A1.getEnumClazz().valueOf("B1"). However the `.valueOf()` method is not accessible even though it extends Enum>... Is there a way around that? – travega Jul 31 '12 at 02:36
  • I've updated the example which has a crude valueOf like method. You'd probably want to look at the Enum.valueOf() method to ensure it's consistent with its behaviour. – Roadkillnz Jul 31 '12 at 04:06
0

You can't declare a enum A with constructor private B (String strVal, Enum associatedEnum). You can declare others enum inside each other, but not like this.

thiago.lenz
  • 399
  • 4
  • 11
0

This works for me, but I might have missed what you are trying to achieve:

public enum A {

  A1(B.B1),
  A2(C.C2);

  private final Enum<?> e;

  private A(Enum<?> e) {
    this.e = e;
  }

  static enum B {
    B1,
    B2;
  }

  static enum C {
    C1(D.D1.getId()),
    C2(D.D2.getId());

    private String id;

    private C(String id) {
      this.id = id;
    }

  }

}
enum D {
  D1("abc"),
  D2("def");

  private final String id;

  private D(String id) {
    this.id = id;
  }

  public String getId() {
    return id;
  }

}
Muel
  • 4,309
  • 1
  • 23
  • 32
  • 1
    If I understand the persons question correctly, they're after the type, not the specific instances within the type. If that is the requirement I've done something similar to yours but am returning all of the available instances within the type – Roadkillnz Jul 31 '12 at 00:06