I'm writing a custom rule that will check whether the class under analysis is extending a type.
For example:
class Bus {
}
class Transport {
}
class PublicTransport extends Transport {
}
class Bus should extend class Transport or a sub class of Transport.
public class EnsureSuperClassRule extends IssuableSubscriptionVisitor {
final String SUPER_CLASS = "common.service.SuperService";
#Override
public List<Tree.Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.CLASS);
}
#Override
public void visitNode(Tree tree) {
ClassTree classTree = (ClassTree) tree;
String className = classTree.simpleName().name();
if (className.endsWith("Service")) {
if(classTree.superClass() == null) {
return false;
}
if (!SUPER_CLASS.equals(localClassTree.superClass().symbolType().fullyQualifiedName())) {
reportIssue(tree, String.format("The class should extend SuperService or a class of type SuperService"));
}
}
}
}
}
How can I get the information related to superclass of the superclass?
You can simply call
Class superClassOfSuperClass = this.class().getSuperClass();
superClassOfSuperClass.method().invoke(this);
I'm not sure with your above example as there is a few typo's or misunderstanding with inheritance
You can collect all super classes until java.lang.Object was reached like so:
#Override
public void visitNode(Tree pTree) {
final ClassTree classTree = (ClassTree) pTree;
final Set<String> superclasses = new HashSet<>();
Type currentSuperclass = classTree.symbol().superClass();
while (currentSuperclass != null) {
superclasses.add(currentSuperclass.fullyQualifiedName());
currentSuperclass = currentSuperclass.symbol().superClass();
}
// ... do something with superClasses
super.visitNode(pTree);
}
#Override
public List<Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.CLASS);
}
(Tested with sonar-java-plugin 6.3.0 and sonar-plugin-api 8.2.0)
Here I go:
abstract class IdentifiedEntity<E extends IdentifiedEntity> implements Cloneable {
...
public void updateWith(E that) {
if (this != that) {
if (that.isNew()) {
throw new IllegalArgumentException("Cannot update with a new entity");
}
if (this.isNew()) {
throw new IllegalStateException("Cannot update a new entity");
}
if (this.getId() != that.getId()) {
throw new IllegalArgumentException("IDs do not match");
}
doUpdateWith(that);
}
}
abstract void doUpdateWith(E that);
...
}
public final class User extends IdentifiedEntity<User> {
...
#Override
void doUpdateWith(User that) {
assert that != null;
this.name = that.name;
this.email = that.email;
System.arraycopy(that.password, 0, password, 0, password.length);
this.enabled = that.enabled;
this.caloriesPerDayLimit = that.caloriesPerDayLimit;
}
...
}
The question is how can I unit test the updateWith(...) to ensure that it definely invokes the abstract doUpdateWith(...) implmented in the descendant (yes, for sure,if i tpasse sall the checks)?
That you guys!
Create a dummy sub class
class ConcreteEntity extends IdentifiedEntity<ConcreteEntity> {
#Override
void doUpdateWith(ConcreteEntity that) {
}
}
then test like this:
#Test
public void test() throws Exception {
ConcreteEntity e = Mockito.spy(new ConcreteEntity());
e.updateWith(e);
Mockito.verify(e).doUpdateWith(e);
}
However such a test is very special. It does not allow you to change implementation of your method.
With the help of #CoronA, I found the answer. Here it is:
#Test
public void updateWith() {
User user = this.user.clone().setId(100);
User mock = Mockito.spy(user);
mock.updateWith(user);
Mockito.verify(mock).doUpdateWith(user);
}
Thank you guys a lot!!!
I have a iterative code like below with is used in different place of my project:
List<NewsItem> thisitem = Select.from(NewsItem.class).where(Condition.prop("_id").eq(item.get_id())).list();
if (thisitem.size() > 0) {
thisitem.get(0).delete();
image_bookmark.setImageResource(R.drawable.ic_bookmark_normal);
} else {
item.save();
image_bookmark.setImageResource(R.drawable.ic_bookmarkfill);
}
I want to write a method witch contain above code ,but worked for every object of class witch extend SugarOrmItem class . i write the below but apparently it's not true:
public static void insert_bookmark(String prop,SugarOrmItem record ,ImageView imageView)
{
List<SugarOrmItem> thisitem = Select.from(SugarOrmItem.class).where(Condition.prop(prop).eq(record.get_id())).list();
if (thisitem.size() > 0) {
thisitem.get(0).delete();
imageView.setImageResource(R.drawable.ic_bookmark_normal);
} else {
imageView.setImageResource(R.drawable.ic_bookmarkfill);
}
}
what should i do?
Edit:
this is my SugarItem class:
import com.orm.SugarRecord;
public abstract class SugarOrmItem extends SugarRecord {
public abstract int get_id();
}
I think it needs to be this:
public static <T extends SugarOrmItem> void insert_bookmark(
String prop, T record, ImageView imageView, Class<T> clazz)
{
List<T> thisitem = Select.from(clazz).
where(Condition.prop(prop).eq(record.get_id())).list();
if (thisitem.size() > 0) {
thisitem.get(0).delete();
imageView.setImageResource(R.drawable.ic_bookmark_normal);
} else {
imageView.setImageResource(R.drawable.ic_bookmarkfill);
}
}
I have the following class structure:
MyClass
FirstClass
FirstClassVersion1
FirstClassVersion2
SecondClass
SecondClassVersion1
SecondClassVersion2
At a certain point i need a reference of MyClass according with class number and class version, so i created a simple factory. But my factory is a little complex as follow:
public class MyClassFactory {
public static MyClass createMyClass(int classNumber, int classVersion) throws Exception {
if (classNumber == 1) {
if (classVersion == 1) {
return new FirstClassVersion1();
} else if (classVersion == 2) {
return new FirstClassVersion2();
}
} else if (classNumber == 2) {
if (classVersion == 1) {
return new SecondClassVersion1();
} else if (classVersion == 2) {
return new SecondClassVersion2();
}
}
throw new Exception("...");
}
}
Is there a better way to do this?
Here's another idea:
public class MyClassFactory {
private MyClassFactory instance = new MyClassFactory();
private MyClassFactory() {}
public MyClassFactory getInstance() { return instance; }
public MyClass create(Class clazz) throws Exception {
return clazz.newInstance();
}
}
Embellish this as needed (e.g. stronger type checks using generics).
Your way requires that you modify the factory every time you extend the class. That can't scale.
I have to handle two classes with identical methods but they don't implement the same interface, nor do they extend the same superclass. I'm not able / not allowed to change this classes and I don't construct instances of this classes I only get objects of this.
What is the best way to avoid lots of code duplication?
One of the class:
package faa;
public class SomethingA {
private String valueOne = null;
private String valueTwo = null;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
And the other...
package foo;
public class SomethingB {
private String valueOne;
private String valueTwo;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
(In reality these classes are larger)
My only idea is now to create a wrapper class in this was:
public class SomethingWrapper {
private SomethingA someA;
private SomethingB someB;
public SomethingWrapper(SomethingA someA) {
//null check..
this.someA = someA;
}
public SomethingWrapper(SomethingB someB) {
//null check..
this.someB = someB;
}
public String getValueOne() {
if (this.someA != null) {
return this.someA.getValueOne();
} else {
return this.someB.getValueOne();
}
}
public void setValueOne(String valueOne) {
if (this.someA != null) {
this.someA.setValueOne(valueOne);
} else {
this.someB.setValueOne(valueOne);
}
}
public String getValueTwo() {
if (this.someA != null) {
return this.someA.getValueTwo();
} else {
return this.someB.getValueTwo();
}
}
public void setValueTwo(String valueTwo) {
if (this.someA != null) {
this.someA.setValueTwo(valueTwo);
} else {
this.someB.setValueTwo(valueTwo);
}
}
}
But I'm not realy satisfied with this solution. Is there any better / more elegant way to solve this problem?
A better solution would be to create an interface to represent the unified interface to both classes, then to write two classes implementing the interface, one that wraps an A, and another that wraps a B:
public interface SomethingWrapper {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
};
public class SomethingAWrapper implements SomethingWrapper {
private SomethingA someA;
public SomethingWrapper(SomethingA someA) {
this.someA = someA;
}
public String getValueOne() {
return this.someA.getValueOne();
}
public void setValueOne(String valueOne) {
this.someA.setValueOne(valueOne);
}
public String getValueTwo() {
return this.someA.getValueTwo();
}
public void setValueTwo(String valueTwo) {
this.someA.setValueTwo(valueTwo);
}
};
and then another class just like it for SomethingBWrapper.
There, a duck-typed solution. This will accept any object with valueOne, valueTwo properties and is trivially extensible to further props.
public class Wrapper
{
private final Object wrapped;
private final Map<String, Method> methods = new HashMap<String, Method>();
public Wrapper(Object w) {
wrapped = w;
try {
final Class<?> c = w.getClass();
for (String propName : new String[] { "ValueOne", "ValueTwo" }) {
final String getter = "get" + propName, setter = "set" + propName;
methods.put(getter, c.getMethod(getter));
methods.put(setter, c.getMethod(setter, String.class));
}
} catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueOne() {
try { return (String)methods.get("getValueOne").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueOne(String v) {
try { methods.get("setValueOne").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueTwo() {
try { return (String)methods.get("getValueTwo").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueTwo(String v) {
try { methods.get("setValueTwo").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
You can use a dynamic proxy to create a "bridge" between an interface you define and the classes that conform but do not implement your interface.
It all starts with an interface:
interface Something {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
}
Now you need an InvocationHandler, that will just forward calls to the method that matches the interface method called:
class ForwardInvocationHandler implements InvocationHandler {
private final Object wrapped;
public ForwardInvocationHandler(Object wrapped) {
this.wrapped = wrapped;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method match = wrapped.getClass().getMethod(method.getName(), method.getParameterTypes());
return match.invoke(wrapped, args);
}
}
Then you can create your proxy (put it in a factory for easier usage):
SomethingA a = new SomethingA();
a.setValueOne("Um");
Something s = (Something)Proxy.newProxyInstance(
Something.class.getClassLoader(),
new Class[] { Something.class },
new ForwardInvocationHandler(a));
System.out.println(s.getValueOne()); // prints: Um
Another option is simpler but requires you to subclass each class and implement the created interface, simply like this:
class SomethingAImpl extends SomethingA implements Something {}
class SomethingBImpl extends SomethingB implements Something {}
(Note: you also need to create any non-default constructors)
Now use the subclasses instead of the superclasses, and refer to them through the interface:
Something o = new SomethingAImpl(); // o can also refer to a SomethingBImpl
o.setValueOne("Uno");
System.out.println(o.getValueOne()); // prints: Uno
i think your original wrapper class is the most viable option...however it can be done using reflection, your real problem is that the application is a mess...and reflection is might not be the method you are looking for
i've another proposal, which might be help: create a wrapper class which has specific functions for every type of classes...it mostly copypaste, but it forces you to use the typed thing as a parameter
class X{
public int asd() {return 0;}
}
class Y{
public int asd() {return 1;}
}
class H{
public int asd(X a){
return a.asd();
}
public int asd(Y a){
return a.asd();
}
}
usage:
System.out.println("asd"+h.asd(x));
System.out.println("asd"+h.asd(y));
i would like to note that an interface can be implemented by the ancestor too, if you are creating these classes - but just can't modify it's source, then you can still overload them from outside:
public interface II{
public int asd();
}
class XI extends X implements II{
}
class YI extends Y implements II{
}
usage:
II a=new XI();
System.out.println("asd"+a.asd());
You probably can exploit a facade along with the reflection - In my opinion it streamlines the way you access the legacy and is scalable too !
class facade{
public static getSomething(Object AorB){
Class c = AorB.getClass();
Method m = c.getMethod("getValueOne");
m.invoke(AorB);
}
...
}
I wrote a class to encapsulate the logging framework API's. Unfortunately, it's too long to put in this box.
The program is part of the project at http://www.github.com/bradleyross/tutorials with the documentation at http://bradleyross.github.io/tutorials. The code for the class bradleyross.library.helpers.ExceptionHelper in the module tutorials-common is at https://github.com/BradleyRoss/tutorials/blob/master/tutorials-common/src/main/java/bradleyross/library/helpers/ExceptionHelper.java.
The idea is that I can have the additional code that I want to make the exception statements more useful and I won't have to repeat them for each logging framework. The wrapper isn't where you eliminate code duplication. The elimination of code duplication is in not having to write multiple versions of the code that calls the wrapper and the underlying classes. See https://bradleyaross.wordpress.com/2016/05/05/java-logging-frameworks/
The class bradleyross.helpers.GenericPrinter is another wrapper that enables you to write code that works with both the PrintStream, PrintWriter, and StringWriter classes and interfaces.