how to change name based on activity in model using android - java

I create a model called Review. There are two activities (QualityReivewActivity.java & FairnessReivewActivity.java) will call the model whenever user leaves a comment.
I want to
public class Review {
float fairness_rating; //change the name to quality_rating
String post_id;
String review_time;
String reviewer_id;
String text_review;
public Review(){
//
}
Review(float fairness_rating, String post_id, String review_time, String reviewer_id, String text_review){
this.fairness_rating=fairness_rating;
this.post_id=post_id;
this.review_time=review_time;
this.reviewer_id=reviewer_id;
this.text_review=text_review;
}
public float getFairness_rating() {
return fairness_rating;
} //change to getQuality_rating if actitivty is QualityReivewActivity.java
public String getPost_id() {
return post_id;
}
public String getReview_time() {
return review_time;
}
public String getReviewer_id() {
return reviewer_id;
}
public String getText_review() {
return text_review;
}
}
and this is the segment of code of QualityReivewActivity
Review c = new Review(mRatingBar.getRating(), post_id, timedComment.toString(), reviewer_uid, my_comment.getText().toString()); //
However, the QualityReviewActivity always shows "fairness_rating". How can I make a dynamic model name to change to "quality_rating" if I am calling from QualityReviewActivity?

You can solve it by using enum.
public enum ratingType {
 Quality,
 Fairness
}
Then use that enum in your function.
public float get_rating(ratingType type) {
 switch (type) {
 case Quality:
  return quality_rating;
 case Fairness:
  return fairness_rating;
 }
}
After that, depending on the class, you can pass the necessary arguments and it will work.
I'm not good at Java, so it may not work if I write it as it is, but the idea is ok.

Related

Java - how to call a method of corresponding class based on string using enum/factory pattern

