Mass Java code file modifying - Remove methods, annotations, etc - java

I got a bundle of code from an very old project, which they generated many redundancy methods and annotations.
Is there anyway that fast, to remove -method "doOldThing()"- from all classes in this package; remove all #AnnotationObsoluted in all class?
I know that we can use search and replace, but writing regex to delete those take a long time. I guess we could have someway to parse a Java file, then remove "doOldThings()" method, check if #AnnotationObsoluted there then remove. Any idea? Tks.

In case anyone interest, here is the code for small util that I wrote to clean up methods (by name) and import statement as well.
import com.googlecode.java2objc.main.Config;
import com.googlecode.java2objc.main.Main;
import japa.parser.ASTHelper;
import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.ImportDeclaration;
import japa.parser.ast.body.*;
import japa.parser.ast.expr.AnnotationExpr;
import japa.parser.ast.type.ClassOrInterfaceType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* User: lent
* Date: 10/01/2014
*/
public class CleanUpAndModelRegeneration
{
public static void main(String... args) throws IOException, ParseException
{
List<File> results =
listFilesForFolder(new File("\\LocationOfYourCode"), new ArrayList<File>());
List<String> javaFiles = new ArrayList<String>();
for (File codeFile : results)
{
// creates an input stream for the file to be parsed
FileInputStream in = new FileInputStream(codeFile);
CompilationUnit cu = null;
try
{
// parse the file
cu = JavaParser.parse(in);
removeMethod(cu, "toString");
removeMethod(cu, "append");
removeMethod(cu, "appendFields");
removeMethod(cu, "fromValue");
optimizeImport(cu);
cleanUpInterfaces("ToString", cu.getTypes());
cleanUpAnnotationForEnum(cu);
// prints the resulting compilation unit to default system output
System.out.println(cu.toString());
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
finally
{
in.close();
}
FileOutputStream fileOutputStream = new FileOutputStream(codeFile, false);
fileOutputStream.write(cu.toString().getBytes());
fileOutputStream.flush();
javaFiles.add(codeFile.toString());
}
try
{
Config config = new Config();
Main main = new Main(config, javaFiles);
main.execute();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void cleanUpAnnotationForEnum(CompilationUnit cu)
{
for (TypeDeclaration type : cu.getTypes())
{
if (type instanceof EnumDeclaration)
{
EnumDeclaration enumDeclaration = (EnumDeclaration) type;
if (enumDeclaration.getAnnotations() != null)
{
enumDeclaration.getAnnotations().clear();
}
for (BodyDeclaration member : enumDeclaration.getMembers())
{
List<AnnotationExpr> annotations = member.getAnnotations();
if (annotations != null)
{
annotations.clear();
}
}
for (EnumConstantDeclaration member : enumDeclaration.getEntries())
{
List<AnnotationExpr> annotations = member.getAnnotations();
if (annotations != null)
{
annotations.clear();
}
}
}
}
}
private static void cleanUpInterfaces(String interfaceName, List<? extends BodyDeclaration> types)
{
for (BodyDeclaration type : types)
{
cleanUpInterface(type, interfaceName);
if (type instanceof TypeDeclaration)
{
List<BodyDeclaration> members = ((TypeDeclaration) type).getMembers();
if (members == null)
{
continue;
}
for (BodyDeclaration body : members)
{
if (body instanceof ClassOrInterfaceDeclaration)
{
cleanUpInterface(body, interfaceName);
cleanUpInterfaces(interfaceName, ((ClassOrInterfaceDeclaration) body).getMembers());
}
}
}
}
}
private static void cleanUpInterface(BodyDeclaration typeDeclaration, String interfaceName)
{
if (typeDeclaration instanceof ClassOrInterfaceDeclaration)
{
List<ClassOrInterfaceType> interfaceTypes = ((ClassOrInterfaceDeclaration) typeDeclaration).getImplements();
if (interfaceTypes == null)
{
return;
}
List<ClassOrInterfaceType> toBeRemove = new ArrayList<ClassOrInterfaceType>();
for (ClassOrInterfaceType interfaceType : interfaceTypes)
{
if (interfaceType.toString().equals(interfaceName))
{
toBeRemove.add(interfaceType);
}
}
interfaceTypes.removeAll(toBeRemove);
}
}
private static void optimizeImport(CompilationUnit cu)
{
List<ImportDeclaration> toBeRemove = new ArrayList<ImportDeclaration>();
if (cu.getImports() == null)
{
return;
}
for (ImportDeclaration importDeclaration : cu.getImports())
{
String importPackageName = importDeclaration.getName().toString();
if (importPackageName.startsWith("java.io")
|| importPackageName.startsWith("javax.xml.datatype")
|| importPackageName.startsWith("java.util")
|| importPackageName.startsWith("java.math")
|| importPackageName.startsWith("java.text"))
{
continue;
}
toBeRemove.add(importDeclaration);
}
cu.getImports().removeAll(toBeRemove);
}
public static List<File> listFilesForFolder(final File folder, List<File> result)
{
for (final File fileEntry : folder.listFiles())
{
if (fileEntry.isDirectory())
{
listFilesForFolder(fileEntry, result);
}
else
{
if (result == null)
{
result = new ArrayList<File>();
}
result.add(fileEntry);
}
}
return result;
}
private static void removeMethod(CompilationUnit cu, String methodName)
{
List<TypeDeclaration> types = cu.getTypes();
for (TypeDeclaration type : types)
{
List<BodyDeclaration> members = type.getMembers();
cleanUp(methodName, type, members);
if (type.getAnnotations() != null)
{
type.getAnnotations().clear();
}
type.setJavaDoc(null);
type.setComment(null);
}
}
private static void cleanUp(String methodName, BodyDeclaration type, List<BodyDeclaration> members)
{
List<BodyDeclaration> membersToRemove = new ArrayList<BodyDeclaration>();
for (BodyDeclaration member : members)
{
try
{
member.setJavaDoc(null);
member.setComment(null);
if (member.getAnnotations() != null)
{
member.getAnnotations().clear();
}
if (member instanceof MethodDeclaration && methodName.equals(((MethodDeclaration) member).getName()))
{
membersToRemove.add(member);
}
if (member instanceof ClassOrInterfaceDeclaration)
{
cleanUp(methodName, member, ((ClassOrInterfaceDeclaration) member).getMembers());
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
if (type instanceof TypeDeclaration)
{
((TypeDeclaration) type).getMembers().removeAll(membersToRemove);
}
else if (type instanceof ClassOrInterfaceDeclaration)
{
((ClassOrInterfaceDeclaration) type).getMembers().removeAll(membersToRemove);
}
else if (type instanceof EnumDeclaration)
{
((EnumDeclaration) type).getMembers().removeAll(membersToRemove);
}
}
private static void changeMethods(CompilationUnit cu)
{
List<TypeDeclaration> types = cu.getTypes();
for (TypeDeclaration type : types)
{
List<BodyDeclaration> members = type.getMembers();
for (BodyDeclaration member : members)
{
if (member instanceof MethodDeclaration)
{
MethodDeclaration method = (MethodDeclaration) member;
changeMethod(method);
}
}
}
}
private static void changeMethod(MethodDeclaration n)
{
// change the name of the method to upper case
n.setName(n.getName().toUpperCase());
// create the new parameter
Parameter newArg = ASTHelper.createParameter(ASTHelper.INT_TYPE, "value");
// add the parameter to the method
ASTHelper.addParameter(n, newArg);
}
}

If you erase the body of doOldThing():
doOldThing() {
}
And then inline the method, it should disappear wherever it is used. If instead you wanted to replace it with a call to doNewThing():
doOldThing() {
doNewThing();
}
and then inline.

Related

Find methods with modified code between two versions of a Java class

I'd like to find the methods which changed between two arbitrary Java files.
What I've Tried
I've tried using diff (GNU diffutils 3.3) to find changes to lines in the file and diff --show-c-function connect those lines to the changed method. Unfortunately, in Java this lists the class, not the function.
I also tried git diff which seems to properly be able to find the changed function (at least as displayed on GitHub), but it doesn't always list the full signature and my files are not in the same Git repository (https://github.com/apache/commons-math/commit/34adc606601cb578486d4a019b4655c5aff607b5).
Desired Results
Input:
~/repos/d4jBugs/Math_54_buggy/src/main/java/org/apache/commons/math/dfp/Dfp.java
~/repos/d4jBugs/Math_54_fixed/src/main/java/org/apache/commons/math/dfp/Dfp.java
State of Files:
The changed methods between those two files are public double toDouble() and protected Dfp(final DfpField field, double x)
Output: (fully qualified names)
org.apache.commons.math.dfp.Dfp.toDouble()
org.apache.commons.math.dfp.Dfp(final DfpField field, double x)
Summary
Can I find the modified methods with the GNU diffutils tool or git diff and if yes, how would I do that? (Note: I'm not bound to those tools and am happy to install something else if needed.)
I used JavaParser 3.4.4, but it probably works but has not been tested with other versions.
It can be imported in Gradle with:
compile group: 'com.github.javaparser', name: 'javaparser-core', version: '3.4.4'
You can use my class like:
HashSet<String> changedMethods = MethodDiff.methodDiffInClass(
oldFileNameWithPath,
newFileNameWithPath
);
MethodDiff Source:
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.CallableDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.printer.PrettyPrinterConfiguration;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
* Created by Loren Klingman on 10/19/17.
* Finds Changes Between Methods of Two Java Source Files
*/
public class MethodDiff {
private static PrettyPrinterConfiguration ppc = null;
class ClassPair {
final ClassOrInterfaceDeclaration clazz;
final String name;
ClassPair(ClassOrInterfaceDeclaration c, String n) {
clazz = c;
name = n;
}
}
public static PrettyPrinterConfiguration getPPC() {
if (ppc != null) {
return ppc;
}
PrettyPrinterConfiguration localPpc = new PrettyPrinterConfiguration();
localPpc.setColumnAlignFirstMethodChain(false);
localPpc.setColumnAlignParameters(false);
localPpc.setEndOfLineCharacter("");
localPpc.setIndent("");
localPpc.setPrintComments(false);
localPpc.setPrintJavadoc(false);
ppc = localPpc;
return ppc;
}
public static <N extends Node> List<N> getChildNodesNotInClass(Node n, Class<N> clazz) {
List<N> nodes = new ArrayList<>();
for (Node child : n.getChildNodes()) {
if (child instanceof ClassOrInterfaceDeclaration) {
// Don't go into a nested class
continue;
}
if (clazz.isInstance(child)) {
nodes.add(clazz.cast(child));
}
nodes.addAll(getChildNodesNotInClass(child, clazz));
}
return nodes;
}
private List<ClassPair> getClasses(Node n, String parents, boolean inMethod) {
List<ClassPair> pairList = new ArrayList<>();
for (Node child : n.getChildNodes()) {
if (child instanceof ClassOrInterfaceDeclaration) {
ClassOrInterfaceDeclaration c = (ClassOrInterfaceDeclaration)child;
String cName = parents+c.getNameAsString();
if (inMethod) {
System.out.println(
"WARNING: Class "+cName+" is located inside a method. We cannot predict its name at"
+ " compile time so it will not be diffed."
);
} else {
pairList.add(new ClassPair(c, cName));
pairList.addAll(getClasses(c, cName + "$", inMethod));
}
} else if (child instanceof MethodDeclaration || child instanceof ConstructorDeclaration) {
pairList.addAll(getClasses(child, parents, true));
} else {
pairList.addAll(getClasses(child, parents, inMethod));
}
}
return pairList;
}
private List<ClassPair> getClasses(String file) {
try {
CompilationUnit cu = JavaParser.parse(new File(file));
return getClasses(cu, "", false);
} catch (FileNotFoundException f) {
throw new RuntimeException("EXCEPTION: Could not find file: "+file);
}
}
public static String getSignature(String className, CallableDeclaration m) {
return className+"."+m.getSignature().asString();
}
public static HashSet<String> methodDiffInClass(String file1, String file2) {
HashSet<String> changedMethods = new HashSet<>();
HashMap<String, String> methods = new HashMap<>();
MethodDiff md = new MethodDiff();
// Load all the method and constructor values into a Hashmap from File1
List<ClassPair> cList = md.getClasses(file1);
for (ClassPair c : cList) {
List<ConstructorDeclaration> conList = getChildNodesNotInClass(c.clazz, ConstructorDeclaration.class);
List<MethodDeclaration> mList = getChildNodesNotInClass(c.clazz, MethodDeclaration.class);
for (MethodDeclaration m : mList) {
String methodSignature = getSignature(c.name, m);
if (m.getBody().isPresent()) {
methods.put(methodSignature, m.getBody().get().toString(getPPC()));
} else {
System.out.println("Warning: No Body for "+file1+" "+methodSignature);
}
}
for (ConstructorDeclaration con : conList) {
String methodSignature = getSignature(c.name, con);
methods.put(methodSignature, con.getBody().toString(getPPC()));
}
}
// Compare everything in file2 to what is in file1 and log any differences
cList = md.getClasses(file2);
for (ClassPair c : cList) {
List<ConstructorDeclaration> conList = getChildNodesNotInClass(c.clazz, ConstructorDeclaration.class);
List<MethodDeclaration> mList = getChildNodesNotInClass(c.clazz, MethodDeclaration.class);
for (MethodDeclaration m : mList) {
String methodSignature = getSignature(c.name, m);
if (m.getBody().isPresent()) {
String body1 = methods.remove(methodSignature);
String body2 = m.getBody().get().toString(getPPC());
if (body1 == null || !body1.equals(body2)) {
// Javassist doesn't add spaces for methods with 2+ parameters...
changedMethods.add(methodSignature.replace(" ", ""));
}
} else {
System.out.println("Warning: No Body for "+file2+" "+methodSignature);
}
}
for (ConstructorDeclaration con : conList) {
String methodSignature = getSignature(c.name, con);
String body1 = methods.remove(methodSignature);
String body2 = con.getBody().toString(getPPC());
if (body1 == null || !body1.equals(body2)) {
// Javassist doesn't add spaces for methods with 2+ parameters...
changedMethods.add(methodSignature.replace(" ", ""));
}
}
// Anything left in methods was only in the first set and so is "changed"
for (String method : methods.keySet()) {
// Javassist doesn't add spaces for methods with 2+ parameters...
changedMethods.add(method.replace(" ", ""));
}
}
return changedMethods;
}
private static void removeComments(Node node) {
for (Comment child : node.getAllContainedComments()) {
child.remove();
}
}
}

Refactoring business logic validation

I'm trying to refactoring this code
private void validate(Customer customer) {
List<String> errors = new ArrayList<>();
if (customer == null) {
errors.add("Customer must not be null");
}
if (customer != null && customer.getName() == null) {
errors.add("Name must not be null");
}
if (customer != null && customer.getName().isEmpty()) {
errors.add("Name must not be empty");
}
if (customer != null) {
Customer customerFromDb = customerRepository.findByName(customer.getName());
if (customerFromDb != null) {
errors.add("Customer already present on db");
}
}
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
}
I read this post Business logic validation patterns & advices
I'd like to build a generic validator for my entities and fields of the entity, I wrote this
private void validate(Customer customer) {
List<ValidationRule> validationRules = new ArrayList<>();
validationRules.add(new NotNullValidationRule(customer));
validationRules.add(new NotNullValidationRule(customer, Customer::getName));
validationRules.add(new NotEmptyValidationRule(customer, Customer::getName));
validationRules.add(new NotExistValidationRule(customer -> customerRepository.findByName(customer.getName())));
Validator.validate(validationRules);
}
and the Validator class
public class Validator {
public static void validate(List<ValidationRule> validationRules) {
final List<String> errors = new ArrayList<>();
for (final ValidationRule rule : validationRules) {
final Optional<String> error = rule.validate();
if (error.isPresent()) {
errors.add(error.get());
}
}
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
}
}
but I don't know how to implement the interface ValidationRule and other classes (NotNullValidationRule, NotEmptyValidationRule, NotExistValidationRule)
I would write something like :
CommonValidations.notNull(errors, customer);
if (customer != null) {
CommonValidations.notEmpty(errors, customer.getName());
}
customerCustomeBeanValidations.validName(errors, customer.getName());
customerCustomeBeanValidations.notExist(errors, customer.getName());
In the link you reference, the accepted answer suggested using the Strategy design pattern, and then gave an example of both an interface and implementation. In your case, you would create a new interface ValidationRule, with at least one method validate(), and then you would create concrete classes that each implementat that interface (NotNullValidationRule, NotEmptyValidationRule, AlreadyExistValidationRule).
I found this solution:
I create an interface ValidationRule
import java.util.Optional;
public interface ValidationRule {
Optional<ValidationError> validate();
}
And some classes that implement the behaviours
public class NotNullValidationRule implements ValidationRule {
private Object object;
private String field;
public NotNullValidationRule(Object object, String field) {
this.object = object;
if (field == null || field.isEmpty()) {
throw new IllegalArgumentException("field must not be null or emtpy");
}
this.field = field;
}
#Override public Optional<ValidationError> validate() {
if (object == null) {
return Optional.empty();
}
try {
Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
if (value == null) {
ValidationError validationError = new ValidationError();
validationError.setName(object.getClass().getSimpleName() + "." + field);
validationError.setError("Field " + field + " is null");
return Optional.of(validationError);
}
}
catch (Exception e) {
throw new IllegalStateException("error during retrieve of field value");
}
return Optional.empty();
}
}
Another where I pass a method to call:
package it.winetsolutions.winactitime.core.service.validation;
import java.beans.PropertyDescriptor;
import java.util.Optional;
import java.util.function.Function;
public class NotExistValidationRule implements ValidationRule {
Object object;
String field;
Function<? super String, ? super Object> function;
public NotExistValidationRule(Object object, String field, Function<? super String, ? super Object> function) {
this.object = object;
if (field == null || field.isEmpty() || function == null) {
throw new IllegalArgumentException("field and function must not be null or emtpy");
}
this.field = field;
this.function = function;
}
#Override public Optional<ValidationError> validate() {
if (object == null) {
return Optional.empty();
}
try {
Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
Long id = (Long) new PropertyDescriptor("id", object.getClass()).getReadMethod().invoke(object);
Object result = function.apply(value == null ? (String) value : ((String) value).trim());
if (result != null &&
!id.equals((Long) new PropertyDescriptor("id", result.getClass()).getReadMethod().invoke(result))) {
ValidationError validationError = new ValidationError();
validationError.setName(object.getClass().getSimpleName() + "." + field);
validationError.setError("Element with " + field +": " + value + " already exists");
return Optional.of(validationError);
}
}
catch (Exception e) {
throw new IllegalStateException("error during retrieve of field value");
}
return Optional.empty();
}
}

Could not find java.beans.propertydescriptor on android

my app uses another projects which contains references to classes as java.beans.propertydescriptor which is not contained by android libraries.
The situation is the next: my project contains the .jar files with this another projects as libraries. I read that the solution is use an opensource class. I found it, but i dont know how can i add this class to the android .jar file. So, how can i add this class to the android java.beans library?
This is the class i have found:
package java.beans;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Vector;
import org.apache.harmony.beans.internal.nls.Messages;
public class PropertyDescriptor extends FeatureDescriptor {
private Method getter;
private Method setter;
private Class<?> propertyEditorClass;
private boolean constrained;
private boolean bound;
public PropertyDescriptor(String propertyName, Class<?> beanClass,
String getterName, String setterName) throws IntrospectionException {
super();
if (beanClass == null) {
throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
}
if (propertyName == null || propertyName.length() == 0) {
throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
}
this.setName(propertyName);
this.setDisplayName(propertyName);
if (setterName != null) {
if (hasMethod(beanClass, setterName)) {
setWriteMethod(beanClass, setterName);
} else {
throw new IntrospectionException(Messages.getString("beans.20")); //$NON-NLS-1$
}
}
if (getterName != null) {
if (hasMethod(beanClass, getterName)) {
setReadMethod(beanClass, getterName);
} else {
throw new IntrospectionException(Messages.getString("beans.1F")); //$NON-NLS-1$
}
}
}
public PropertyDescriptor(String propertyName, Method getter, Method setter)
throws IntrospectionException {
super();
if (propertyName == null || propertyName.length() == 0) {
throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
}
this.setName(propertyName);
this.setDisplayName(propertyName);
setWriteMethod(setter);
setReadMethod(getter);
}
public PropertyDescriptor(String propertyName, Class<?> beanClass)
throws IntrospectionException {
String getterName;
String setterName;
if (beanClass == null) {
throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
}
if (propertyName == null || propertyName.length() == 0) {
throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
}
this.setName(propertyName);
this.setDisplayName(propertyName);
getterName = createDefaultMethodName(propertyName, "is"); //$NON-NLS-1$
if (hasMethod(beanClass, getterName)) {
setReadMethod(beanClass, getterName);
} else {
getterName = createDefaultMethodName(propertyName, "get"); //$NON-NLS-1$
if (hasMethod(beanClass, getterName)) {
setReadMethod(beanClass, getterName);
}
}
setterName = createDefaultMethodName(propertyName, "set"); //$NON-NLS-1$
if (hasMethod(beanClass, setterName)) {
setWriteMethod(beanClass, setterName);
}
if (getter == null && setter == null) {
throw new IntrospectionException(Messages.getString(
"beans.01", propertyName)); //$NON-NLS-1$
}
}
public void setWriteMethod(Method setter) throws IntrospectionException {
if (setter != null) {
int modifiers = setter.getModifiers();
if (!Modifier.isPublic(modifiers)) {
throw new IntrospectionException(Messages.getString("beans.05")); //$NON-NLS-1$
}
Class<?>[] parameterTypes = setter.getParameterTypes();
if (parameterTypes.length != 1) {
throw new IntrospectionException(Messages.getString("beans.06")); //$NON-NLS-1$
}
Class<?> parameterType = parameterTypes[0];
Class<?> propertyType = getPropertyType();
if (propertyType != null && !propertyType.equals(parameterType)) {
throw new IntrospectionException(Messages.getString("beans.07")); //$NON-NLS-1$
}
}
this.setter = setter;
}
public void setReadMethod(Method getter) throws IntrospectionException {
if (getter != null) {
int modifiers = getter.getModifiers();
if (!Modifier.isPublic(modifiers)) {
throw new IntrospectionException(Messages.getString("beans.0A")); //$NON-NLS-1$
}
Class<?>[] parameterTypes = getter.getParameterTypes();
if (parameterTypes.length != 0) {
throw new IntrospectionException(Messages.getString("beans.08")); //$NON-NLS-1$
}
Class<?> returnType = getter.getReturnType();
if (returnType.equals(Void.TYPE)) {
throw new IntrospectionException(Messages.getString("beans.33")); //$NON-NLS-1$
}
Class<?> propertyType = getPropertyType();
if ((propertyType != null) && !returnType.equals(propertyType)) {
throw new IntrospectionException(Messages.getString("beans.09")); //$NON-NLS-1$
}
}
this.getter = getter;
}
public Method getWriteMethod() {
return setter;
}
public Method getReadMethod() {
return getter;
}
#Override
public boolean equals(Object object) {
boolean result = (object != null && object instanceof PropertyDescriptor);
if (result) {
PropertyDescriptor pd = (PropertyDescriptor) object;
boolean gettersAreEqual = (this.getter == null)
&& (pd.getReadMethod() == null) || (this.getter != null)
&& (this.getter.equals(pd.getReadMethod()));
boolean settersAreEqual = (this.setter == null)
&& (pd.getWriteMethod() == null) || (this.setter != null)
&& (this.setter.equals(pd.getWriteMethod()));
boolean propertyTypesAreEqual = this.getPropertyType() == pd
.getPropertyType();
boolean propertyEditorClassesAreEqual = this
.getPropertyEditorClass() == pd.getPropertyEditorClass();
boolean boundPropertyAreEqual = this.isBound() == pd.isBound();
boolean constrainedPropertyAreEqual = this.isConstrained() == pd
.isConstrained();
result = gettersAreEqual && settersAreEqual
&& propertyTypesAreEqual && propertyEditorClassesAreEqual
&& boundPropertyAreEqual && constrainedPropertyAreEqual;
}
return result;
}
public void setPropertyEditorClass(Class<?> propertyEditorClass) {
this.propertyEditorClass = propertyEditorClass;
}
public Class<?> getPropertyType() {
Class<?> result = null;
if (getter != null) {
result = getter.getReturnType();
} else if (setter != null) {
Class<?>[] parameterTypes = setter.getParameterTypes();
result = parameterTypes[0];
}
return result;
}
public Class<?> getPropertyEditorClass() {
return propertyEditorClass;
}
public void setConstrained(boolean constrained) {
this.constrained = constrained;
}
public void setBound(boolean bound) {
this.bound = bound;
}
public boolean isConstrained() {
return constrained;
}
public boolean isBound() {
return bound;
}
boolean hasMethod(Class<?> beanClass, String methodName) {
Method[] methods = findMethods(beanClass, methodName);
return (methods.length > 0);
}
String createDefaultMethodName(String propertyName, String prefix) {
String result = null;
if (propertyName != null) {
String bos = propertyName.substring(0, 1).toUpperCase();
String eos = propertyName.substring(1, propertyName.length());
result = prefix + bos + eos;
}
return result;
}
Method[] findMethods(Class<?> aClass, String methodName) {
Method[] allMethods = aClass.getMethods();
Vector<Method> matchedMethods = new Vector<Method>();
Method[] result;
for (Method method : allMethods) {
if (method.getName().equals(methodName)) {
matchedMethods.add(method);
}
}
result = new Method[matchedMethods.size()];
for (int j = 0; j < matchedMethods.size(); ++j) {
result[j] = matchedMethods.elementAt(j);
}
return result;
}
void setReadMethod(Class<?> beanClass, String getterName) {
boolean result = false;
Method[] getters = findMethods(beanClass, getterName);
for (Method element : getters) {
try {
setReadMethod(element);
result = true;
} catch (IntrospectionException ie) {
}
if (result) {
break;
}
}
}
void setWriteMethod(Class<?> beanClass, String setterName)
throws IntrospectionException {
boolean result = false;
Method[] setters = findMethods(beanClass, setterName);
for (Method element : setters) {
try {
setWriteMethod(element);
result = true;
} catch (IntrospectionException ie) {
}
if (result) {
break;
}
}
}
public PropertyEditor createPropertyEditor(Object bean) {
PropertyEditor editor;
if (propertyEditorClass == null) {
return null;
}
if (!PropertyEditor.class.isAssignableFrom(propertyEditorClass)) {
// beans.48=Property editor is not assignable from the
// PropertyEditor interface
throw new ClassCastException(Messages.getString("beans.48")); //$NON-NLS-1$
}
try {
Constructor<?> constr;
try {
// try to look for the constructor with single Object argument
constr = propertyEditorClass.getConstructor(Object.class);
editor = (PropertyEditor) constr.newInstance(bean);
} catch (NoSuchMethodException e) {
// try no-argument constructor
constr = propertyEditorClass.getConstructor();
editor = (PropertyEditor) constr.newInstance();
}
} catch (Exception e) {
// beans.47=Unable to instantiate property editor
RuntimeException re = new RuntimeException(
Messages.getString("beans.47"), e); //$NON-NLS-1$
throw re;
}
return editor;
}
}
Thanks.
I downloaded from this page https://code.google.com/p/openbeans/downloads/detail?name=openbeans-1.0.jar the openbean.jar. Then, i imported this jar to the project and changed the references at imported library.
Then export again the project as .jar library and import in the android project.

Java Reflection to set Value for the java pojo

Goal :
set value for the given java bean at run time and generate JSON Object or JSON array.
the above is my goal and i have tried some thing like the below :
package com.hexgen.tools;
import java.lang.reflect.Method;
import com.google.gson.Gson;
public class ConvertPOJOToJSON {
public Object creatJSONObject(String className) throws IllegalArgumentException, IllegalAccessException, InstantiationException, Exception {
Class<?> objectClass = null;
Object clsObject =null;
try {
objectClass = Class.forName(className);
clsObject = objectClass.newInstance();
for(Method m : objectClass.getMethods())
if (m.getName().startsWith("set") && m.getParameterTypes().length == 1 && m.getModifiers()==23)
m.invoke(clsObject, "myValue");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return clsObject;
}
public static void main(String[] args) {
Gson gson = new Gson();
ConvertPOJOToJSON pojoToJSON = new ConvertPOJOToJSON();
try {
System.out.println("JSON OBJECT : "+gson.toJson(pojoToJSON.creatJSONObject("com.hexgen.ro.request.CreateRequisitionRO")));
} catch (Exception e) {
e.printStackTrace();
}
}
}
The Output of the above class :
JSON OBJECT : {"isAllocable":false}
there are many fields in the class i gave com.hexgen.ro.request.CreateRequisitionRO but only one boolean value is set to false and returns the value.
i have some constant value to set for the fields say if the field type is Integer than set some default integer value like so
EDIT :
I have created a enum like the following :
package com.hexgen.tools;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.joda.time.LocalDate;
public enum DefaultParamValues {
STRING("HEXGEN"),
INTEGER(123),
DATE(new LocalDate()),
BOOLEAN(true),
LONGVALUE(123123),
BIGDECIMAL(new BigDecimal("100000"));
private String defaultString;
private int defaultInteger;
private LocalDate defaultDate;
private boolean defaultBoolean;
private long defaultLong;
private BigDecimal defaultBigDecimal;
private DefaultParamValues(String strDefaultValue) {
defaultString = strDefaultValue;
}
private DefaultParamValues(int intDefaultValue) {
defaultInteger = intDefaultValue;
}
private DefaultParamValues(LocalDate dateDefaultValue) {
defaultDate = dateDefaultValue;
}
private DefaultParamValues(boolean booleanDefaultValue) {
defaultBoolean = booleanDefaultValue;
}
private DefaultParamValues(long longDefaultValue) {
defaultLong = longDefaultValue;
}
private DefaultParamValues(BigDecimal bigIntegerDefaultValue) {
defaultBigDecimal = bigIntegerDefaultValue;
}
public String getDefaultString() {
return defaultString;
}
public int getDefaultInt() {
return defaultInteger;
}
public LocalDate getDefaultDate() {
return defaultDate;
}
public boolean getDefaultBoolean() {
return defaultBoolean;
}
public long getDefaultLong() {
return defaultLong;
}
public BigDecimal getDdefaultBigDecimal() {
return defaultBigDecimal;
}
}
created one more method like the following :
public Object creatObjectWithDefaultValue(String className) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
DefaultParamValues defaultParamValues = null;
Class<?> objectClass = null;
Object clsObject =null;
try {
objectClass = Class.forName(className);
clsObject = objectClass.newInstance();
Field[] fields = objectClass.getDeclaredFields();
for(Field f:fields){
if(!f.isAccessible()){
f.setAccessible(true);
Class<?> type = f.getType();
if(! Modifier.isFinal(f.getModifiers()) && type.equals(Integer.class)){
f.set(clsObject, defaultParamValues.INTEGER);
} else if( !Modifier.isFinal(f.getModifiers()) && type.equals(java.math.BigDecimal.class)){
f.set(clsObject, defaultParamValues.BIGDECIMAL);
} else if(! Modifier.isFinal(f.getModifiers()) && type.equals(org.joda.time.LocalDate.class)){
f.set(clsObject,defaultParamValues.DATE);
} else if(! Modifier.isFinal(f.getModifiers()) && type.equals(boolean.class)){
f.set(clsObject, defaultParamValues.BOOLEAN);
} else if(! Modifier.isFinal(f.getModifiers()) && type.equals(java.lang.String.class)){
f.set(clsObject, defaultParamValues.STRING);
}
else if(! Modifier.isFinal(f.getModifiers()) && type.equals(long.class)){
f.set(clsObject, defaultParamValues.LONGVALUE);
}
//f.setAccessible(false);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return clsObject;
}
to set the default values but i get the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.math.BigDecimal field com.hexgen.ro.request.CreateRequisitionRO.transSrlNo to com.hexgen.tools.DefaultParamValues
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at com.hexgen.tools.JsonConverter.creatObjectWithDefaultValue(JsonConverter.java:93)
at com.hexgen.tools.JsonConverter.main(JsonConverter.java:201)
Please help me to find the solution.
Best Regards
If your looking for a lightweight library which can do this and more including allowing you to do your own filtering to find Methods/Fields. I wrote an open source library which has no 3rd party dependencies and is available on Maven Central.
Checkout https://github.com/gondor/reflect
As for your issue it appears your setting the "Enum" constant and not the inner value of the enum. Wouldn't it DefaultParamValues.BIGDECIMAL.getDdefaultBigDecimal()

How to programmatically read a Java interface?

I'd like to implement a method that returns the field(s) from an interface that define a specified (int) value. I don't have source to the interface.
So, the signature could be something like this:
public ArrayList<String> getFieldnames(Object src, int targetValue);
And I'm assuming internally it could find the declared fields and test each against the value, returning the list.
ArrayList<String> s = new ArrayList<String>();
if( src!= null )
{
Field[] flist = src.getClass().getDeclaredFields();
for (Field f : flist )
if( f.getType() == int.class )
try {
if( f.getInt(null) == targetValue) {
s.add(f.getName());
break;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
return s;
Unfortunately, this implementation is incorrect - it's as if there are no fields at all when called with the interface itself. If I pass an object that implements the interface, the list of possible fields will be too wide to be of use.
Thanks for any help!
public ArrayList<String> getFieldnames(Object src, int targetValue) {
final Class<?> myInterfaceClass = MyInterface.class;
ArrayList<String> fieldNames = new ArrayList<>();
if (src != null) {
for (Class<?> currentClass = src.getClass(); currentClass != null; currentClass = currentClass.getSuperclass()) {
Class<?> [] interfaces = currentClass.getInterfaces();
if (Arrays.asList(interfaces).contains(myInterfaceClass)) {
for (Field field : currentClass.getDeclaredFields()) {
if (field.getType().equals(int.class)) {
try {
int value = field.getInt(null);
if (value == targetValue) {
fieldNames.add(field.getName());
}
} catch (IllegalAccessException ex) {
// Do nothing. Always comment empty blocks.
}
}
}
}
}
}
return fieldNames;
}
This
src.getClass()
returns src class not interface. Consider this
interface I {
}
class A implements I {
}
new A().getClass() -- returns A.class
Although I would rather have passed in an object, I suppose changing the signature to a string value and passing in the FQIN gets the job done just as well.
Thanks to <this question> for the idea (and Google for directing me there).
Solution:
public ArrayList<String> getFieldnamesByValue(Class<?>x, int targetValue)
{
ArrayList<String> s = new ArrayList<String>();
if( x != null )
{
Field[] flist = x.getDeclaredFields();
for (Field f : flist )
if( f.getType() == int.class )
try {
if( f.getInt(null) == targetValue) {
s.add(f.getName());
break;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
return s;
}

Categories