How to find all references to a method programmatically? - java

So, this isn't how to find method references using Eclipse IDE.
I need to find them via code (Java).
Background:
We have hundreds of projects, all based off a common project. Over the years, the common project has some really bad code that has been replaced. The bad code has been marked as Deprecated.
Now, I want to remove all the deprecated code. But, I want to create some code to migrate all the other projects we have.
Approach:
Now, for some things, I could search the project code for some keywords (i.e method name) and replace with something else. However, there are some method names that would collide and doing a simple search/replace would not work.
My thought is, if I have a deprecated method:
com.foo.bar.SomeClass.someMethod(String)
Then some way to find every place that someMethod(String) is used, I could then replace that one with newMethod(String)
I have looked some at:
org.reflections.Reflections
ASM
Basically, I want to create a migration program to make migrating to the new common code simple. I plan to use this same migration code to help migrate the projects from JDK8 to OpenJDK11.
Thoughts on how I can accomplish this?

You can certainly use ASM with a ClassVisitor / MethodVisitor to find all references to this method.
You just have to override visitMethod in the ClassVisitor to return your own MethodVisitor, and in the MethodVisitor override visitMethodInsn.
In the visitMethodInsn you check if the target is one of the deprecated methods, and log where it is used. Here an example:
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import static org.objectweb.asm.Opcodes.*;
public class MethodScanner extends ClassVisitor {
private final String fileName;
private MethodScanner(String fileName) {
super(ASM7);
this.fileName = fileName;
}
public static void main(String[] args) throws IOException {
scanJar(new File("path/to/some.jar"));
}
public static void scanJar(File jarFile) throws IOException {
var jf = new JarFile(jarFile);
jf.stream().filter(je -> getFileExtension(je.getName()).equals(".class"))
.forEach(je -> processEntry(jf, je));
}
private static String getFileExtension(String name) {
int idx = name.lastIndexOf(".");
if (idx == -1)
return "";
return name.substring(idx);
}
private static void processEntry(JarFile jf, JarEntry je) {
try {
byte[] bytes = jf.getInputStream(je).readAllBytes();
MethodScanner ms = new MethodScanner(jf.getName() + "!" + je.getName());
ClassReader cr = new ClassReader(bytes);
cr.accept(ms, 0);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
#Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
return new MethodScannerVisitor(super.visitMethod(access, name, descriptor, signature, exceptions), fileName, name + descriptor);
}
private static class MethodScannerVisitor extends MethodVisitor {
private final String fileName;
private final String methodName;
private MethodScannerVisitor(MethodVisitor parent, String fileName, String methodName) {
super(ASM7, parent);
this.fileName = fileName;
this.methodName = methodName;
}
#Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
if (owner.equals("java/lang/Math") && name.equals("random") && descriptor.equals("()D")) {
System.out.println("reference to Math.random() from " + fileName + " in " + methodName);
}
}
}
}

