Removing Repetition with Java Annotations - java

Is it possible to make the following code cleaner with less repetition using annotations?
I know it would be possible with java 8 closures, but trying to get this working on java 6/7
Variable x = new Variable(this,"HClass","HC"){
#Override
String getValue(Player p){
return getHeroFromPlayer(p).getHeroClass().getName();
}
};
Variable y = new Variable(this,"HSecClass","HSC"){
#Override
String getValue(Player p){
return getHeroFromPlayer(p).getSecondClass().getName();
}
};
Variable z = new Variable(this,"HLevel","HL"){
#Override
String getValue(Player p){
return getHeroFromPlayer(p).getLevel();
}
};
Variable a = new Variable(this,"HMastered","HMa"){
#Override
String getValue(Player p){
return getHeroFromPlayer(p).isMaster(getHeroFromPlayer(p).getHeroClass()) && (heroSClass == null || getHeroFromPlayer(p).isMaster(heroSClass))
? LocaleType.MESSAGE_HEROES_TRUE.getVal() : LocaleType.MESSAGE_HEROES_FALSE.getVal();;
}
};
This goes on for some time, where they are all added to a map, which returns the results lazily.
Edit: I was hoping that annotations would allow me to do something along the lines of
#Variable("HLevel","HL")
String getHLevel(){getHeroFromPlayer(p).getlevel();}
Edit: Variable.java
abstract class Variable {
final private VariableGroup vg;
final private List<String> keys = new Vector<String>();
Variable(VariableGroup vg,String...varargs){
this.vg = vg;
for (String s:varargs){
keys.add(s);
}
}
abstract String getValue(Player p);
}

Based on your comments you can do something like this
#Variable("Primary Class")
public String getHClass(Player p) {
return getHeroFromPlayer(p).getHeroClass().getName();
}
#Variable("Primary Class Level")
public int getHLevel(Player p) {
return getHeroFromPlayer(p).getHLevel();
}
#Variable("Secondary Class")
public String getHSecClass(Player p) {
return getHeroFromPlayer(p).getSecondClass().getName();
}
#Variable("Secondary Class Level")
public int getHLevel(Player p) {
return getHeroFromPlayer(p).getHSecLevel();
}
Note: there is no need for all fields to return a String. To get this information you can do the following
Class heroClass =
for(Method method : heroClass.getMethods()) {
Variable var = method.getAnnotation(Variable.class);
if (var == null) continue; // ignore Object.getClass()
String description = var.value; // text to display to users
String attributeName = method.getName().substring(3); // cut "get"
String initials = attributeName.replaceAll("[a-z]+", "");
}

It's hard to say what can be improved without seeing the code for the Variable class. My first question is why are you are creating anonymous inner classes just to return a value for the getValue method? Why not just add a value parameter to the constructor and update the method to return that value?

Related

Return multiple variables from single method with different data types in java

I am new at java . I have method witch contain some variables with different data type i.e. String and Array
pNumber=rs.getString("pNumber");
userName=rs.getString("userName");
simOperater=rs.getString("simOperater");
AdharNumber=rs.getString("AdharNumber");
rechargeAmount[i]=rs.getString("rechargeAmount");
activeDate[i]=rs.getString("activeDate");
plainDeatils[i]=rs.getString("plainDeatils");
and I want to return all the variables from single method in java so what approach should I use please help
just return a response object
public class MyResponse {
public String pNumber;
public String userName;
//....
}
usage:
public MyResponse yourMethod() {
MyResponse myResponse = new MyResponse();
myResponse.pNumber=rs.getString("pNumber");
myResponse.userName=rs.getString("userName");
//...
return myResponse;
}
If you don't want to write more lines, you can also set the return type of your method to Object and return your variable as you normally would, but then cast the returned object into the right type as it was before.
e.g.
class test {
static Object test_return(int which) {
String s = "This is a string";
int i = 100;
if(which == 0) {
return s;
} else {
return i;
}
}
public static void main(String args[]) {
String s = (String) test_return(0);
int i = (int) test_return(1);
System.out.println("String: " + s + "\nint: " + i);
}
}
output:
String: This is a string
int: 100
edit:
since you are new to java, you might not understand how types exactly work here. so I would suggest you read this and this to learn more about autoboxing and unboxing

Check multiple null values in if statement using OR and store errors in an array

