I'm trying to code, for fun, a class that use an annotion with another annotation inside, but I don't understand how to code.
My code
First annotation
#interface FirstAnnotation {
String author();
}
Second annotation, contains the first annotation
public #interface SecondAnnotation {
FirstAnnotation inside();
int version();
}
Class with annotation
#FirstAnnotation(
author = "alessandro"
)
#SecondAnnotation(
version = 1,
inside = /*Compilation code: what code? FirstAnnotation, this??*/
)
public class GeneralClass {
/*
* a generic method
*/
public void method() {
System.out.println("method");
}
}
What I have to put in row with string Compilation code, as reference to actual value of FirstAnnotation in the class?
You class should be:
#SecondAnnotation(
version = 1,
inside = #FirstAnnotation(
author = "alessandro"
)
)
public class GeneralClass {
/*
* a generic method
*/
public void method() {
System.out.println("method");
}
}
Related
I have an object in use throughout my codebase, UnsecureObject. This object is auto-generated with no getters/setters, and all member fields are public. So editing is done by doing something like the following:
unsecureObjInstance.firstName = "Jane";
This is not desirable for numerous reasons that I probably don't have to explain here. But using this generated class is required for some other technical details with our messaging pipeline that I won't go into.
I have a desire is to leverage a mapping utility written by someone else on my team to convert this UnsecureObject to a pojo that I am writing.
An example of the mapper in action (with two normal classes w/ getters/setters) would be something like:
new MapperBuilder<>(PojoOne.class, PojoTwo.class)
.from(PojoOne::getName).to(PojoTwo::getFirstName)
.build();
This will map the PojoOne#name field to the PojoTwo#firstName field.
Is there a way to translate this to input my UnsecureObject here? I have tried something like the following:
new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
.from(u -> u.firstName).to(SecureObject::getFirstName)
.build();
But get an error here, something along the lines of 'u -> u.firstName' could not be invoked.
So the question is:
Is there a way to essentially "construct" a getter on the fly using these public members? So in the .from() method, I can construct the call to look like a standard method that will yield my u.firstName?
Thanks for the help!
EDIT:
this is approx what the MapperBuilder class looks like (attempted to edit a bit to take away project specific wrappers/simplify)
/**
* This class is used to convert between POJO getter method references to the corresponding field names.
* #param <B> type
*/
public interface PojoProxy<B> {
/**
* Invokes the given getter method and returns information about the invocation.
* #param getter the getter to invoke
* #return information about the method invoked
*/
<T> GetterInvocation<T> invokeGetter(Function<B, T> getter);
}
/**
* Stores information about a method invocation.
* #param <T> method return type
*/
public interface GetterInvocation<T> {
public Class<T> getReturnType();
public String getFieldName();
}
/**
* A builder class to create {#link Mapper} instances.
* #param <FROM> source type
* #param <TO> target type
*/
public class MapperBuilder<FROM, TO> {
private final Class<FROM> _fromClass;
private final Class<TO> _toClass;
private final PojoProxy<FROM> _fromProxy;
private final PojoProxy<TO> _toProxy;
public MapperBuilder(Class<FROM> fromClass, Class<TO> toClass) {
_fromClass = fromClass;
_toClass = toClass;
//We will pretend there is an impl that provides the proxy.
//Proxies wrap the from and to classes in order to get reflection information about their getter calls.
_fromProxy = PojoProxy.of(fromClass);
_toProxy = PojoProxy.of(toClass);
}
public <FROM_VALUE> ToFieldBuilder<FROM_VALUE> from(Function<FROM, FROM_VALUE> getter) {
GetterInvocation<FROM_VALUE> methodInvocation = _fromProxy.invokeGetter(getter);
return new ToFieldBuilder<>(methodInvocation.getFieldName(), methodInvocation.getReturnType());
}
public class ToFieldBuilder<FROM_VALUE> {
private final String _fromFieldPath;
private final Class<FROM_VALUE> _fromClass;
public ToFieldBuilder(String fromFieldPath, Class<FROM_VALUE> fromClass) {
_fromFieldPath = fromFieldPath;
_fromClass = fromClass;
}
public <TO_VALUE> FromFieldBuilder<FROM_VALUE, TO_VALUE> to(Function<TO, TO_VALUE> getter) {
//similar to above, but now using a FromFieldBuilder.
}
}
public class FromFieldBuilder<FROM_VALUE, TO_VALUE> {
//impl..
}
}
I dont see MapperBuilder.from() method details, you can try this implementation of MapperBuilder.java Function (getter) -> (BiConsumer) setter
public class MapperBuilder<S, D> {
private final S src;
private final D dest;
public MapperBuilder(S src, Class<D> dest) {
this.src = src;
try {
this.dest = dest.newInstance();
} catch (Exception e) {
throw new RuntimeException("Required default constructor for: " + dest);
}
}
//getter - function to get value from source instance
//setter - biConsumer to set value to destination instance
//example - map(SrcClass::getSrcValue, DestClass::setDestValue)
public <V> MapperBuilder<S, D> map(Function<S, V> getter, BiConsumer<D, V> setter) {
setter.accept(dest, getter.apply(src));
return this;
}
public D build() {
return dest;
}
}
SrcClass.java some source class:
public class SrcClass {
private String srcValue;
public String getSrcValue() {
return srcValue;
}
public void setSrcValue(String srcValue) {
this.srcValue = srcValue;
}
}
DestClass.java some destination class:
package com.example.demo;
public class DestClass {
private String destValue;
public String getDestValue() {
return destValue;
}
public void setDestValue(String destValue) {
this.destValue = destValue;
}
}
DemoApplication.java demo:
public class DemoApplication {
public static void main(String[] args) {
SrcClass src = new SrcClass();
src.setSrcValue("someValue");
DestClass dest = new MapperBuilder<>(src, DestClass.class)
.map(SrcClass::getSrcValue, DestClass::setDestValue)
// map another fields
.build();
// for your UnsecureObject case
UnsecureObject unsecureObject = new MapperBuilder<>(src, UnsecureObject.class)
.map(SrcClass::getSrcValue,
(unsecure, srcValue) -> unsecure.unsecureValue = srcValue)
.build();
}
}
How to choose CDI java bean base on annotation, then the annotation poses table of arguments?
The problem is easier to show using an example than to describe.
Assume that for each object of type Problem we have to choose proper solution.
public class Problem {
private Object data;
private ProblemType type;
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
public ProblemType getType() { return type; }
public void setType(ProblemType type) { this.type = type;}
}
There are few types of problems:
public enum ProblemType {
A, B, C;
}
There are few solutions:
public interface Solution {
public void resolve(Problem problem);
}
like FirstSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.A, ProblemType.C })
public class FirstSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
and SecondSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.B })
public class SecondSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
The solution should be chosen based on annotation #SolutionQualifier:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SolutionQualifier {
ProblemType[] problemTypes();
public static class SolutionQualifierLiteral extends AnnotationLiteral<SolutionQualifier> implements SolutionQualifier {
private ProblemType[] problemTypes;
public SolutionQualifierLiteral(ProblemType[] problems) {
this.problemTypes = problems;
}
#Override
public ProblemType[] problemTypes() {
return problemTypes;
}
}
}
By SolutionProvider:
#RequestScoped
public class DefaultSolutionProvider implements SolutionProvider {
#Inject
#Any
private Instance<Solution> solutions;
#Override
public Instance<Solution> getSolution(Problem problem) {
/**
* Here is the problem of choosing proper solution.
* I do not know how method {#link javax.enterprise.inject.Instance#select(Annotation...)}
* works, and how it compares annotations, so I do no know what argument I should put there
* to obtain proper solution.
*/
ProblemType[] problemTypes = { problem.getType() };
return solutions.select(new SolutionQualifier.SolutionQualifierLiteral(problemTypes));
}
}
And in the last one there is a problem:
I do not know how method javax.enterprise.inject.Instance#select(Annotation...) works internally, and how it compares annotations, so I do no know what argument I should put there to obtain proper solution. If there appear a problem of type A table ProblemType[] will consist of one argument, while FirstSolution.class is annotated with #SolutionQualifier having two arguments, so therefore I will not get the proper Instance.
I didn't find a way to resolve it using CDI API, instead:
I created another enum:
public enum SoultionType {
A(ProblemType.A, ProblemType.C),
B(ProblemType.A);
//...
SoultionType(ProblemType problems...) {
// ...
}
public static SoultionType getByProblemType(ProblemType problem) {
// ...
}
}
Changed so SolutionQualifier has only SoultionType field inside, so there is no problem with the comparison.
I want to be able to annotate a class with a list of 2 types of annotations which are related in function, but are completely different in arguments. The order of this list matters though. I have tried looking for this already, but was unable to find any references to this (I was not sure what to call this).
Edit:
What I want to be able to do in the end:
//place holder for example (Abstract)
public #interface A {
}
#Target(PARAMETER)
public #interface B extends A {
//Gets stuff
Class type();
int key();
}
#Target(PARAMETER)
public #interface FlaggedListOfA extends A {
//List of A
A[] set();
}
//Goal is to have annotation that does this
#Target(METHOD)
public #interface ImportantFunc {
A[] dataForA() default {};
String[] names();
int property() default 0;
//etc.
}
//End goal:
public class SomeImportantClass {
#ImportantFunc(dataForA = {#B(...), #B(...}, ...)
public void doStuff() {
}
//So I can have an end goal of this (Order matters, may contain repeats,
//and has unknown length!)
#ImportantFunc(dataForA = {#B(...), #FlaggedListOfA(#B(...), #B(...))}, ...)
public void doStuffB() {
}
#ImportantFunc(dataForA = {#FlaggedListOfA(#B(...)), #FlaggedListOfA(#B(...), #B(...))}, ...)
public void doStuffC() {
}
#ImportantFunc(dataForA = {#FlaggedListOfA(#B(...), #FlaggedListOfA(#B(...), #B(...))), #B(...)}, ...)
public void doStuffD() {
}
}
Reflections to get all uses of ImportantFunc (Ex: 100 uses of it) in package and uses this data to choose which function to use. The annotation is to help with the reflection since once it gets the data from #ImportantFunc, it then converts it to input for a library which does the actual choosing of which function to execute (this is internal and can not be modified). This could also be achieved with much longer and more annoying ways, but I was hoping to use annotations to simplify the process of defining all of these functions.
Edit:
Another way this could be solved is finding a way to group two annotations together.
Being able to do this would not be completely ideal, but would definitely make this much more workable:
public #interface Example {
AnyTypeOfAnnotation[] set();
}
One kludgy way to do this is to actually make A be a union of B and C. This means it has all the fields of both B and C, but you only ever use it as either a B or a C.
Here's a working example.
import java.lang.annotation.*;
enum NoType {;}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface A {
Class<?> data() default NoType.class; // field from B
int dataA() default 0; // field from C
String dataB() default ""; // field from C
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface D {
A[] value() default {};
}
class Foo {}
class Bar {}
class Example {
#D({
#A(data = Bar.class),
#A(dataA = 5, dataB = "Bla"),
#A(data = Foo.class)
})
public static void main(String[] args) throws Exception {
for (A a : Example.class.getMethod("main", String[].class)
.getAnnotation(D.class).value()) {
if (a.data() != NoType.class) {
System.out.printf("B(%s)%n", a.data());
} else {
System.out.printf("C(dataA = %d, dataB = \"%s\")%n",
a.dataA(), a.dataB());
}
}
}
}
The output of that program is:
B(class Bar)
C(dataA = 5, dataB = "Bla")
B(class Foo)
Of course, it's not a very pretty solution, but it does work.
Not sure this would be sufficient for your use case:
public #interface A {
}
public #interface B extends A {
//Gets stuff
Class data();
}
public #interface C extends A {
//Gets different stuff related to same goal
int dataA();
String dataB();
}
public #interface D {
Class<? extends A>[] order();
}
#B(Bar.class)
#C(dataA = 5, dataB = "Bla")
#D(order = {B.class, C.class})
public class SomeImportantClass {
}
This method uses D annotation as a mean to retain annotation order. The bad part is that you cannot add multiple annotations of the same type.
There is another method that makes A, B and C into normal classes.
public abstract class AnnotationAttribute {
public abstract Class<?>[] getDataTypes();
public abstract Object[] getData();
}
public class B extends AnnotationAttribute {
#Override public Class<?>[] getDataTypes() {
return new Class<?>[] {Foo.class, Bar.class};
}
#Override public Object[] getData() {
return new Object[] {new Foo(), new Bar()};
}
}
public #interface D {
Class<? extends AnnotationAttribute>[] data() default {};
}
#D(data = {B.class});
public class Test {
}
This method requires you to create one class for one concrete attribute type. This is because annotations have to be compile-time constant, and referencing via Class requires you to define the class out in code.
I am using Java7. I have a custom annotation created and annotated it on an Marker interface.
#SomeName(name="ABC")
public interface Bank{
}
Below is the class which implements the above interface.
public class BankImpl implements Bank{
//some code
}
Now i have a method in a separate class which takes above class as an input:
public void someMethod(Class class){
//Here i need to get the custom annotation value
}
Above method is called as below:
someMethod(BankImpl.class);
Now inside someMethod() how can i get the annotation value?
Thanks!
String someMethod(Class<Bank> clazz){
SomeName sn = clazz.getAnnotation(SomeName.class);
return sn.name();
}
You only need the Class of the inteface to get everything of the Annotation which is annotated on the interface.
The problem is that the class itself does not have the annotation, therefore you'll get a null value when asking for the annotation. You really need to look into all the hierarchy of the class (i.e. superclass and interfaces):
import java.util.*;
import java.lang.annotation.*;
#Retention(value=RetentionPolicy.RUNTIME)
#interface SomeName {
String name();
}
#SomeName(name = "ABC")
interface Bank {
}
class BankImpl implements Bank {
}
public class Test {
public void someMethod(Class c) {
Annotation annotation = c.getAnnotation(SomeName.class);
if (annotation == null) {
LinkedList<Class> queue = new LinkedList<Class>();
queue.addLast(c.getSuperclass());
for (Class cc : c.getInterfaces())
queue.addLast(cc);
while (!queue.isEmpty()) {
c = queue.removeFirst();
annotation = c.getAnnotation(SomeName.class);
if (annotation != null)
break;
}
}
if (annotation == null)
System.out.println("No such annotation !");
else
System.out.println("name is: " + ((SomeName)annotation).name());
}
public static void main(String... args) {
Test test = new Test();
test.someMethod(BankImpl.class);
}
}
I have the following db table:
id method_id
1 1
1 2
1 3
and 2 classes:
EmailController and Smscontroller
in my code, I need to iterate over the table and according to the method_id (1 or 2) to invoke the send method of either EmailController or Smscontroller.
What is the recommended design pattern for it?
EDITED
There could be 100 methods! I put only 3. This is why I do not prefer the if else.
As well, the object that I send to EmailController send method is different than the one that I send to SmsController send method.
In EmailController I need to send User object.
In SmsController I need to send Manager object
I can't think of a design pattern. But for ultimate flexibility you can have a design similar to this:
public interface Sendable /* or Sender, SendingManager, etc. */ {
public int getId();
public void send();
}
public class EmailController implements Sendable {
}
public class SmsController implements Sendable {
}
public class Sendables {
private Map<Integer, Sendable> sendables = new HashMap<Integer, Sendable>();
public void addSendable(Sendable s) {
this.sendables.put(s.getId(), s);
}
public void sendById(Integer id) {
this.sendables.get(id).send();
}
}
Then you can use it like this:
Sendables sendables = new Sendables();
sendables.add(new EmailController());
sendables.add(new SmsController());
sendables.add(new ChatController());
// etc.
Row row = table.getRow(...); // let's assume this gets a row from your table
sendables.send(row.getId());
Another solution could be to have an extra table like this:
TABLE: CLASS_NAMES
method_id class_name
1 "com.foo.SmsController"
2 "com.foo.EmailController"
And then pass class_name to Class.forName and let it instantiate the appropriate controller for you to use.
EDIT: A reflection-based version of the code as suggested by Luis. Note that for production use you should ensure that the passed parameters are valid (not null, etc.) and also handle exceptions with rigor.
TABLE: CLASS_NAMES
method_id class_name param_class_name
1 "com.foo.SmsController" "com.foo.Manager"
2 "com.foo.EmailController" "com.foo.User"
SendManager
public class SendManager {
private static final String SEND_METHOD_NAME = "send";
/* DAO for the CLASS_NAMES tables */
private ClassNameDAO classNameDao;
/**
* Gets the row corresponding to methodId, for example
* (1, "com.foo.SmsController", "com.foo.Manager") then using reflection
* instantiates an instance of SmsController and invokes its send method
* with <code>param</code> passed to it.
*/
public void send(int methodId, Object param) throws Exception {
ClassNameRow classNameRow = classNameDao.findByMethodId(methodId);
String senderParameterClassName = className.senderParameterClassName();
Class paramClass = Class.forName(senderParameterClassName);
if (!paramClass.isInstance(param)) {
throw new IllegalArgumentException("methodId and param are not compatible");
}
String senderClassName = classNameRow.getSenderClassName();
Class senderClass = Class.forName(senderClassName);
/* Your sender classes must be JavaBeans and have no-arg constructors */
Object sender = senderClass.newInstance();
Class paramClass = Class.forName(senderParameterClassName);
Method send = senderClass.getMethod(SEND_METHOD_NAME, paramClass);
send.invoke(sender, param);
}
}
Sample Usage
SendManager sendManager = new SendManager();
Manager m = ...;
sendManager.send(1, m);
User u = ...;
sendManager.send(2, u);
How about this:
abstract class Controller {
public static Controller getInstance(int methodId) {
switch (methodId) {
case 1:
return new EmailController();
case 2:
return new SmsController();
default:
return null;
}
}
public abstract void send();
}
class EmailController extends Controller {
#Override
public void send() {
System.out.println("sending email");
}
}
class SmsController extends Controller {
#Override
public void send() {
System.out.println("sending sms");
}
}
And use it like this:
Controller.getInstance(methodId).send();
I'm using the Strategy pattern and the Factory Method pattern in my solution.
Strategy Pattern
http://johnlindquist.com/2010/08/25/patterncraft-strategy-pattern/
http://en.wikipedia.org/wiki/Strategy_pattern