Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow enum members to define functions #22281

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -201,7 +201,7 @@ public static ValueReaderWriter<?> readerWriterFor(CompactStreamSerializer compa
= createReaderWriterForArray(compactStreamSerializer, clazz, componentTypes.element2, fieldName + "!values");
return new HashMapReaderWriter(fieldName, componentTypes.element1,
componentTypes.element2, keyReaderWriter, valueReaderWriter);
} else if (type.isEnum()) {
} else if (Enum.class.isAssignableFrom(type)) {
return new EnumReaderWriter(fieldName, (Class<? extends Enum>) type);
}

Expand All @@ -219,7 +219,7 @@ public static ValueReaderWriter<?> readerWriterFor(CompactStreamSerializer compa
private static ValueReaderWriter createReaderWriterForArray(CompactStreamSerializer compactStreamSerializer,
Class<?> clazz, Class<?> componentType,
String fieldName) {
if (componentType.isEnum()) {
if (Enum.class.isAssignableFrom(componentType)) {
return new EnumArrayReaderWriter(fieldName, (Class<? extends Enum>) componentType);
}

Expand Down
Expand Up @@ -122,7 +122,7 @@ private Comparable sanitizeScalar(Object input) {
Comparable value = (Comparable) input;
if (value == null) {
value = NULL;
} else if (value.getClass().isEnum()) {
} else if (Enum.class.isAssignableFrom(value.getClass())) {
value = TypeConverters.ENUM_CONVERTER.convert(value);
}
return canonicalizeScalarForStorage(value);
Expand Down
Expand Up @@ -103,7 +103,7 @@ public static long estimateValueCost(Object value) {
return DATE_COST;
}

if (clazz.isEnum()) {
if (Enum.class.isAssignableFrom(clazz)) {
// enum values are shared, so they don't cost anything
return 0;
}
Expand Down
Expand Up @@ -89,7 +89,7 @@ public static AttributeType getAttributeType(Class klass) {
return AttributeType.SQL_LOCAL_DATE_TIME;
} else if (klass == OffsetDateTime.class) {
return AttributeType.SQL_OFFSET_DATE_TIME;
} else if (klass.isEnum()) {
} else if (Enum.class.isAssignableFrom(klass)) {
return AttributeType.ENUM;
} else if (klass == UUID.class) {
return AttributeType.UUID;
Expand Down
Expand Up @@ -157,7 +157,7 @@ private Object readAttributeValue(Map.Entry entry) {
}

Object convertEnumValue(Object attributeValue) {
if (attributeValue != null && attributeValue.getClass().isEnum()) {
if (attributeValue != null && Enum.class.isAssignableFrom(attributeValue.getClass())) {
attributeValue = attributeValue.toString();
}
return attributeValue;
Expand Down
Expand Up @@ -40,12 +40,29 @@ public class ComplexTestDataStructure {
private ComplexTestDataStructure() {
}

enum Health {
DEAD {
@Override
public boolean isAlive() {
return false;
}
},

SICK,
SPLENDID;

public boolean isAlive() {
return true;
}
}

public static class Person implements Serializable, PortableAware {
String name;
List<Limb> limbs_list = new ArrayList<Limb>();
Limb[] limbs_array;
Limb firstLimb;
Limb secondLimb;
Health health;

transient PersonPortable portable;

Expand All @@ -57,6 +74,10 @@ public Limb getFirstLimb() {
return firstLimb;
}

public Health getHealth() {
return health;
}

@Override
public boolean equals(Object o) {
if (!(o instanceof Person)) {
Expand Down Expand Up @@ -85,6 +106,7 @@ public static class PersonPortable implements Serializable, Portable {
Portable[] limbs_portable;
LimbPortable firstLimb;
LimbPortable secondLimb;
Health health;

@Override
public boolean equals(Object o) {
Expand Down Expand Up @@ -116,6 +138,7 @@ public void writePortable(PortableWriter writer) throws IOException {
writer.writePortableArray("limbs_portable", limbs_portable);
writer.writePortable("firstLimb", firstLimb);
writer.writePortable("secondLimb", secondLimb);
writer.writeInt("health", health == null ? -1 : health.ordinal());
}

@Override
Expand All @@ -124,6 +147,10 @@ public void readPortable(PortableReader reader) throws IOException {
limbs_portable = reader.readPortableArray("limbs_portable");
firstLimb = reader.readPortable("firstLimb");
secondLimb = reader.readPortable("secondLimb");
int healthOrdinal = reader.readInt("health");
if (healthOrdinal > 0) {
health = Health.values()[healthOrdinal];
}
}
}

Expand Down Expand Up @@ -353,8 +380,13 @@ private static void setupLimbPortable(Limb limb) {
}

public static Person person(String name, Limb... limbs) {
return person(name, null, limbs);
}

public static Person person(String name, Health health, Limb... limbs) {
Person person = new Person();
person.name = name;
person.health = health;
if (limbs.length > 0) {
person.limbs_list.addAll(Arrays.asList(limbs));
} else {
Expand Down
Expand Up @@ -85,7 +85,7 @@ public class ExtractionInCollectionSpecTest extends AbstractExtractionTest {
private static final Person HUNT_NULL_LIMB = person("Hunt");

private static final Person HUNT_NULL_FIRST = person("Hunt",
null, limb("left", tattoos(null, "cross"), null, finger("thumbie"))
(ComplexTestDataStructure.Health) null, null, limb("left", tattoos(null, "cross"), null, finger("thumbie"))
);

private static final Person HUNT_PRIMITIVE_NULL_FIRST = person("Hunt",
Expand Down
Expand Up @@ -59,12 +59,12 @@
@Category({QuickTest.class, ParallelJVMTest.class})
public class ExtractionInSingleValueSpecTest extends AbstractExtractionTest {

private static final Person BOND = person("Bond",
private static final Person BOND = person("Bond", ComplexTestDataStructure.Health.SICK,
limb("left-hand", tattoos(), finger("thumb"), finger(null)),
limb("right-hand", tattoos("knife"), finger("middle"), finger("index"))
);

private static final Person KRUEGER = person("Krueger",
private static final Person KRUEGER = person("Krueger", ComplexTestDataStructure.Health.DEAD,
limb("linke-hand", tattoos("bratwurst"), finger("Zeigefinger"), finger("Mittelfinger")),
limb("rechte-hand", tattoos(), finger("Ringfinger"), finger("Daumen"))
);
Expand Down Expand Up @@ -135,6 +135,13 @@ public void nestedAttribute_firstIsNull_comparedToNull() {
Expected.of(HUNT_WITH_NULLS));
}

@Test
public void enumWithMembers() {
execute(Input.of(BOND, KRUEGER),
Query.of(Predicates.equal("health", ComplexTestDataStructure.Health.DEAD), mv),
Expected.of(KRUEGER));
}

@Parameterized.Parameters(name = "{index}: {0}, {1}, {2}")
public static Collection<Object[]> parametrisationData() {
return axes(
Expand Down
Expand Up @@ -71,7 +71,7 @@ public void setUp() throws NoSuchMethodException {
hand = new Limb("hand", whiteNail, blackNail);

unnamedLimb = new Limb(null);
body = new Body("bodyName", leg, hand, unnamedLimb);
body = new Body("bodyName", Health.SPLENDID, leg, hand, unnamedLimb);
}

@Test(expected = IllegalArgumentException.class)
Expand All @@ -97,6 +97,17 @@ public void constructor_whenModifierIsPositionAndMethodReturnTypeIsCollection_th
new MethodGetter(null, limbCollectionMethod, "[0]", null);
}

@Test
public void getValue_whenFieldIsEnum()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the motivation for this test? It is not failing with current master and it does not test MethodGetter with enum elements, but maybe I 'm missing something?

throws Exception {
MethodGetter limbGetter = new MethodGetter(null, limbArrayMethod, "[any]", null);
MethodGetter nailGetter = new MethodGetter(limbGetter, nailArrayMethod, "[any]", null);

MultiResult result = (MultiResult) nailGetter.getValue(body);

assertContainsInAnyOrder(result, whiteNail, blackNail, redNail, greenNail, null);
}

@Test
public void getValue_whenModifierOnArrayIsStar_thenReturnMultiValueResultWithAllItems() throws Exception {
MethodGetter getter = new MethodGetter(null, limbArrayMethod, "[any]", null);
Expand Down Expand Up @@ -270,13 +281,23 @@ private void assertContainsInAnyOrder(MultiResult multiResult, Object... items)
}
}

enum Health {
SICK,
SPLENDID
}

@SuppressWarnings("unused")
static class Body {
String name;
Limb[] limbArray;
Collection<Limb> limbCollection;

Health health;

Body(String name, Limb... limbs) {
this(name, Health.SPLENDID, limbs);
}
Body(String name, Health health, Limb... limbs) {
this.name = name;
this.limbCollection = Arrays.asList(limbs);
this.limbArray = limbs;
Expand Down
Expand Up @@ -135,7 +135,7 @@ public static ProxyPolicy shouldProxy(Class<?> delegateClass, Class<?>[] ifaces)
if (DELEGATION_WHITE_LIST.contains(className)) {
return RETURN_SAME;
}
if (NO_PROXYING_WHITELIST.containsKey(className) || delegateClass.isEnum()) {
if (NO_PROXYING_WHITELIST.containsKey(className) || Enum.class.isAssignableFrom(delegateClass)) {
return ProxyPolicy.NO_PROXY;
}
if (SUBCLASS_PROXYING_WHITELIST.contains(className) || ifaces.length == 0) {
Expand Down Expand Up @@ -297,7 +297,7 @@ private static Object construct(Class<?> clazz, Object delegate) {
} catch (Exception e) {
throw new IllegalStateException(e);
}
} else if (input.isEnum()) {
} else if (Enum.class.isAssignableFrom(input)) {
return new EnumConstructor(input);
}
throw new UnsupportedOperationException("Cannot construct target object for target " + input
Expand Down
Expand Up @@ -102,7 +102,7 @@ static Object cloneConfig(Object thisConfigObject, ClassLoader classloader) thro
otherList.add(otherItem);
}
updateConfig(setter, otherConfigObject, otherList);
} else if (returnType.isEnum()) {
} else if (Enum.class.isAssignableFrom(returnType.getClass())) {
Enum thisSubConfigObject = (Enum) method.invoke(thisConfigObject, null);
Class otherEnumClass = classloader.loadClass(thisSubConfigObject.getClass().getName());
Object otherEnumValue = Enum.valueOf(otherEnumClass, thisSubConfigObject.name());
Expand Down
19 changes: 13 additions & 6 deletions hazelcast/src/test/java/example/serialization/HiringStatus.java
Expand Up @@ -18,12 +18,19 @@

public enum HiringStatus {

HIRING("Hiring"),
NOT_HIRING("Not hiring");
HIRING {
@Override
public String getHumanReadable() {
return "Hiring";
}
},
NOT_HIRING() {
@Override
public String getHumanReadable() {
return "Not hiring";
}
};

private final String humanReadable;
public abstract String getHumanReadable();

HiringStatus(String humanReadable) {
this.humanReadable = humanReadable;
}
}