When user submit the form I want to check multiple text fields in a form and check whether it is null or not and it must show which input field is blank
String A = request.getparameter("a");
String B = request.getparameter("b");
String C = request.getparameter("c");
if(A==null || B==null || C==null)
{
//Here I want to store the corresponding errors in an arrayfield and it should display which field is empty.
}
change the implementation to this thne
if(A==null){
//A is null, add message
}
else if(B==null){
//error message against B
}
else if(C==null){
//error message against C
}
Use Apache Commons StringUtils.isEmpty(str), which checks for empty strings and handles null gracefully.
so it would be something like
if(StringUtils.isEmpty(A)){
}
// inside onCreate method do this
//make this variable globle
ArrayList<MyVariableNameValue> nullStringList=new ArrayList<>();
for (MyVariableNameValue nullString: checkNull()) {
Log.d("nullsize", "onCreate: "+nullString.getName());
}
//up to here
//create getter method class to store the variable name and value in mainactivity or outside it
public class MyVariableNameValue{
String name,value;
public MyVariableNameValue(String name,String value){
this.name=name;
this.value=value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}
//create a method to return null variable values and name in maiactivity
public ArrayList<MyVariableNameValue> checkNull(){
nullStringList.clear();
String A = request.getparameter("a");
String B = request.getparameter("b");
String C = request.getparameter("c");
ArrayList<MyVariableNameValue> checkString = new ArrayList<>();
checkString.add(new MyVariableNameValue("A",A));
checkString.add(new MyVariableNameValue("B",B));
checkString.add(new MyVariableNameValue("C",C));
for (MyVariableNameValue myString: checkString) {
if(TextUtils.isEmpty(myString.getValue())){
nullStringList.add((myString));
}
}
return nullStringList;
}

How to deal with recursion in toString Java method?

My program is structured as follows: a class that represents an atomic concept which is essentially a String and another class that is made of a list of general concepts. Both classes extends the class Concept that is an abstract class, this means that in the list I could have both atomic concepts and intersection of concepts arbitrary nested.
Each concept, atomic or composed, is printed out by toString method.
Roughly speaking, this is based on this context-free grammar:
C : atom | (C and)+ C
Where C is the abstract class Concept, atom is AtomicConcept and (C and)+ C is Intersection.
This is the AtomicConcept class:
public class AtomicConcept extends Concept{
private String atomicConceptName;
public AtomicConcept(String c) {
this.atomicConceptName = c;
}
#Override
public String toString() {
return atomicConceptName;
}
}
This is che ConceptIntersection class:
import java.util.List;
public class ConceptIntersection extends Concept{
private List<Concept> list;
public ConceptIntersection(List<Concept> l) throws Exception {
if(l.size()>1)
{
this.list = l;
}
else
{
throw new Exception("Intersection needs at least two concepts!");
}
}
public String toString()
{
return Utils.conceptIntersection + Utils.lparen + Utils.splitConcepts(list) + Utils.rparen;
}
}
As you can see in toString function, I also created a method called splitConcepts that takes in input a list of general concepts and returns one string made of each concept separated by comma.
public static String splitConcepts(List<Concept> list)
{
String result = "";
for (Concept item : list) {
System.out.println(item);
result += item.toString() + comma;
}
result = result.substring(0, result.length() - 1);
return result;
}
Where is the problem?
I have trouble with this function because when I call a nested intersection in another one, this function never ends!
One example:
public static void main(String[] args) throws DLRException {
// TODO Auto-generated method stub
AtomicConcept atom = new AtomicConcept("one");
AtomicConcept at = new AtomicConcept("two");
List<Concept> list = new LinkedList<Concept>();
list.add(at);
list.add(atom);
DLRConceptIntersection intersection = new DLRConceptIntersection(list);
System.out.println(intersection); // works fine
list.add(intersection);
DLRConceptIntersection intersection2 = new DLRConceptIntersection(list);
System.out.println(intersection2); //loop never ends!
}
Is a correct approach to fix this problem?
You have a circular reference :
DLRConceptIntersection intersection = new DLRConceptIntersection(list);
list.add(intersection);
This causes the intersection's List to contain a reference to the same instance referred by intersection, which is why toString() run into infinite recursion.
I'm assuming you didn't intend intersection and intersection2 to share the same List.
You can avoid it if you create a copy of the List in the DLRConceptIntersection constructor:
public ConceptIntersection(List<Concept> l) throws Exception {
if(l.size()>1) {
this.list = new ArrayList<>(l);
} else {
throw new Exception("Intersection needs at least two concepts!");
}
}

Problems writing and reading ArrayList<Object> with filestream in Java

In my Android application, I have a list of custom objects
ArrayList<Poke> pcList = new ArrayList<>();
Later in my code, I have save and load methods, that use Java OOS, and OIS to function. I have used these exact methods in other projects and know they work properly.
I believe I am having an issue with saving and loading a list of custom objects.
Here are the lines I'm calling to save, as well as load my list.
// save
oos.writeObject(pcList);
...
// load
pcList = (ArrayList<Poke>)ois.readObject();
Any ideas why I can't properly load/save with my list of custom objects?
Here is the interface that links a few similar objects:
public interface Poke {
int getNum();
String getName();
String getType();
int getValue();
boolean getShiny();
String getImageName();
}
Here is one of the similar object classes
public class BasicPoke implements Poke {
boolean shiny = false;
Random randomInt = new Random();
int iRandom = randomInt.nextInt(34 - 1) + 1;
int iShiny = randomInt.nextInt(31 - 1) + 1;
public int getNum(){
return this.iRandom;
}
public String getName(){
return this.pokeNames[iRandom-1];
}
public String getType(){
return this.pokeTypes[iRandom-1];
}
public int getValue(){
return 1;
}
public boolean getShiny() {
return (iShiny == 15);
}
public String getImageName() {
String threeDigitInteger = String.format(Locale.getDefault(),"%03d", this.getNum());
return (this.getShiny()) ? "icon"+threeDigitInteger+"s" : "icon"+threeDigitInteger;
}
String pokeNames = {"..","..",".."};
String pokeTypes = {"..","..",".."};
Please implement Serializable for the BasicPoke class. And by the way, could you tell us what issue (exception) when you load/save a list of objects?
Thanks,
Nghia

Array Of Methods That Return A String

I'm creating a kind of data testing program, and one specific part is giving me a huge amount of trouble. In my main method class there is one section where I need to send over a String of data as a parameter in a method to my methods class (let's call it ValidatorClass) and the idea being that the method will then return any validation errors or if there are none simply an empty String.
This would be fine except that I use "for loops" when going through my data to validate as doing it without is just too clunky. I tried to research about arrays of methods and found plenty of useful things that work with void methods but found nothing on any methods that return variables.
In a nutshell I'm asking: Is it possible to create an array of methods (or implement an array of objects to simulate an array of methods) that return a variable?
Here is some example code, but in the actual program the method's return would actually be used further on:
public class Validation{
public static void main(String args){
ValidatorClass valTest = new ValidatorClass();
String[] dataList = {"Andrew", "Jameson", "Male"}
for(int i = 0; i < dataList.length; i++){
String errors = valTest.testInput(dataList[i], i).validationList[i];
System.out.println(errors);
}
}
}
And in ValidatorClass:
public class ValidatorClass{
public String testInput(String data, int index){
//Tests the data by calling method "index" which corresponds to data type.
//ie. validateName would be index : 1, validateSurname index : 2 etc
String errors = validationMethodList[index](data); //Somehow add data as a parameter to it
return errors;
}
public String validateName(String name){
String errors = "";
if(name.length < 1){
errors += "Name Not Entered";
}
return errors;
}
public String validateSurname(String surname){
String errors = "";
if(surname.length < 1){
errors += "Surame Not Entered";
}
return errors;
}
public String validateGender(String gender){
String errors = "";
if(!gender.equalsIgnoreCase("male") || !gender.equalsIngoreCase("female")){
errors += "Invalid Gender";
}
return errors;
}
}
I imagine that you have something like...
static String validate1(Validatible v) { /* do something */ }
static String validate2(Validatible v) { /* do something else */ }
static String validate3(Validatible v) { /* do something still else */ }
And that you want to execute, in some method...
Validatible v = getValidatible();
System.out.println(validate1(v));
System.out.println(validate2(v));
System.out.println(validate3(v));
Then perhaps you could write an interface:
public interface Validator {
String validate(Validatible v);
}
...and keep them in an array or a list...
private static final List<Validator> validators = Arrays.asList(
new Validator() {
#Override
public String validate() {
/* do something */
}
},
new Validator() {
#Override
public String validate() {
/* do something else */
}
},
new Validator() {
#Override
public String validate() {
/* do something still else */
}
}
);
// Can be written more compactly if in Java 8.
Thereafter, you can call the methods in a for-loop:
Validatible v = getValidatible();
for(Validator validator : validators) {
System.out.println(validator.validate(v));
}
Possible improvements would include using a StringBuilder to build a single String (or using the Stream API and using Collectors.joining) if this fits your purpose better.

Categories