In MainActivity.java, I have the following
classofmethods new1 = new classofmethods();
static getset GS = new GS();
.....
code .....
settle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String keyword1 = nc.methodName(String, String, int);
GS.setkeyword(keyword1);
try {
//Method 1 makes an API call...Trying to set an //endpoint but the URL prints out as ....keyword=null;
new1.method1();
new1.method2();
new1.method3();
new1.method4();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
GS
String keyword = null;
public String getkeyword() {
return keyword;
}
public void setkeyword(String keyword) {
this.keyword = keyword;
}
My problem is that the onClick executes my desired code, however it will not set the keyword.
In the GS class, I declared keyword as "public String keyword = null;"
The API when executed in method1() returns null.
I guess it is a timing issue? I have looked at other threads but no solutions. I have another activity that adjust users settings and those values are passed through the API correctly.
Edit: this is why stack overflow has post quality guidelines. I failed to provide enough info.
In my classofmethods:
keyword was declared like: public String keyword = GS.getkeyword();
endpoint was specified like: &keyword=" + keyword
fix was: &keyword=" + MainActivity.GS.getkeyword()
Use this
private String keywword;
public String getkeyword() {
return keyword;
}
public void setkeyword(String keyword) {
this.keyword = keyword;
}
Related
This question already has answers here:
Printing debug info on errors with java 8 lambda expressions
(2 answers)
How can I find the target of a Java8 method reference?
(2 answers)
Closed 3 years ago.
If a method in a library is called with a Java Lambda expression, these are often just wrapped method calls. Is it possible to find out what method that originally was, just for logging purposes? (Another question is about what object it applies to - this is specifically about the called method.)
class Foo {
private void doSomething() { ... }
public void doSomethingInTransaction() {
doInTransaction(this::doSomething);
}
private void doInTransaction(Runnable run) { ... }
}
When calling doSomethingInTransaction() the method doInTransaction is actually called with an Object of type Runnable. It would sometimes be nice to log the name and class of the method that was passed here (that is, Foo.doSomething), as well as the object. Is it somehow possible to find out what that was via reflection or whatnot? If that requires specific Java versions, that'd be an interesting answer, too.
(UPDATE: please note that this is not a duplicate of the related question Java 8 - how to access object and method encapsulated as lambda since I'm mostly asking for the method that is encapsulated there. That wasn't asked there.)
The following example shows how to get the method reference name from the runnable. As explained in the comments, the code may be unnecesserarily complex and only works for certain cases (including the one in the question). Also, it makes certain assumptions that don't work in the general case.
Example class:
public class Test {
public void callingMethod() {
this.acceptingMethod(this::methodReferenceMethod);
}
public void acceptingMethod(final Runnable runnable) {
final String name = Util.getRunnableName(runnable, "acceptingMethod");
System.out.println("Name is " + name);
}
public void methodReferenceMethod() {
}
public static void main(final String[] args) {
new Test().callingMethod();
}
}
Now the actual magic here:
class Util {
public static String getRunnableName(final Runnable runnable, final String calledMethodName) {
final String callSiteMethodName = getCallSiteMethodNameNotThreadSafe();
final Class<?> callSiteClass = getDeclaringClass(runnable);
final String runnableName = extractRunnableName(callSiteClass, callSiteMethodName, calledMethodName);
return runnableName;
}
private static String extractRunnableName(
final Class<?> callSiteClass,
final String callSiteMethodName,
final String calledMethodName) {
try {
final AtomicReference<String> result = new AtomicReference<>(null);
final ClassReader cr = new ClassReader(callSiteClass.getName());
final TraceClassVisitor traceVisitor = new TraceClassVisitor(new PrintWriter(System.out));
cr.accept(new CheckClassAdapter(Opcodes.ASM7, traceVisitor, false) {
#Override
public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
if (!name.equals(callSiteMethodName)) {
return super.visitMethod(access, calledMethodName, descriptor, signature, exceptions);
}
return new CheckMethodAdapter(Opcodes.ASM7, super.visitMethod(access, name, descriptor, signature, exceptions), new HashMap<>()) {
#Override
public void visitInvokeDynamicInsn(final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments) {
final String invokeDynamic = ((Handle) bootstrapMethodArguments[1]).getName();
result.set(invokeDynamic);
}
};
}
}, 0);
return result.get();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
public static String getCallSiteMethodNameNotThreadSafe() {
final int depth = 4;
return Thread.currentThread().getStackTrace()[depth].getMethodName();
}
public static Class<?> getDeclaringClass(final Runnable runnable) {
return Arrays.stream(runnable.getClass().getDeclaredFields())
.filter(f -> f.getName().equals("arg$1"))
.map(f -> {
f.setAccessible(true);
try {
return f.get(runnable).getClass();
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
})
.findFirst()
.orElseThrow(IllegalStateException::new);
}
}
The output is as expected "Name is methodReferenceMethod". I would probably never use this in any project, but I guess it is possible. Also, this only works for the given example, as there is only one INVOKEVIRTUAL in the calling method. For the general case, one would need to adjust the checkMethodVisitor and filter the calls to the "calledMethodName" only. Lastly, the code to get the calling method uses a fixed index for the stack trace element, which also does not generalize well.
I'm trying to read a csv and storing the records in an ArrayList.
Since I know the no. of records in the csv file I'm specifying the size i.e. 600 when creating the object.
I want the program to be able to read files of unknown no. of records.
How do I make it dynamic.
Here's the working code for the file with 600 records.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.*;
public class BankRecords extends Client{
//Create objects for processing data
//private static int count;
static BankRecords[] obj=new BankRecords[600];
static List<List<String>> array = new ArrayList<List<String>>();
#Override
void readData() {
// TODO Auto-generated method stub
String line=" ";
//int i=0;
//try with resources statement
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
array.add(Arrays.asList(line.split(",")));
//check data
//count++;
//System.out.println(array.get(i++));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
processData();
}
#Override
void processData() {
// TODO Auto-generated method stub
int idx=0;
for(List<String> bankData: array)
{
obj[idx]= new BankRecords();
obj[idx].setId(bankData.get(0));
obj[idx].setAge(Integer.parseInt(bankData.get(1)));
obj[idx].setSex(bankData.get(2));
obj[idx].setRegion(bankData.get(3));
obj[idx].setIncome(Double.parseDouble(bankData.get(4)));
obj[idx].setMarried(bankData.get(5));
obj[idx].setChild(Integer.parseInt(bankData.get(6)));
obj[idx].setCar(bankData.get(7));
obj[idx].setSact(bankData.get(8));
obj[idx].setCact(bankData.get(9));
obj[idx].setMort(bankData.get(10));
obj[idx].setPep(bankData.get(11));
idx++;
//System.out.println(obj[idx].getId());
}
printData();
}
#Override
void printData() {
//Printing First 25 ID, age, sex, region, income and mortgage
System.out.println("ID\t\tAGE\t\tSEX\t\tREGION\t\tINCOME\t\tMORTGAGE\n");
for(int i=0;i<25;i++){
String s=String.format("%s\t\t%s\t\t%s\t\t%-10s\t%8.2f\t%2s", obj[i].getId(),obj[i].getAge(),obj[i].getSex(),obj[i].getRegion(),obj[i].getIncome(),obj[i].getMort());
System.out.println(s);
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public String isMarried() {
return married;
}
public void setMarried(String married) {
this.married = married;
}
public int getChild() {
return child;
}
public void setChild(int child) {
this.child = child;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getSact() {
return sact;
}
public void setSact(String sact) {
this.sact = sact;
}
public String getCact() {
return cact;
}
public void setCact(String cact) {
this.cact = cact;
}
public String getMort() {
return mort;
}
public void setMort(String mort) {
this.mort = mort;
}
public String getPep() {
return pep;
}
public void setPep(String pep) {
this.pep = pep;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BankRecords bnk= new BankRecords();
bnk.readData();
}
}
ArrayList can the elements dynamically, so it is not required to know the size in advance.
However, for the BankRecords array, do not initialize it with 600 initially. Instead do something like this:
static BankRecords[] obj = null;
static List<List<String>> array = new ArrayList<List<String>>();
void processData() {
// TODO Auto-generated method stub
obj=new BankRecords[array.size()];
// TODO do your work here
}
You do not have to know the number of records beforehand in order to use an ArrayList. You can specify a default size in the constructor, however it is smart enough to expand itself if you add more records than this.
You are almost there, but for some strange reasons you are using Lists in places where you already have an array; yet on the other side, you are using an array where a List would be a much better fit.
You can rework your code as follows:
// TODO Auto-generated method stub
HINT: those TODOs are generated by your IDE. The idea is that you delete them as soon as you have some real content instead. Keeping them means leaving garbage in your source code. Anything that doesn't add real value to your source code: remove it. Always. Immediately!
String line=" ";
List<Bankrecord> records = new ArrayList<>();
//int i=0; ... again: unused code --- remove that!
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
String[] lineData = line.split(",");
BankRecord recordForNewLine = buildRecordFrom(lineData);
records.add(recordForNewLine);
} ...
And then you could rework your processData into something like:
private BankRecord buildRecordFrom(String[] lineData) {
BankRecord newRecord = new BankRecords();
newRecord.setId(lineData[0];
...
return newRecord;
}
And things that you should really consider changing, too:
Building your bank records by simply assuming that column contains a valid ID, and the next column contains a valid xyz ... is a bad idea.
Instead, you should be validating all your input: you should check that each array you gain from split has **exactly the expected length. And then have to validate that each value from that array has the expected "content"
Then, from a modelling perspective: you have a ton of setters on your Bankrecord class. But that is simply wrong! In real life, when some "record" is created, then its essential properties (such as its ID) can't be changed after creation!
Instead, you should make sure that such properties in your class can't be changed after the object has been created. The way to go here: Builder pattern!
Finally: my code above is meant as "inspiration point" to get you going. Dont blindly copy/paste it; there might be various typos in - just read it until you get what (and why) it is doing (what it is doing)!
Then: I hope you understand that real CSV parsing is much more complicated than splitting around "," (for example: strings in CSV data can contain ',' too; and then your simple split would rip up that string!)
If you are serious about parsing real-world-other-people CSV input, then you better look into using existing libraries to do this for you. Writing a correct CSV parser is hard work (and not very rewarding; since that means re-inventing a complicated wheel for no good reason)!
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.
I want to design API which could handle XPATH input from user.
Currently i have model the XPATH input in following way,
public interface ICondition {
String getConditionString();
}
public class XPathCondition implements ICondition {
private Class<? extends XPATHFunction> clazz = null;
private Operator operator = null;
private String compValue = null;
private String param = null;
public void setXPathFunction(Class<? extends XPATHFunction> clazz) {
this.clazz = clazz;
}
public void setComparisionType(Operator operator) {
this.operator = operator;
}
public void setComparisionValue(String value) {
this.compValue = value;
}
public void setParam(String param) {
this.param = param;
}
public String getConditionString() {
XPATHFunction function = null;
try {
function = (XPATHFunction) clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return function.call(param) + operator.getOprValue() + compValue;
}
public static void main(String[] args) {
XPathCondition xpathCond = new XPathCondition();
xpathCond.setXPathFunction(CountFunction.class);
xpathCond.setParam("/CPRRegistrationInfo/*");
xpathCond.setComparisionType(Operator.GT);
xpathCond.setComparisionValue("0");
System.out.println(xpathCond.getConditionString());
}
}
public interface XPATHFunction {
public String call(String param);
}
public class CountFunction implements XPATHFunction {
public String call(String param) {
return "count(" + param + ") ";
}
}
There could be other XPATH function which have to implement and interface XPATHFunction and implement it in its way.
API just have create XPATHCondition and set appropriate function and call getConditionString() method to get the final xpath.
Is there any better way, we can model XPATH input?
Please help me to re factor the above design.
I don't think I cannot really comment on your class structure or suggest something different. It is a very tough problem.
What I'd suggest is:
Start with some simple sub-set of the full XPath syntax
Instead of starting from the design of the API and the classes start designing the user interface: what are you going to show the user? What are his/her possible actions? The class design should then derive from the UI design.
If possible use a schema for the underlying XML, so that you can present the user with a limited choice of the possible element and attribute name to use in the expression
The dialogue and the array displays just fine, I just want to be able to set the static variable from the originating class within the onClick that is in a method that is in a different class. All of the try, catch and
<?> were things that I put in at the insistence of the compiler:
public class Setter
{
public void myList(Context context, Class<?> thisclass, int arrayid, String choice)
{
return new AlertDialog.Builder(context)
.setItems(arrayid, new OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
setChoice(thisclass, context, arrayid, which, choice);
}
})
.create();
}
public void setChoice(Class<?> thisclass, Context context, int arrayid, int which, String choice)
{
String[] array = context.getResources().getStringArray(arrayid);
try
{
Field f = thisclass.getDeclaredField(choice);
f.set(null, array[which]);
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
public class ClassA extends Activity
{
static String stringa;
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
AlertDialog thinga = setted.myList(this, getclass(), R.array.thinga, stringa).show();
...
}
}
When I select an item from the list, I get this from debugger:
ClassCache.findFieldByName(Field[], String) line: 438
Class.getDeclaredField(String) line: 666
Setter.setChoice(Class, Context, int, int, String) line: 45 // the line with the Field
I think I'm passing it the class wrong but this is a bit out of my current depth.
I have a number of different classes each with their own static Strings. I am passing the method below the name of the String (in choice) and the context of what I had hoped was the original class that called a method that called a method that led to the code below. I was hoping I could call context.choice = something and the machine would read that as ClassA.stringa = something; how do I do that?
Briefly, I want to have a list of items that the user can choose from be the content of a dialogue, and have their selection be saved and accessible to the class that called for the creation of the dialogue. Perhaps I'm going about this all wrong but I got tired of dealing with other 'kludges' involving using spinners to do the same thing.
Because onClick can't have non-final objects declared elsewhere (at least that is my understanding) I thought maybe I could get around that by calling to another method, setChoice that would store the value of whatever was chosen. I would definitively say this is a kludge and would love to be shown the light as to how you are supposed to deal with these things.
Java does not have closures, but you can get close with anonymous inner classes.
String output;
public void onCreate() {
Setter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
output = "selected";
}
});
}
See also this swing tutorial: http://download.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
Edit:
In spirit of your example, this should look like this:
public class Setter
{
public void setChoice(IsetString setter, String something)
{
setter.setString(something);
}
}
class ClassA extends Activity implements setString
{
static String stringa;
string polka = "dots";
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
setted.setChoice(new IsetString() {
#Override
public void setString(String s) {
stringa = s;
}
}, polka);
...
}
}
interface IsetString {
void setString(String s);
}
The short answer - use the Reflection API.
The long answer - you'll need to obtain access to the Fields of the desired Context Class. Once you gain access to the Field instances, you can set their values using the set() method; the API call is a bit tricky in that you'll need to pass in the object reference (the context object and not the context class) whose field you wish to modify.
It is necessary that your Context, choice and something parameters to the method, contain the necessary information to make this operation as simple as possible. In other words, the Context class might have to contain the actual Class object (or provides a way to get one) that contains the field.
You can use reflection for that. Suppose you context is class itself
public void setChoice(Class<?> context, String choice, String something)
{
try {
Field f = context.getDeclaredField(choice);
f.set(null, something);
} catch (....) {
}
}
Add proper exception handling
Note that first argument to set is null. That is only valid for static methods. So you may want to check that method is static using f.getModifiers().