Doing some searching, I have some base code, but still not going 100%
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class ProjectMigration {
public static void main (String[] args) {
ProjectMigration migration = new ProjectMigration();
try {
migration.migrate();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
private List<DeprecatedClass> getDeprecatedMethods () {
List<DeprecatedClass> deprecatedClasses = new ArrayList<>();
deprecatedClasses.add(
new DeprecatedClass("com.e2open.selenium.api_common.abstractHelpers.SystemInformation",
"isInternetExplorer8", "boolean", ""));
deprecatedClasses.add(
new DeprecatedClass("com.e2open.selenium.api_common.AbstractPage", "radioButtonSelect",
"boolean", "java.lang.String", "java.lang.String"));
return deprecatedClasses;
}
public void migrate ()
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
List<DeprecatedClass> deprecatedClasses = getDeprecatedMethods();
for (DeprecatedClass clazz : deprecatedClasses) {
System.out.println("CLASS: " + clazz.getClazz());
Class c = Class.forName(clazz.getClazz());
analyze(c.newInstance(), clazz);
System.out.println();
}
}
private void analyze (Object object, DeprecatedClass deprecatedClass) {
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) {
#Override
public MethodVisitor visitMethod (
int access, String name, String desc, String signature, String[] exceptions) {
if (isDeprecatedMethod(deprecatedClass, name, desc)) {
logMethod(name, desc);
return new MethodVisitor(Opcodes.ASM5) {
#Override
public void visitMethodInsn (
int opcode, String owner, String name, String desc, boolean arg4) {
if (owner.contains("e2open")) {
processMethod(owner, name, desc);
}
super.visitMethodInsn(opcode, owner, name, desc, arg4);
}
};
}
return null;
}
};
try {
ClassReader classReader = new ClassReader(object.getClass().getCanonicalName());
classReader.accept(cv, 0);
} catch (IOException e) {
System.err.println("Something went wrong !! " + e.getMessage());
}
}
protected void processMethod (String owner, String name, String desc) {
System.out.println(
"classUsed[" + owner.replace("/", ".") + "]; methodUsed[" + name + "]; methodParameters["
+ desc + "]");
}
protected void logMethod (String name, String desc) {
String returnType = getReturnType(desc);
String paramters = getParamters(desc);
System.out.println(String.format("METHOD: %s %s(%s)", returnType, name, paramters));
}
private String getParamters (String desc) {
String parms = desc.split("\\)")[0];
if (parms.equals("(")) {
return "";
}
parms = parms.substring(2, parms.length());
String[] parmameters = parms.split(";");
StringBuilder paramterString = new StringBuilder();
for (String p : parmameters) {
paramterString.append(p.replaceAll("/", ".")).append(", ");
}
return paramterString.toString().substring(0, paramterString.length() - 2);
}
private String getReturnType (String desc) {
String returnType = desc.split("\\)")[1];
if (returnType.equals("V")) {
return "void";
}
if (returnType.length() == 1) {
return returnType;
}
return returnType.substring(1, returnType.length() - 1).replace("/", ".");
}
private boolean isDeprecatedMethod (
DeprecatedClass deprecatedClass, String method, String parmeters) {
if ((method.equals(deprecatedClass.getMethod()))
&& (parmeters.equals(deprecatedClass.getParameters()))) {
return true;
}
return false;
}
private class DeprecatedClass {
private String clazz;
private String method;
private List<String> parameters;
private String returnType;
public DeprecatedClass() {}
/**
* No paramters and no return type
*
* #param clazzName The class to check. Example: com.e2open.selenium.api_common.AbstractPage
* #param methodName The method name to find references for. Example: clearAllInputFields
*/
public DeprecatedClass(String clazzName, String methodName) {
this.clazz = clazzName;
this.method = methodName;
}
/**
* Use if there is a return type and/or parameters
*
* #param clazzName The class to check. Example: com.e2open.selenium.api_common.AbstractPage
* #param methodName he method name to find references for. Example: findFieldByAttribute
* #param returnType The returned type. Example: org.openqa.selenium.By
* #param parameterValues List of paramters. Example: "java.lang.String", "java.lang.String",
* "java.lang.String"
*/
public DeprecatedClass(String clazzName, String methodName, String returnType,
String... parameterValues) {
this.clazz = clazzName;
this.method = methodName;
setReturnType(returnType);
if (parameterValues != null) {
for (String parm : parameterValues) {
if (StringUtils.isNoneBlank(parm)) {
addParameter(parm);
}
}
}
}
/**
* #return the clazz
*/
public String getClazz () {
return clazz;
}
/**
* #param clazz the clazz to set
*/
public void setClazz (String clazz) {
this.clazz = clazz;
}
/**
* #return the method
*/
public String getMethod () {
return method;
}
/**
* #param method the method to set
*/
public void setMethod (String method) {
this.method = method;
}
/**
* #param returnType the returnType to set
*/
public void setReturnType (String returnType) {
if (returnType != null) {
if ("boolean".equals(returnType)) {
this.returnType = "Z";
} else {
this.returnType = "L" + returnType.replaceAll("\\.", "/") + ";";
}
}
}
/**
* #return the parameters
*/
public String getParameters () {
StringBuilder parms = new StringBuilder();
if (this.parameters == null) {
parms.append("()");
} else {
parms.append("(").append(String.join("", this.parameters)).append(")");
}
if (this.returnType == null) {
parms.append("V");
} else {
parms.append(this.returnType);
}
return parms.toString();
}
/**
* #param parameters the parameters to set
*/
public void addParameter (String parameter) {
if (this.parameters == null) {
this.parameters = new ArrayList<>();
}
this.parameters.add("L" + parameter.replaceAll("\\.", "/") + ";");
}
}
}
The results I get is:
CLASS: com.e2open.selenium.api_common.abstractHelpers.SystemInformation
METHOD: Z isInternetExplorer8()
classUsed[com.e2open.selenium.api_common.abstractHelpers.SystemInformation]; methodUsed[getSystemData]; methodParameters[()Lcom/e2open/selenium/api_common/abstractHelpers/SystemInformation$SystemData;]
classUsed[com.e2open.selenium.api_common.browser.BrowserType]; methodUsed[equals]; methodParameters[(Ljava/lang/Object;)Z]
CLASS: com.e2open.selenium.api_common.AbstractPage
METHOD: Z radioButtonSelect(java.lang.String, Ljava.lang.String)
classUsed[com.e2open.selenium.api_common.JLog]; methodUsed[write]; methodParameters[(Ljava/lang/String;)V]
classUsed[com.e2open.selenium.api_common.AbstractPage]; methodUsed[radioButtonGet]; methodParameters[(Ljava/lang/String;Ljava/lang/String;)Lorg/openqa/selenium/WebElement;]
However, the results are not correct.
If I take one of the methods:
com.e2open.selenium.api_common.abstractHelpers.SystemInformation.isInternetExplorer8()
And use Eclipse to find References, I get
isInternetExplorer8 Eclipse References Image
And for the other method doing a search on:
com.e2open.selenium.api_common.AbstractPage.radioButtonSelect(String, String)
radioButtonSelect Eclipse Reference Image
I am unsure what to change or where to go from here.

