Breaking up long switch - java

I have this code:
public void addSkillXp(SkillType attribute, int value) {
final SkillDatabaseEntity skillDatabaseEntity = skillValueCache.getEntity();
switch (attribute) {
case TWO_HANDED_CRUSHING_WEAPONS:
skillDatabaseEntity.setTwoHandedCrushingWeaponsXp(value);
skillMapper.addTwoHandedCrushingWeaponsXp(userEntity.getId(), value);
break;
case ONE_HANDED_CRUSHING_WEAPONS:
skillDatabaseEntity.setOneHandedCrushingWeaponsXp(value);
skillMapper.addOneHandedCrushingWeaponsXp(userEntity.getId(), value);
break;
case TWO_HANDED_AXES:
skillDatabaseEntity.setTwoHandedAxesXp(value);
skillMapper.addTwoHandedAxesXp(userEntity.getId(), value);
break;
case ONE_HANDED_AXES:
skillDatabaseEntity.setOneHandedAxesXp(value);
skillMapper.addOneHandedAxesXp(userEntity.getId(), value);
break;
case THROWING_WEAPONS:
skillDatabaseEntity.setThrowingWeaponsXp(value);
skillMapper.addThrowingWeaponsXp(userEntity.getId(), value);
break;
case FISTFIGHT:
skillDatabaseEntity.setFistfightXp(value);
skillMapper.addFistfightXp(userEntity.getId(), value);
break;
...
}
The switch is goes on for more 20 cases. The SkillDatabaseEntity is a simple DAO class:
public class SkillDatabaseEntity {
private int twoHandedCrushingWeaponsXp;
private int oneHandedCrushingWeaponsXp;
private int twoHandedAxesXp;
private int oneHandedAxesXp;
private int throwingWeaponsXp;
private int fistfightXp;
private int longswordsXp;
private int shortswordsXp;
private int polearmsXp;
private int daggersXp;
private int longbowsXp;
private int showrtbowsXp;
private int crossbowsXp;
private int lightArmorXp;
private int heavyArmorXp;
private int robeArmorXp;
private int armorlessDefenseXp;
private int shieldDefenseXp;
private int staffsXp;
private int wandsXp;
private int spectresXp;
private int scavengingXp;
private int cookingXp;
public int getTwoHandedCrushingWeaponsXp() {
return twoHandedCrushingWeaponsXp;
}
public void setTwoHandedCrushingWeaponsXp(int twoHandedCrushingWeaponsXp) {
this.twoHandedCrushingWeaponsXp = twoHandedCrushingWeaponsXp;
}
public int getOneHandedCrushingWeaponsXp() {
return oneHandedCrushingWeaponsXp;
}
public void setOneHandedCrushingWeaponsXp(int oneHandedCrushingWeaponsXp) {
this.oneHandedCrushingWeaponsXp = oneHandedCrushingWeaponsXp;
}
public int getTwoHandedAxesXp() {
return twoHandedAxesXp;
}
public void setTwoHandedAxesXp(int twoHandedAxesXp) {
this.twoHandedAxesXp = twoHandedAxesXp;
}
public int getOneHandedAxesXp() {
return oneHandedAxesXp;
}
public void setOneHandedAxesXp(int oneHandedAxesXp) {
this.oneHandedAxesXp = oneHandedAxesXp;
}
public int getThrowingWeaponsXp() {
return throwingWeaponsXp;
}
public void setThrowingWeaponsXp(int throwingWeaponsXp) {
this.throwingWeaponsXp = throwingWeaponsXp;
}
...
}
I need to add removeSkillXp but really want to avoid this huge switch and also if I'm here I want to improve that old scwitch too. How can I do that?
What I have as a plan is to create a new class like this:
SkillModifier:
increaseExperience(UserEntity, value)
decreaseExperience(UserEntity, value)
getExperience(UserEntity, value)
getSupportedSkillType()
And create an instance of this class for every case in the switch, add the instances into a map (This can be easily done with Spring DI) and use something like this:
public void addSkillXp(SkillType attribute, int value) {
skillMap.get(attribute).increaseExperience(userEntity, value);
}
Can this work? Or is there a better pattern to do?

If you move the functionality from the code into the object, things get much easier.
For example:
enum SkillType {
TWO_HANDED_CRUSHING_WEAPONS {
#Override
void updateEntity(SkillDatabaseEntity entity, int value) {
entity.setTwoHandedCrushingWeaponsXp(value);
}
#Override
void mapSkill(SkillMapper mapper, int userId, int value) {
mapper.addTwoHandedCrushingWeaponsXp(userId, value);
}
},
ONE_HANDED_CRUSHING_WEAPONS {
#Override
void updateEntity(SkillDatabaseEntity entity, int value) {
entity.addOneHandedCrushingWeaponsXp(value);
}
#Override
void mapSkill(SkillMapper mapper, int userId, int value) {
mapper.addOneHandedCrushingWeaponsXp(userId, value);
}
},
TWO_HANDED_AXES {
#Override
void updateEntity(SkillDatabaseEntity entity, int value) {
entity.setTwoHandedAxesXp(value);
}
#Override
void mapSkill(SkillMapper mapper, int userId, int value) {
mapper.addTwoHandedAxesXp(userId, value);
}
};
abstract void updateEntity(SkillDatabaseEntity entity, int value);
abstract void mapSkill(SkillMapper mapper, int userId, int value);
}
public void addSkillXp(SkillType skill, int value) {
final SkillDatabaseEntity skillDatabaseEntity = skillValueCache.getEntity();
skill.updateEntity(skillDatabaseEntity, value);
skill.mapSkill(skillMapper, userEntity.getId(), value);
}
Here addSkillXp has become just three lines of code.
Another elegant benefit to this is that all of the skill-reelated code is in the same enum.

The whole switch seems redundant because each case does the same thing. Why not create an abstract class weapon which has a method increaseXP and is extended by each weapon class (2h etc.).
In this way the implementation is in the abstract class and the other sub-classes just call .increaseXP. By the way the database class seems unnecessary, just keep a list / array of weapons for each player.
Some more background info see:
https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism

Related

Problem to read an ArrayList or List of a parcelable class

I have this parcelable class:
public class EventInviteWorkingHours implements Parcelable {
int dayOfWeek;
String begin;
String finish;
public EventInviteWorkingHours() {
}
protected EventInviteWorkingHours(Parcel in) {
dayOfWeek = in.readInt();
begin = in.readString();
finish = in.readString();
}
public static final Creator<EventInviteWorkingHours> CREATOR = new Creator<EventInviteWorkingHours>() {
#Override
public EventInviteWorkingHours createFromParcel(Parcel in) {
return new EventInviteWorkingHours(in);
}
#Override
public EventInviteWorkingHours[] newArray(int size) {
return new EventInviteWorkingHours[size];
}
};
public int getDayOfWeek() {
return dayOfWeek;
}
public void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
public String getBegin() {
return begin;
}
public void setBegin(String begin) {
this.begin = begin;
}
public String getFinish() {
return finish;
}
public void setFinish(String finish) {
this.finish = finish;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(dayOfWeek);
dest.writeString(begin);
dest.writeString(finish);
}
}
and in another class that implements parcelable and has this variable:
List<EventInviteWorkingHours> workingHours;
i write and read this variable like that:
dest.writeTypedList(workingHours);
in.readTypedList(workingHours, EventInviteWorkingHours.CREATOR);
But, when I get the item by intent that contains this variable, this error appears:
java.lang.RuntimeException: Parcel android.os.Parcel#d7fbbfb: Clearing the unknown type code 7274612 at offset 788
Somebody knows how to fix it? I already have tried with ArrayList and write and read for differents ways, but never works
I haven`t find any solution with parcelable, but i used serializable and it works very well:
The first parcelable class is now serializable class:
public class EventInviteWorkingHours implements Serializable {
int dayOfWeek;
String begin;
String finish;
public EventInviteWorkingHours() {
}
public int getDayOfWeek() {
return dayOfWeek;
}
public void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
public String getBegin() {
return begin;
}
public void setBegin(String begin) {
this.begin = begin;
}
public String getFinish() {
return finish;
}
public void setFinish(String finish) {
this.finish = finish;
}
}
And in another class that implements parcelable and has this variable:
List<EventInviteWorkingHours> workingHours;
Will read and write that variable like that:
workingHours = (List<EventInviteWorkingHours>) in.readSerializable();
dest.writeSerializable((Serializable) workingHours);

Implement addDiscount method that gets DiscountData as input to store it in the subscription object

I have the following two classes. I need to Implement a method in the second class namely addDiscount that gets DiscountData as input to store it in the subscription object.
I am guessing I need to use an arraylist here? If so, how?
DiscountData Class:
class DiscountData {
private int value;
private int length;
public DiscountData(int value, int length) {
this.value = value;
this.length = length;
}
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
public int getLength() {
return this.length;
}
public void setLength(int length) {
this.length = length;
}
}
Subscription class:
public class Subscription {
public void addDiscount(DiscountData discountData) {
// your code here
}
}
Smth like this:
public class Subscription {
private List<DiscountData> data = new ArrayList<DiscountData>();
public void addDiscount(DiscountData discountData) {
data.add(discountData);
}
}

Java cascade of errors in object code when compiling

I'm trying to compile a java program, however I get a cascade of errors stating
"Error expected", "illegal start of type", "class, interface or enum expected" from the file containing methods/constructors for an object called Task.
From what I can gather online these errors occur when statements are made outside of a class or method etc. but I haven't done any of that.
The code was working fine before, all I have done to Task.java is add a few basic get and set methods and change the name of some of the variables.
What's more is that I can't view all the errors in cmd. For some reason I can only scroll up so far, so I can't even attempt to pin point the source.
public class Task
{
// private member variables
private int CriticalTime;
private int TaskTime;
private int id;
private int numDependency;
private int day;
private boolean generic;
private boolean isComplete;
private boolean isCritical;
private boolean ignore;
private boolean dummy;
private boolean isScheduled;
private int[] dependency;
public Task()
{
CriticalTime = 0;
TaskTime = 0;
id = 0;
numDependency = 0;
day = 0;
generic = false;
isComplete = false;
isCritical = false;
ignore = false;
dummy = false;
isScheduled = false;
int[] dependency;
return;
}
public Task(int x, int y, int ID, int NumDependency, int Day, boolean Generic, boolean IsComplete, boolean IsCritical, boolean Ignore, boolean Dummy, boolean IsScheduled, int[] Dependency)
{
CriticalTime = x;
TaskTime = y;
id = ID;
numDependency = NumDependency;
day = Day;
generic = Generic;
isComplete = IsComplete;
isCritical = IsCritical;
ignore = Ignore;
dummy = Dummy;
isScheduled = IsScheduled;
this.dependency = Dependency;
return;
}
public void setTask(int x, int y, int ID, int NumDependency, int Day, boolean Generic, boolean IsComplete, boolean IsCritical, boolean Ignore, boolean Dummy boolean IsScheduled, int[] Dependency)
{
CriticalTime = x;
TaskTime = y;
id = ID;
numDependency = NumDependency;
day = Day;
generic = Generic;
isComplete = IsComplete;
isCritical = IsCritical;
ignore = Ignore;
dummy = Dummy;
isScheduled = IsScheduled;
this.dependency = Dependency;
}
public void setTask(int[] Dependency)
{
CriticalTime = 0;
day = 0;
generic = false;
isComplete = false;
isCritical = false;
ignore = false;
dummy = false;
isScheduled = false;
this.dependency = Dependency;
}
public int getCriticalTime()
{
return CriticalTime;
}
public int getTaskTime()
{
return TaskTime;
}
public int getTaskID()
{
return id;
}
public int getNumDependency()
{
return numDependency;
}
public boolean getGenericBoolean()
{
return generic;
}
public boolean getIsCompleteBoolean()
{
return isComplete;
}
public boolean getIsCriticalBoolean()
{
return isCritical;
}
public boolean getIgnoreBoolean()
{
return ignore;
}
public boolean getIsScheduled()
{
return isScheduled;
}
public boolean getDummy()
{
return dummy;
}
public int getDay()
{
return day;
}
public int getDependency(int x)
{
return dependency[x];
}
public void setGenericBoolean(boolean Generic)
{
generic = Generic;
}
public void setIsCompleteBoolean(boolean IsComplete)
{
isComplete = IsComplete;
}
public void setIsCriticalBoolean(boolean IsCritical)
{
isCritical = IsCritical;
}
public void setIgnoreBoolean(boolean Ignore)
{
ignore = Ignore;
}
public void setIsScheduled(boolean IsScheduled)
{
isScheduled = IsScheduled;
}
public void setCriticalTime(int A)
{
CriticalTime = A;
}
public void setCriticalTime(int A, int B)
{
CriticalTime = A + B;
}
public void setDependency(int i, int A)
{
dependency[i]=A;
}
public void setTaskTime(int A)
{
TaskTime = A;
}
public void setTaskID(int A)
{
id = A;
}
public void setNumDep(int A)
{
numDependency = A;
}
public void setDummy(boolean Dummy)
{
dummy = Dummy;
}
public void setDay(int i)
{
day = i;
}
}
Sorry if this is badly formatted or has unnecessary methods etc., I'm very much a novice.
Not a direct answer, but a guide how to solve such things: simply comment out 95% of that code.
In other words: the more code you try to compile, the easier it is that a simple syntactic error turns into an error message that is not pointing to the correct place directly.
Thus:
you simply start by running the compiler much more often. Write 5 lines of code (of which you think: this should compile) - then run the compiler. Fix bugs. And so on
and as said: when you have such a huge thing and you can't translate error messages into meaningful information: try to isolate where the problem comes from.
And beyond that: read about clean code. That practice advocates for example to have a maximum of 3 parameters for a method. And surprise: such missing commas, as in your case are much easier to spot when there are only 2 of them for 3 parameters - instead of 11 for 12 parameters as in your case).
Seriously: your "syntax" problems are just a symptom of the real problem: and that lies in the way how you are designing your class and its methods.
There is a , missing on boolean Dummy boolean IsScheduled, of setTask. It should be
public void setTask(int x, int y, int ID, int NumDependency,
int Day, boolean Generic, boolean IsComplete, boolean IsCritical,
boolean Ignore, boolean Dummy, boolean IsScheduled, int[] Dependency)
{
...
}
This is a type of error that is easily spotted if you were using an IDE to program.

Java type parameter is not within its bound

I have a class Zeitpunkt which implements a date with time and in addition a class Suchbaum which represents a binary search tree.
I want to use a Comparator-Object in Suchbaum to sort a tree by the day of Zeitpunkt, but when I want to create a Suchbaum object, it prints the named error.
Zeipunkt
public class Zeitpunkt<T> implements Comparable<T>
{
private int jahr;
private int monat;
private int tag;
private int stunden;
private int minuten;
private double sekunden;
public int vergleich(Zeitpunkt a) { ... }
#Override
public int compareTo(T o) {
if(o instanceof Zeitpunkt)
return vergleich((Zeitpunkt)o);
return 0;
}
...
}
Suchbaum
public class Suchbaum<T extends Comparable<T>> {
private class Element {
private T daten;
private Element links;
private Element rechts;
public Element(T t) {
daten = t;
links = null;
rechts = null;
}
}
private Element wurzel;
private Comparator<T> comp;
...
}
Testclass
public class BaumTest {
public static void main(String[] args) {
// error in the following line (IntelliJ underlines the first
// "Zeitpunkt"). Suchbaum<Zeitpunkt<?>> = ... doesn't work either..
// *Completely confused*
Suchbaum<Zeitpunkt> sb = new Suchbaum<>((Zeitpunkt z1, Zeitpunkt z2) -> {
if(z1.getTag() > z2.getTag())
return 1;
else if(z1.getTag() == z2.getTag())
return 0;
else
return -1;
});
}
}
Any ideas? (the other threads with this topic didn't help me out)
Seems that you don't want to make your Zeitpunkt class parametrized, you just want it to implement Comparable interface. So change it like this:
public class Zeitpunkt implements Comparable<Zeitpunkt> {
private int jahr;
private int monat;
private int tag;
private int stunden;
private int minuten;
private double sekunden;
public int vergleich(Zeitpunkt a) {
return 0;
}
#Override
public int compareTo(Zeitpunkt o) {
return vergleich(o);
}
}
Also you need to define a constructor in your Suchbaum class:
public Suchbaum(Comparator<T> comp) {
this.comp = comp;
}

Sorting values with Comparator changes all the values with that object

I am working in an android application I want to sort a List of Objects with an Object Property. I have sorted it successfully but when I sort it all the List with that object changes the value to same as the sorted value
Please look into ma code :
SortedSet<Caseload> removeDuplicateClientName = new TreeSet<Caseload>(
new Comparator<Caseload>() {
#Override
public int compare(Caseload caseload0, Caseload caseload1) {
return caseload0.ClientName.compareTo(caseload1.ClientName);
}
});
// Getting the list of values from web service
mLISTCaseloadsHeads = parsedXML.getCaseLoadValues("get_Caseload_ClientServiceGroupID", param);
List<Caseload> newBackUp=mLISTCaseloadsHeads ;
Iterator<Caseload> iterator = mCaseloadsHeads.iterator();
while (iterator.hasNext()) {
removeDuplicateClientName.add(iterator.next());
}
mCaseloadsHeads.clear();
mCaseloadsHeads.addAll(removeDuplicateClientName);
The List newBackUp also changes the value to the same as sorted List
Caseload class:
public class Caseload implements Comparable<Caseload> {
public int BusClientLogID;
public int ClientID;
public int ClientStatus;
public int ClientServiceGroup_ClientSiteTherapyID;
public String ClientName;
public String TimeArrive;
public String TimeDepart;
public String SignOutTime;
public String SignInTime;
public String ServiceCompletedCount;
public Boolean ShowFooter = false;
public int getBusClientLogID() {
return BusClientLogID;
}
public void setBusClientLogID(int busClientLogID) {
BusClientLogID = busClientLogID;
}
public int getClientID() {
return ClientID;
}
public void setClientID(int clientID) {
ClientID = clientID;
}
public int getClientStatus() {
return ClientStatus;
}
public void setClientStatus(int clientStatus) {
ClientStatus = clientStatus;
}
public int getClientServiceGroup_ClientSiteTherapyID() {
return ClientServiceGroup_ClientSiteTherapyID;
}
public void setClientServiceGroup_ClientSiteTherapyID(
int clientServiceGroup_ClientSiteTherapyID) {
ClientServiceGroup_ClientSiteTherapyID = clientServiceGroup_ClientSiteTherapyID;
}
public String getClientName() {
return ClientName;
}
public void setClientName(String clientName) {
ClientName = clientName;
}
public String getTimeArrive() {
return TimeArrive;
}
public void setTimeArrive(String timeArrive) {
TimeArrive = timeArrive;
}
public String getTimeDepart() {
return TimeDepart;
}
public void setTimeDepart(String timeDepart) {
TimeDepart = timeDepart;
}
public String getSignOutTime() {
return SignOutTime;
}
public void setSignOutTime(String signOutTime) {
SignOutTime = signOutTime;
}
public String getSignInTime() {
return SignInTime;
}
public void setSignInTime(String signInTime) {
SignInTime = signInTime;
}
public String getServiceCompletedCount() {
return ServiceCompletedCount;
}
public void setServiceCompletedCount(String serviceCompletedCount) {
ServiceCompletedCount = serviceCompletedCount;
}
#Override
public int compareTo(Caseload compareCaseload) {
int busClientLogID = ((Caseload) compareCaseload).getBusClientLogID();
return busClientLogID - this.BusClientLogID;
}
}
Please give me a solution.
I doubt the return statement associated with your compare function in the comparator.
You should go by this approach to get the right ordering :
#Override
public int compare(YourClass lhs, YourClass rhs) {
YourClass p1 = (YourClass) lhs;
YourClass p2 = (YourClass) rhs;
int first = p1.ClientName; //use your getter if you want
int second = p2.ClientName;
if (second < first) {
return 1;
}
else if (second > first) {
return -1;
}
else {
return 0;
}
}
If you go by this approach I guess you will get the required ordering after sort.
Edit:
Now I have got the issue, you are using a reference of the original list in newBackup and its not a new list that is why this is happening, use this and you are good to go.
List<Caseload> newBackUp=new ArrayList<Caseload>(mLISTCaseloadsHeads);

Categories