I need check if enum element is into enum set - java

I'm new in java. I need check if enum element is into enum set.
in Delphi:
type
TWeekEnum = (weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday)
TWeekSetEnum = (weSaturday, weSunday)
if (weSunday in (TWeekSetEnum))
...
Java?

You can define the enum this way, and then also create your subsets as static methods on it.
public enum TWeekEnum {
weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday;
public static EnumSet<TWeekEnum> getWeekend() {
return EnumSet.of(weSaturday, weSunday);
}
public static EnumSet<TWeekEnum> getWeekDays() {
return EnumSet.complementOf(getWeekend());
}
}
Then you can check if it contains your selected item like this
TWeekEnum.getWeekend().contains(TWeekEnum.weTuesday)

If you prefer the elements to be in the calling code (and not inside the enum) - another solution is to add a normal method named in as follows: -
public enum TWeekEnum {
weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday;
public boolean in (TWeekEnum ... weekEnum) {
return Arrays.asList(types).contains(this);
}
}
This can be called anywhere in the codebase as follows: -
TWeekEnum weekEnum = TWeekEnum.weSaturday; // <---- If set dynamically, check for null
if (weekEnum.in(TWeekEnum.weSaturday, TWeekEnum.weSunday)) {
// do something
}
... this can look nicer (and read better) if enum values statically imported i.e.
import static com.foo.TWeekEnum.weSaturday;
import static com.foo.TWeekEnum.weSunday;
...
if (weekEnum.in(weSaturday, weSunday)) {
// do something
}

Related

Java class method with Class and Field as parameters

How can i create a method that accepts Class and Field as parameters? Like this:
List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");
public class SomeClassEntity {
Integer fieldOne = 10;
Double fieldThree = 0.123;
public Integer getFieldOne() {
return fieldOne;
}
public void setFieldOne(Integer fieldOne) {
this.fieldOne = fieldOne;
}
public Double getFieldThree() {
return fieldThree;
}
public void setFieldThree(Double fieldThree) {
this.fieldThree = fieldThree;
}
}
public class UsefulThingsService<T> {
public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
// there is some code
}
}
Want to have correct references on compile stage, not at runtime.
Update:
I need code that would look more convenient than this:
Field fieldOne = null;
try {
fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);
I apologize for the next clarification.
Update 2:
- The service compares the list with the previous list, reveals only the changed fields of objects (list items) and updates these fields in the objects in the original list.
- Currently i use annotation on entity's field that is actually ID of the entity and that ID is used to detect identically entities (old and new) when i need to update field of entity in source list.
- Service detect annotated field and use it for next update process.
- I want to refuse to use annotations and provide an Field directly in constructor of service. Or use something other that could establish a relationship between class and field on compilation stage.
Assuming that you want field access because you want to get and set the value, you’d need two functions:
public class UsefulThingsService<T> {
public <V> void makeUsefulThings(List<T> list, Function<T,V> get, BiConsumer<T,V> set) {
for(T object: list) {
V v = get.apply(object);
// there is some code
set.accept(object, v);
}
}
}
and
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldOne, SomeClassEntity::setFieldOne);
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldThree, SomeClassEntity::setFieldThree);
There are, however, some things open. E.g., how is this service supposed to do something useful with the field resp. property, without even knowing its actual type. In your example, both are subtypes of Number, so you could declare <V extends Number>, so the method knows how to extract numerical values, however, constructing an appropriate result object would require specifying another function argument.

No Enum constant found for type in java