Related

Unable to serialize property [OpenApi maven codgen plugin]

i'm using "openapi-generator-maven-plugin" version 6.2.1 for generate modules from a YAML file and consume a RestAPI.
The code that is generated from the plugin looks fine and it work great with "GET" requests, the problem that i've encountered so far, is on "POST" requests. Apparently when I pass an object with null values (even if they are nullable) it throws "Unable to serialize property" from [org.eclipse.yasson.internal.Marshaller], even if the object is Serializable.
More specific:
I've this object generated from the plugin.
/*
* MS00140
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
package org.openapitools.client.model;
import java.util.Objects;
import java.util.Arrays;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.JsonValue;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.openapitools.jackson.nullable.JsonNullable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.openapitools.jackson.nullable.JsonNullable;
import java.util.NoSuchElementException;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonTypeName;
/**
* ModelFile
*/
#JsonPropertyOrder({
ModelFile.JSON_PROPERTY_LINK,
ModelFile.JSON_PROPERTY_NAME,
ModelFile.JSON_PROPERTY_MIME_TYPE,
ModelFile.JSON_PROPERTY_DATA
})
#JsonTypeName("File")
#javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2022-11-21T13:50:57.834020300+01:00[Europe/Berlin]")
public class ModelFile implements Serializable {
private static final long serialVersionUID = 1L;
public static final String JSON_PROPERTY_LINK = "link";
private JsonNullable<String> link = JsonNullable.<String>undefined();
public static final String JSON_PROPERTY_NAME = "name";
private JsonNullable<String> name = JsonNullable.<String>undefined();
public static final String JSON_PROPERTY_MIME_TYPE = "mimeType";
private JsonNullable<String> mimeType = JsonNullable.<String>undefined();
public static final String JSON_PROPERTY_DATA = "data";
private JsonNullable<byte[]> data = JsonNullable.<byte[]>undefined();
public ModelFile() {
}
public ModelFile link(String link) {
this.link = JsonNullable.<String>of(link);
return this;
}
/**
* Get link
* #return link
**/
#javax.annotation.Nullable
#ApiModelProperty(value = "")
#JsonIgnore
public String getLink() {
return link.orElse(null);
}
#JsonProperty(JSON_PROPERTY_LINK)
#JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public JsonNullable<String> getLink_JsonNullable() {
return link;
}
#JsonProperty(JSON_PROPERTY_LINK)
public void setLink_JsonNullable(JsonNullable<String> link) {
this.link = link;
}
public void setLink(String link) {
this.link = JsonNullable.<String>of(link);
}
public ModelFile name(String name) {
this.name = JsonNullable.<String>of(name);
return this;
}
/**
* Get name
* #return name
**/
#javax.annotation.Nullable
#ApiModelProperty(value = "")
#JsonIgnore
public String getName() {
return name.orElse(null);
}
#JsonProperty(JSON_PROPERTY_NAME)
#JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public JsonNullable<String> getName_JsonNullable() {
return name;
}
#JsonProperty(JSON_PROPERTY_NAME)
public void setName_JsonNullable(JsonNullable<String> name) {
this.name = name;
}
public void setName(String name) {
this.name = JsonNullable.<String>of(name);
}
public ModelFile mimeType(String mimeType) {
this.mimeType = JsonNullable.<String>of(mimeType);
return this;
}
/**
* Get mimeType
* #return mimeType
**/
#javax.annotation.Nullable
#ApiModelProperty(value = "")
#JsonIgnore
public String getMimeType() {
return mimeType.orElse(null);
}
#JsonProperty(JSON_PROPERTY_MIME_TYPE)
#JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public JsonNullable<String> getMimeType_JsonNullable() {
return mimeType;
}
#JsonProperty(JSON_PROPERTY_MIME_TYPE)
public void setMimeType_JsonNullable(JsonNullable<String> mimeType) {
this.mimeType = mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = JsonNullable.<String>of(mimeType);
}
public ModelFile data(byte[] data) {
this.data = JsonNullable.<byte[]>of(data);
return this;
}
/**
* Get data
* #return data
**/
#javax.annotation.Nullable
#ApiModelProperty(value = "")
#JsonIgnore
public byte[] getData() {
return data.orElse(null);
}
#JsonProperty(JSON_PROPERTY_DATA)
#JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public JsonNullable<byte[]> getData_JsonNullable() {
return data;
}
#JsonProperty(JSON_PROPERTY_DATA)
public void setData_JsonNullable(JsonNullable<byte[]> data) {
this.data = data;
}
public void setData(byte[] data) {
this.data = JsonNullable.<byte[]>of(data);
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ModelFile _file = (ModelFile) o;
return equalsNullable(this.link, _file.link) &&
equalsNullable(this.name, _file.name) &&
equalsNullable(this.mimeType, _file.mimeType) &&
equalsNullable(this.data, _file.data);
}
private static <T> boolean equalsNullable(JsonNullable<T> a, JsonNullable<T> b) {
return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
}
#Override
public int hashCode() {
return Objects.hash(hashCodeNullable(link), hashCodeNullable(name), hashCodeNullable(mimeType), hashCodeNullable(data));
}
private static <T> int hashCodeNullable(JsonNullable<T> a) {
if (a == null) {
return 1;
}
return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ModelFile {\n");
sb.append(" link: ").append(toIndentedString(link)).append("\n");
sb.append(" name: ").append(toIndentedString(name)).append("\n");
sb.append(" mimeType: ").append(toIndentedString(mimeType)).append("\n");
sb.append(" data: ").append(toIndentedString(data)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
When I make the request the only property that I set for the moment is the "link" property, because the REST service knows what to do.
public File getFileByLink(String link) throws WebServiceException, DataNotFoundException {
log.debug("Executing---> getFileByLink()");
File file;
try {
ModelFile inputFile = new ModelFile();
inputFile.setLink(link);
file = utilityApi.apiUtilityGetFileByLinkPost(inputFile);
if (file == null) {
throw new DataNotFoundException("Error!");
}
} catch (ApiException e) {
throw new WebServiceException(e.getCode() + " - " + e.getMessage());
} catch (DataNotFoundException e) {
throw e;
} catch (Exception e) {
throw new WebServiceException(e);
}
log.debug("Leaving ---> getFileByLink()");
return file;
}
Now when it perform the actual request and try to serialize the object throws this error:
13:55:36,124 SEVERE [org.eclipse.yasson.internal.Marshaller] (default task-1) Unable to serialize property 'data_JsonNullable' from org.openapitools.client.model.ModelFile
13:55:36,133 SEVERE [org.eclipse.yasson.internal.Marshaller] (default task-1) Generating incomplete JSON
13:55:36,145 ERROR [it.inps.itg.web.exception.WebServiceException] (default task-1) WebServiceException in Class: TemplateAction.java and Method: executeAction Message: RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY008205: JSON Binding serialization error javax.json.bind.JsonbException: Unable to serialize property 'data_JsonNullable' from org.openapitools.client.model.ModelFile Cause: javax.ws.rs.ProcessingException: RESTEASY008205: JSON Binding serialization error javax.json.bind.JsonbException: Unable to serialize property 'data_JsonNullable' from org.openapitools.client.model.ModelFile
At first I didn't use the property <serializableModel>true</serializableModel>, and I thought that the object could not be searialized for this problem, but even if the class implement the Serializable interface the problem still occur.
If can help, I've tried to set values to all the object's properties and as long as they are not null, there's non serialization problems. The problem occur when there's at least one property that is null.

Convert comma separated key=value pairs to Java object

I'm trying to implement a HttpMessageConverter which would allow my program to talk over REST to an embedded smart controller.
The controller responds with strings such as:
ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
I have a Java object called SensorInfo.
public class SensorInfo {
String ret;
Double htemp;
String hhum;
Double otemp;
Integer err;
Integer cmpfreq;
// getters and setters
}
What's the best way of mapping the controller response to the above Java object?
You can simply split the string and assign each element as needed. You have:
ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
Lets assume you have that stored in a variable called myStr. Then all you need to do is this:
String[] strSplit = myStr.split(" ");
SensorInfo info = new SensorInfo();
info.ret = afterEquals(strSplit[0]);
info.htemp = Double.parse(afterEquals(strsplit[1]));
info.hhum = afterEquals(strSplit[2]);
info.otemp= Double.parse(afterEquals(strSplit[3]));
info.err = Integer.parse(afterEquals(strSplit[4]));
info.cmpfreq = Integer.parse(afterEquals(strSplit[5]));
You will declare a method to extract the part of the response after the equals sign to make the above work:
private String afterEquals(String input) {
input.substring(input.indexOf('=') + 1);
}
Note that this assumes the order of your response is fixed. If it isn't, you can easily modify this to look at each argument to see which variable to assign it to.
You should add error handling, as the following is not really error prone, but might help you:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ValueAssigner {
// ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
String ret;
Double htemp;
String hhum;
Double otemp;
Integer err;
Integer cmpfreq;
public static void main(String[] a) {
System.out.println(new ValueAssigner("ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24").getCmpfreq());
}
ValueAssigner(String in) {
String[] split = in.split(",");
for (String s : split) {
Method method;
String[] keyValue = s.split("=");
try {
method = this.getClass().getMethod("set" + ucFirst(keyValue[0]), String.class);
method.invoke(this, keyValue[1]);
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException | SecurityException | NoSuchMethodException e) {
// e.printStackTrace();
// omitted here
}
}
}
private static String ucFirst(String in) {
return in.substring(0, 1).toUpperCase() + in.substring(1);
}
public String getRet() {
return ret;
}
public void setRet(String ret) {
this.ret = ret;
}
public Double getHtemp() {
return htemp;
}
public void setHtemp(String htemp) {
this.htemp = Double.parse(htemp);
}
public String getHhum() {
return hhum;
}
public void setHhum(String hhum) {
this.hhum = hhum;
}
public Double getOtemp() {
return otemp;
}
public void setOtemp(String otemp) {
this.otemp = Double.parse(otemp);
}
public Integer getErr() {
return err;
}
public void setErr(String err) {
this.err = Integer.parse(err);
}
public Integer getCmpfreq() {
return cmpfreq;
}
public void setCmpfreq(String cmpfreq) {
this.cmpfreq = Integer.parse(cmpfreq);
}
}

Create map of maps from eclipse toString()

Eclipse can auto-generate a toString() method from a object's fields. If those fields are objects then they too may have similarly auto-generated toString() methods.
e.g. a President object might look like this:
President [country=USA, name=Name [title=Mr, forename=Barack, surname=Obama], address=Address [houseNumber=1600, street=Pennsylvania Avenue, town=Washington]]
which is easier to read if I format it:
President [
country=USA,
name=Name [
title=Mr,
forename=Barack,
surname=Obama],
address=Address [
houseNumber=1600,
street=Pennsylvania Avenue,
town=Washington]]
What is the best way to parse this String to create a map of maps?
I've got a solution, but it's not pretty. I was hoping to be able to avoid the low level String manipulation somehow, but here it is:
import java.util.LinkedHashMap;
import java.util.Map;
public class MappedObject {
public String className;
public Map<String, String> leafFields = new LinkedHashMap<>();
public Map<String, MappedObject> treeFields = new LinkedHashMap<>();
#Override
public String toString() {
return "[className=" + className
+ (leafFields.isEmpty() ? "" : ", leafFields=" + leafFields)
+ (treeFields.isEmpty() ? "" : ", treeFields=" + treeFields)
+ "]";
}
public static MappedObject createFromString(String s) {
MappedObject mo = new MappedObject();
new Mapper(s).mapObject(mo);
return mo;
}
private static class Mapper {
private String s;
public Mapper(String s) {
this.s = s;
}
private String mapObject(MappedObject mo) {
mo.className = removeFirstNCharacters(s.indexOf(' '));
while (s.contains("=")) {
removeLeadingNonLetters();
String key = removeFirstNCharacters(s.indexOf('='));
removeFirstNCharacters(1); // remove the =
String leafValue = getLeafValue();
if (leafValue != null) {
mo.leafFields.put(key, leafValue);
if (s.startsWith("]")) { // that was the last field in the tree
return s;
}
} else {
MappedObject treeField = new MappedObject();
mo.treeFields.put(key, treeField);
s = new Mapper(s).mapObject(treeField);
}
}
return s; // s contains only close brackets - ]
}
private void removeLeadingNonLetters() {
int i = 0;
while (!Character.isLetter(s.charAt(i))) {
i++;
}
removeFirstNCharacters(i);
}
private String removeFirstNCharacters(int n) {
String value = s.substring(0, n);
s = s.substring(value.length());
return value;
}
private String getLeafValue() {
int endIndex = getEndIndex();
if (!s.contains("[") || s.indexOf('[') > endIndex) {
return removeFirstNCharacters(endIndex);
}
return null;
}
/** The end of the value, if it's a leaf field. */
private int getEndIndex() {
if(s.contains(",")) {
return Math.min(s.indexOf(','), s.indexOf(']'));
}
return s.indexOf(']');
}
}
}

How to add code to a method

Hello I just want to ask how should i get the codes function into a method which is run by the main at the moment! Basically so that I can activate the working method from the main instead. I am new to programming so I am having quite a bit of trouble grasping everything properly
package bla_bla;
import java.io.IOException;
import java.util.ArrayList;
import java.util.*;
import javax.swing.text.html.parser.Element;
import org.codehaus.jackson.map.ObjectMapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.jsoup.select.Evaluator.Id;
import org.json.*;
import argo.saj.InvalidSyntaxException;
public class supermonkey {
private static ArrayList<BugsList> bugsList;
private static ArrayList<BugsList> bugbug;
public static void main(String args[]) throws IOException {
bugsList = new ArrayList<BugsList>();
bugbug = new ArrayList<BugsList>();
Document doc = Jsoup.connect("https://bugzilla.mozilla.org/rest/bug?product=Input&f1=bug_mentor&o1=isnotempty").get();
String rawData = doc.body().text();
// System.out.println(title);
JSONObject obj = new JSONObject(rawData);
// System.out.println(obj);
System.out.println(obj.get("bugs"));
JSONArray jsonMainArr = new JSONArray(obj.get("bugs").toString());
for (int i = 0; i < jsonMainArr.length(); i++) { // **line 2**
JSONObject childJSONObject = jsonMainArr.getJSONObject(i);
JSONObject assigned = childJSONObject.getJSONObject("assigned_to_detail");
// JSONObject assigned2 = childJSONObject.getJSONObject("assigned_to_detail");
int id = assigned.getInt("id");
BugsList bug = new BugsList();
BugsList bug2 = new BugsList();
bug.setId(id);
String severity = childJSONObject.getString("severity");
String resolution = childJSONObject.getString("resolution");
String summary = childJSONObject.getString("summary");
String component = childJSONObject.getString("component");
bug.setSeverity(severity);
bug.setResolution(resolution);
bug.setSummary(summary);
bug.setComponent(component);
bugsList.add(bug);
// String severity = assigned.getString();
// System.out.println("sss "+ assigned);
}
getComponent("Code Quality");
// getSeverity(524276);
// getResolution(524276);
// getSummary(524276);
}
public static void getSeverity(int id){
for(int i =0;i<bugsList.size(); i++){
if(bugsList.get(i).getId() == id){
System.out.println("The id exists in the list " + bugsList.get(i).getSeverity());
}
}
}
public static void getResolution(int id){
for(int i =0;i<bugsList.size(); i++){
if(bugsList.get(i).getId() == id){
System.out.println("The id exists in the list and The resolution is" + bugsList.get(i).getResolution());
}
}
}
public static void getSummary(int id){
for(int i =0;i<bugsList.size(); i++){
if(bugsList.get(i).getId() == id){
System.out.println("The comp.. exists in the list and The summary is " + bugsList.get(i).getSummary());
}
}
}
// Current used method
public static ArrayList<BugsList> getComponent(String component){
for(int i =0;i<bugsList.size(); i++){
if(bugsList.get(i).getComponent().equals(component)){
System.out.println("(Code Quality) component contains summary " + bugsList.get(i).getSummary() +" /The resolution is " +
bugsList.get(i).getResolution() + " /Severity is " + bugsList.get(i).getSeverity());
bugbug.add(bugsList.get(i));
}
}
return bugbug;
}
}
package bla_bla;
public class BugsList {
private String severity;
private int id;
private String resolution;
private String summary;
private String component;
public String getComponent() {
return component;
}
public void setComponent(String component) {
this.component = component;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getResolution() {
return resolution;
}
public void setResolution(String resolution) {
this.resolution = resolution;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
I think I understand you problem. You write your code into the main function and that not the solution.
Your main function should look something like that:
public static void main(String args[]) throws IOException {
Supermonkey supermonkey = new Supermonkey();
supermonkey.getComponent("componennt name ");
}
Your Class is Supermonkey and you create an instance call supermonkey (sometime people use mySupermonkey) . There is only one instance of this class that will use.
Then into the constructor method you can create everything to build your instance supermonkey as :
public class Supermonkey {
private ArrayList<BugsList> bugsList;
private ArrayList<BugsList> bugbug;
public Supermonkey(){
bugsList = new ArrayList<BugsList>();
bugbug = new ArrayList<BugsList>();
Document doc = Jsoup
.connect(
"https://bugzilla.mozilla.org/rest/bug?product=Input&f1=bug_mentor&o1=isnotempty")
.get();
String rawData = doc.body().text(); // ... partial code add everything about initialisation of your instance
Then you can have a method of this Class Supermonkey
// Current used method
public ArrayList<BugsList> getComponent(String component) {
for (int i = 0; i < bugsList.size(); i++) {
if (bugsList.get(i).getComponent().equals(component)) {
System.out
.println("(Code Quality) component contains summary "
+ bugsList.get(i).getSummary()
+ " /The resolution is "
+ bugsList.get(i).getResolution()
+ " /Severity is "
+ bugsList.get(i).getSeverity());
bugbug.add(bugsList.get(i));
}
}
return bugbug;
}
A this method is call from the public static void main(String args[]) with supermonkey.getComponent("componennt name ");
Also I think about to change the name of Class BugsList it seems to be a BugItem , may be ?

Java: standard library to convert field name ("firstName") to accessor method name ("getFirstName")

Is there a standard library (such as org.apache.commons.beanutils or java.beans) that will take a string field name and convert it to the standard method name? I'm looking all over and can't find a simple string conversion utility.
The JavaBean introspector is possibly the best choice. It handles "is" getters for boolean types and "getters" which take an argument and setters with none or two arguments and other edge cases. It is nice for getting a list of JavaBean fields for a class.
Here is an example,
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
public class SimpleBean
{
private final String name = "SimpleBean";
private int size;
public String getName()
{
return this.name;
}
public int getSize()
{
return this.size;
}
public void setSize( int size )
{
this.size = size;
}
public static void main( String[] args )
throws IntrospectionException
{
BeanInfo info = Introspector.getBeanInfo( SimpleBean.class );
for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
System.out.println( pd.getName() );
}
}
This prints
class
name
size
class comes from getClass() inherited from Object
EDIT: to get the getter or setter and its name.
public static String findGetterName(Class clazz, String name) throws IntrospectionException, NoSuchFieldException, NoSuchMethodException {
Method getter = findGetter(clazz, name);
if (getter == null) throw new NoSuchMethodException(clazz+" has no "+name+" getter");
return getter.getName();
}
public static Method findGetter(Class clazz, String name) throws IntrospectionException, NoSuchFieldException {
BeanInfo info = Introspector.getBeanInfo(clazz);
for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
if (name.equals(pd.getName())) return pd.getReadMethod();
throw new NoSuchFieldException(clazz+" has no field "+name);
}
public static String findSetterName(Class clazz, String name) throws IntrospectionException, NoSuchFieldException, NoSuchMethodException {
Method setter = findSetter(clazz, name);
if (setter == null) throw new NoSuchMethodException(clazz+" has no "+name+" setter");
return setter.getName();
}
public static Method findSetter(Class clazz, String name) throws IntrospectionException, NoSuchFieldException {
BeanInfo info = Introspector.getBeanInfo(clazz);
for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
if (name.equals(pd.getName())) return pd.getWriteMethod();
throw new NoSuchFieldException(clazz+" has no field "+name);
}
A wild one-liner appeared!
String fieldToGetter(String name)
{
return "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
You can use a PropertyDescriptor without an Inspector (which was suggested by Peter):
final PropertyDescriptor propertyDescriptor =
new PropertyDescriptor("name", MyBean.class);
System.out.println("getter: " + propertyDescriptor.getReadMethod().getName());
System.out.println("setter: " + propertyDescriptor.getWriteMethod().getName());
String fieldToSetter(String name)
{
return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
With copyright by Matt Ball
I modified the methods above, to remove the underscore character and capitalize the next character... for instance, if the field name is "validated_id", then the getter method name will be "getValidatedId"
private String fieldToGetter(String name) {
Matcher matcher = Pattern.compile("_(\\w)").matcher(name);
while (matcher.find()) {
name = name.replaceFirst(matcher.group(0), matcher.group(1).toUpperCase());
}
return "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
private String fieldToSetter(String name) {
Matcher matcher = Pattern.compile("_(\\w)").matcher(name);
while (matcher.find()) {
name = name.replaceFirst(matcher.group(0), matcher.group(1).toUpperCase());
}
return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
Guava CaseFormat will do it for you.
For example from lower_underscore -> LowerUnderscore
CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, str)
In the following example two fields named example and eXample have the getters
getExample and geteExample IF generated by eclipse. BUT this is not compatible with PropertyDescriptor("eXample",...).getReadMethod().getName() which expects getEXample as a valid getter name.
public class XX {
private Integer example;
private Integer eXample;
public Integer getExample() {
return example;
}
public Integer geteXample() {
return eXample;
}
public void setExample(Integer example) {
this.example = example;
}
public void seteXample(Integer eXample) {
this.eXample = eXample;
}
public static void main(String[] args) {
try {
System.out.println("Getter: " + new PropertyDescriptor("example", ReflTools.class).getReadMethod().getName());
System.out.println("Getter: " + new PropertyDescriptor("eXample", ReflTools.class).getReadMethod().getName());
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
}
String fieldToGetter(Field field) {
final String name = field.getName();
final boolean isBoolean = (field.getType() == Boolean.class || field.getType() == boolean.class);
return (isBoolean ? "is" : "get") + name.substring(0, 1).toUpperCase() + name.substring(1);
}
String fieldToGetter(boolean isBoolean, String name) {
return (isBoolean ? "is" : "get") + name.substring(0, 1).toUpperCase() + name.substring(1);
}

Categories

Resources