Yes, I read many examples in web, but I didn't find a way how to call a method based on string value. May be I am not searching in right way... I wrote all code, but don't know how to call the method.
fyi: I don't want to use if else or switch case
Here is what I want:
I get the card reader type as String from database. I have to call the corresponding class' method.
My code:
LoginPanel.java
public class LoginPanel {
public static void main(String args[]) {
String readerType = "Omnikey5427-CK"; // I get this ("Omnikey5427-CK" or "Omnikey5427-G2") from a database as String
// I WANT TO CALL getCardNumber() method of respective class
}
}
ISmartCardReader.java
public interface ISmartCardReader {
public Integer getCardNumber();
}
Omnikey5427G2.java
public class Omnikey5427G2 implements ISmartCardReader {
public Omnikey5427G2() {
System.out.println("G222222222222222...");
}
public Integer getCardNumber() {
return 222;
}
}
Omnikey5427CK.java
public class Omnikey5427CK implements ISmartCardReader {
public Omnikey5427CK() {
System.out.println("CKKKKKKKKKKKKKKK...");
}
public Integer getCardNumber() {
return 111;
}
}
SmacrtCardEnumFactory.java
public enum SmacrtCardEnumFactory {
OMNIKEY5427CK("Omnikey5427-CK") {
public ISmartCardReader geInstance() {
return new Omnikey5427CK();
}
},
OMNIKEY5427G2("Omnikey5427-G2") {
public ISmartCardReader geInstance() {
return new Omnikey5427G2();
}
};
private String cardReaderName;
private SmacrtCardEnumFactory(String cardReaderName) {
this.cardReaderName = cardReaderName;
}
public String cardReaderName() {
return cardReaderName;
}
}
You can use valueOf() function of enum provided your enum sonstant names match strings used to lookup (you may use cardName.toUpper()). You may also create objects for all the card types and store them in a hash map and then lookup them. You can also write some fatory method, but this will be if-then-else or switch inside
You could iterate over the factory's values() and get the one that matches the string:
public enum SmacrtCardEnumFactory {
// current code omitted for brevity
public static getSmartCardReader(String name) {
return Arrays.stream(values())
.filter(r -> r.cardReaderName().equals(name))
.map(SmacrtCardEnumFactory::getInstance();
.orElse(null);
}
}

Is it possible to create enums with a variable which is defined only when using this enum?

I am trying to build an object which will be used to communicate with other objects. This communication object should have an enum, these enums include "ORDER_CREATED", "ORDER_CANCELLED" and "ORDER_AT_LOCATION". What I now want to do is assign a value to the enum "ORDER_AT_LOCATION" with a String location. This way there are no blank fields containing "null" if the enum is "ORDER_CREATED".
I am not entirely sure if this is even possible.
I tried using a constructor for one specific enum but didn't have any luck
public class OrderEvent {
private OrderEventTypes eventType;
}
enum OrderEventTypes{
//I want a constructor with String info only for the enum ORDER_AT_LOCATION
ORDER_AT_LOCATION{
String info;
public void ORDER_IN_TRANSIT(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
, ORDER_CANCELLED, ORDER_COMPLETED, ORDER_CREATED;
}
the expected result should be that this statement works.
if(eventType.equals("ORDER_AT_LOCATION")) {
System.out.println(eventType.getInfo());
}
if you have any other nice solutions to this I would be very thankful, all the solutions I could come up with were perfectly do-able but not as nice as this would be.
You can create the enum with a constructor which accepts a String value and initialises the info field:
enum OrderEventTypes{
ORDER_AT_LOCATION("ORDER_AT_LOCATION"),
ORDER_CANCELLED,
ORDER_COMPLETED,
ORDER_CREATED;
private final String info;
OrderEventTypes(){
this("");
}
OrderEventTypes(String info){
this.info = info;
}
public String getInfo(){
return this.info;
}
#Override
public String toString() {
return this.info;
}
}
Now when you need to compare, you can use the getter to get the value of the info field:
if("ORDER_AT_LOCATION".equals(eventType.getInfo())){
System.out.println(eventType.getInfo());
}

Check if class has a variable in its constructor based on a string?

Let's say I have a class named Person and its constructor had variables like name, age, hairColor and so on. If I had a function that receives a string that should match one of the class's variables, how could I check if that class actually had that variable and how could I go about modifying it? For example:
public class Person {
public String name;
public int age;
public String hairColor;
public Person() {
name = "Bryce";
age = 21;
hairColor = "brown";
}
public void changeHairColor(String variable, String color) {
if (/*this class contains the variable passed as an argument to this method*/) {
// Person[variable] = color
}
}
}
I'm a python dev, mostly, so the method changeHairColor has some pseudo-python in it. I want to be able to edit the variable in a similar way you could edit variables inside of dictionaries with Python:
person = {
"name": "Bryce",
"age": 21,
"hairColor": "brown"
}
def changeHairColor(variable, color):
person[variable] = color
If that is at all possible.
The only way to do it in Java is to use Java Reflection API:
public class Test {
public String name;
public int age;
public String hairColor;
public void setProperty(String property, Object value) {
try {
Field declaredField = this.getClass().getDeclaredField(property);
switch (declaredField.getAnnotatedType().getType().getTypeName()) {
case "java.lang.String":
declaredField.set(this, value);
break;
// handle other types
}
} catch (NoSuchFieldException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}
}
public static void main(String[] args) {
Test test = new Test();
test.setProperty("name", "Bob");
System.out.println(test.name);
}
}
I would not solve this with reflection. If your PlayerCharacter has an enumerable set of attributes, I would model these as a Java enum and store the attribute values within the PlayerCharacter object in an EnumMap:
import java.util.EnumMap;
public class PlayerCharacter {
public enum Attribute {
AGILITY,
DEXTERITY,
/* etc ...*/
VITALITY
}
private EnumMap<Attribute, Integer> attributes = new EnumMap<>(Attribute.class);
public PlayerCharacter() {
// initialize each attribute with a default value (0 in this example)
for (Attribute a : Attribute.values()) {
attributes.put(a, new Integer(0));
}
}
public int getValue(Attribute attribute) {
return attributes.get(attribute);
}
public void levelUp(Attribute attribute, int amount) {
attributes.put(attribute, attributes.get(attribute) + amount);
}
}
The biggest benefit of using an enum instead of plain old String (+reflection), is that this way you get compile-time type safety for the code that's using your PlayerCharacter.
Using Reflection API, you can access the methods and properties on an object at run time. The other answer describes its usage. But I don't recommend reflections for your problem. How about the following:
public void changeHairColor(String variable, String color) {
if("name".equalsIgnoreCase(variable))
this.name = color;
else if("age".equalsIgnoreCase(variable))
this.age = Integer.parseInt(color);
else if("color".equalsIgnoreCase(variable))
this.color = color;
else
throw new Exception ("error - property not available");
}
}
Note, your existing method name 'changeHairColor' doesn't make sense in the context. It should be someething like 'changeProperty' because you are not just changing the 'color', you are changing any available property with this method.

Java-How do I call a class with a string?

I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.

Creating a list out of my DTO

I have a year object. For now lets say only two years and its getters and setters
private String mYearOne;
private String mYearTwo;
public String getmYearOne() {
return mYearOne; }
public void setmYearOne(String mYearOne) {
this.mYearOne = mYearOne; }
public String getmYearTwo() {
return mYearTwo; }
public void setmYearTwo(String mYearTwo) {
this.mYearTwo = mYearTwo; }
Then each year has three insurance plans. And its getters and setters.
private String healthPlan;
private String carPlan;
private String housePlan;
private String healthPlanTwo;
private String carPlanTwo;
private String housePlanTwo;
public String getHealthPlan() {
return healthPlan; }
public void setHealthPlan(String healthPlan) {
this.healthPlan = healthPlan; }
public String getCarPlan() {
return carPlan; }
public void setCarPlan(String carPlan) {
this.carPlan = carPlan; }
public String getHousePlan() {
return housePlan; }
public void setHousePlan(String housePlan) {
this.housePlan = housePlan; }
public String getHealthPlan() { //For the second year
return healthPlan; }
public void setHealthPlan(String healthPlan) {
this.healthPlan = healthPlan; }
public String getCarPlan() {
return carPlan; }
public void setCarPlan(String carPlan) {
this.carPlan = carPlan; }
public String getHousePlan() {
return housePlan; }
public void setHousePlan(String housePlan) {
this.housePlan = housePlan; }
public String getHealthPlanTwo() {
return healthPlanTwo; }
public void setHealthPlanTwo(String healthPlanTwo) {
this.healthPlanTwo = healthPlanTwo; }
public String getCarPlanTwo() {
return carPlanTwo; }
public void setCarPlanTwo(String carPlanTwo) {
this.carPlanTwo = carPlanTwo; }
public String getHousePlanTwo() {
return housePlanTwo; }
public void setHousePlanTwo(String housePlanTwo) {
this.housePlanTwo = housePlanTwo; }
You will notice the code is bulky. I need to define them in a <list> of year. So that if 10 years are considered, I would have 10 multiplied
by 3 = 30 plans and its getters and setters respectively.
How could this be done?
I think your best bet will be to maintain a count of number of years and arraylists for the insurance plans. This way, you can get the arraylist once and get the insurance plan details for whatever year you actually want. This will be characterized by a single insurance plan arraylist and a single arraylist for years.
private ArrayList mYear;
private ArrayList healthPlan;
private ArrayList carPlan;
private ArrayList housePlan;
public String getHousePlanForYear(String year){
return housePlan.get(mYear.indexOf(year));
}
public void setHousePlanForYear(String housePlan, String year){
this.housePlan.set(mYear.indexOf(year), housePlan);
}
Similarly for the other plans. Of course, all this is assuming that the year is always present and other boundary conditions. Just add your boundary checks in these getters and setters and you will be good to go. :)
I see a design/domain modelling problem here. A person can ideally have multiple "plans" and "riders" attached to each plan. This should clearly be abstracted away properly by creating a "PlanCollection" class or simply maintaining a list of "plans" which all extend/implement a common "Plan" class/interface.
Each plan can have a "plan" duration and a start date. Also, logically, you don't attach plans to "year" but the timeline information is encapsulated in the Plan itself (like start and duration as mentioned above).
Take a look at enums and maps. The enum would specify car, house etc.
You could create a map that takes an enum as key and a List of years as the key. Don't be tempted to create YearThree etc.
On a note of style: if you intend to use m to prefix fields, take the m out of the setter. E.g. setYearOne not setmYearOne.
Choose your types wisely, don't use a String if an int is better.

Categories