I am using enum in java, Here is the enum
public enum AbuseSectionType{
MUSIC("Music"), DANCE("Dance"), SOLO("Solo"), ACT("Act")
private String displayString;
AbuseSectionType(String displayValue) {
this.displayString = displayValue;
}
#JsonValue
public String getDisplayString() {
return displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
}
I am trying to get value AbuseSectionType.valueOf("Music"). I am getting no enum constant and found no error. I am supposed to have value MUSIC.
The name() of an enum is the name specified when declaring it, MUSIC in your case.
If we read the javadoc for valueOf():
Returns the enum constant of the specified enum type with the
specified name.
valueOf() is using the name() of the enum. But what you want to achieve is different, so you cannot use this method. What you can do instead is to make your own method that finds the value from your own field (displayString).
Here's an example:
public static AbuseSectionType fromDisplayString(String displayString)
{
for(AbuseSectionType type : AbuseSectionType.values())
if(type.getDisplayString().equals(displayString)
return type;
return null; //not found
}
The default valuOf() method will only retrieve the respective enmum if the exact spelling of the enum-definition is used. In your case you have defined the enum MUSIC so in order to get that one you have to do it like this: AbuseSectionType.valueOf("MUSIC");
In order to achieve what you seem to want you have to implement a method in the enum class by yourself. For your example you could do somthing like this:
public AbuseSectionType resolve(String name) {
for(AbuseSectionType current : AbuseSectionType.values()) {
if(current.displayString.equals(name)) {
return current;
}
}
return null;
}
use AbuseSectionType.valueOf("MUSIC") pass the name of enum. See java docs regarding use of valueOf

Generalized method to get similar object attributes

I have an object which has a few arrays as fields. It's class roughly looks like this:
public class Helper {
InsuranceInvoices[] insuranceInvoices;
InsuranceCollectiveInvoices[] insuranceCollectiveInvoices
BankInvoices[] bankInvoices;
BankCollectiveInvoices[] bankCollectiveInvoices;
}
All of the invoice types have a mutual marker interface Invoices.
I need to get all of the invoices to invoke another method on them.
Helper helperObject = new Helper();
// ...
for (InsuranceInvoices invoice : helperObject.getInsuranceInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
for (BankInvoices invoice : helperObject.getBankInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
// repeat with all array fields
The problem is that all invoices only have the marker interface in common. The method getCustomerID() is not defined by a mutual interface or class. This is a behaviour I cannot change due to a given specification.
The code repetition inside the for-each-loop is something that bugs me. I have to do the exact same thing on all invoice objects in the four different arrays. Hence four for-each-loops that unecessary bloat the code.
Is there a way that I can write a general (private) method? One idea was:
private void generalMethod(Invoice[] invoiceArray){
// ...
}
But this would require four instanceof checks because the class Invoice doesn't know the method getCusomterId(). Therefore I would gain nothing; the method would still contain repetitions.
I'm thankful for every possible solution to generalize this problem!
Possible solutions to generalize the problem (ordered from best to worst):
Using wrapper class
public class InvoiceWrapper {
private String customerID;
public String getCustomerID() {
return customerID;
}
public InvoiceWrapper(BankInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
public InvoiceWrapper(InsuranceInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
// other constructors
}
Upd If I understood correctly, you need to do something with IDs in all arrays. To use InvoiceWrapper, you also need to implement iterator in Helper class, that will walk through arrays and return a wrapper for each entry. So, you will have code that works with 4 arrays anyway.
Using instance of casts
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
if (invoice instanceof InsuranceInvoices) {
return ((InsuranceInvoices) invoices).getCustomerID();
} else if ...
}
}
Calling methods by name via Reflection
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
Method method = invoice.getClass().getDeclaredMethod("getCustomerId");
return (String) method.invoke(invoice);
}
}
It's not pretty, but you could use reflection to look up the getCustomerId Method and then invoke() it, cf. Class.getDeclaredMethod().
private void generalMethod(Invoice[] invoiceArray){
try {
for (Invoice invoice : invoiceArray) {
Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId");
getCustomerId.invoke(invoice);
}
} catch (Exception e) {
// ...
}
}
Do note that this is untested.
If you are not allowed to change the classes you are handling by adding a custom interface to them. The best thing you can do is wrap them with a custom class that does have the desired properties.
This way you will have one class with all 'not so nice' code that converts the classes you can not touch to nice classes that match a proper and useful design.
For instance you could have a class WrappedInsuranceInvoice that extends WrappedInsurace and contains a member field InsuranceInvoice. If you don't need to keep the original class you would be off even better by copying the data. This way you could for instance lose the arrays and use lists instead.

Access private enum in legacy code in

I have legacy code where is private enum which I need to construct another type for acceptance testing, but I'm stuck because this enum is private and it is not part of any class, looks like following:
enum Element {
ELEMENT1, ELEMENT2;
public static Element[] values() { /* compiled code */ }
public static Element valueOf(java.lang.String name) { /* compiled code */ }
private Element() { /* compiled code */ }
}
is there a way how to use this enum, expose it from legacy code, or maybe way how to mock it?
Update:
I know I can read values enums by reflection, but I have another class which is public and I need to use enum value in its constructor, this class is in the same package like Element, its constructor is :
public class ElementProvider {
public ElementProvider(string name, Element element){ /*compiled code*/ }
}
A way to do it could be to use Class.forName and load it using the package + name.
For example:
Class<?> enumElement = Class.forName("com.my.package.Element");
Then if everything is OK you will have the enum.
Then with getEnumConstants you can read all constants of the enum (you can check if it's an enum using isEnum if needed):
Object[] enumElements = elements.getEnumConstants();
for (Object obj : enumElements) {
System.out.println(obj);
}
You are forced to use Object since you don't know what type it will be (well, you know but you can't access it)
And use enumElements[0] to access ELEMENT1 and so on.
About your updated question, that's the first thing that comes in my mind:
Class<?> enumElement = Class.forName("org.myname.test.Element");
Object[] enumElements = elements.getEnumConstants();
Object element1 = enumElements[0];
ElementProvider elementProvider = ElementProvider.class.getDeclaredConstructor(String.class, enumElement).newInstance("Hello", element1);

Can I declare enums within enums to specify/limit both keys and values in a map in Java?

I want to be able to specify a list of keys and allowed values for each key programatically so that the code can be checked at compile time for errors and in the hope of better performance.
Imagine I am representing word in a database and each word has a number of features:
public class Word {
public Map<Feature, FeatureValue> features = new EnumMap<Feature, FeatureValue>();
}
And I have an enum class:
public enum Feature {
TYPE("Type") {
enum Value {
NOUN("Noun"),
VERB("Verb");
}
#Override
public Value[] getValues() {
return new Value[]{Value.NOUN, Value.VERB};
}
},
PLURALITY("Plurality") {
enum Value {
SING("Singular"),
PL("Plural");
}
#Override
public Value[] getValues() {
return new Value[]{Value.SING, Value.PL};
}
},
}
I would at least want to be able to do something like:
word.features.put(TYPE, TYPE.Value.NOUN);
word.features.put(PLURALITY, PLURALITY.Value.PL);
So that it's easy to see that the values match the key, but the enum within enum syntax doesn't seem to be allowed.
I also tried this:
TYPE("Type") {
public String NOUN = "Noun";
public String VERB = "Verb";
but I couldn't reference TYPE.NOUN since they aren't allowed to be static for some reason.
Please is there someone who know a good pattern to specifying something like this? I'm just worried if use strings in my code like
word.features.put(TYPE, "Noun");
I am asking for trouble with typos etc.
You can't do it like that but you can do it like this:
// define a type values as an enum:
enum TypeValue {
Noun, Verb
}
// define an attribute class parametrized by an enum:
public class Attribute<E extends Enum<E>> {
// define your attribute types as static fields inside this class
public static Attribute<TypeValue> Type = new Attribute<TypeValue>();
}
// and now define your method like this:
<E extends Enum<E>, Feature extends Attribute<E>> void put(Feature feature, E value) {
}
// you will then have a compilation error when trying to invoke the method with improper associated parameters.
// eg if we define
enum OtherValue { X }
features.put(Attribute.Type, TypeValue.Noun); // ok
features.put(Attribute.Type, OtherValue.X); // Fails

Categories

Resources