private JDefinedClass createProxyClass(Serialization serialization) throws JClassAlreadyExistsException {
JDefinedClass proxyClass = valueClass._class(JMod.PRIVATE | JMod.STATIC, "Proxy" + acceptingInterface.name(), EClassType.CLASS);
for (JTypeVar visitorTypeParameter: acceptingInterface.typeParams()) {
Types.generifyWithBoundsFrom(proxyClass, visitorTypeParameter.name(), visitorTypeParameter);
}
AbstractJClass usedAcceptingInterfaceType = acceptingInterface.narrow(proxyClass.typeParams());
proxyClass._implements(usedAcceptingInterfaceType);
if (serialization.isSerializable()) {
proxyClass._implements(types._Serializable);
proxyClass.field(JMod.PRIVATE | JMod.FINAL | JMod.STATIC, types._long, "serialVersionUID", JExpr.lit(serialization.serialVersionUID()));
}
JMethod constructor = proxyClass.constructor(JMod.NONE);
AbstractJClass usedValueClassType = valueClass.narrow(proxyClass.typeParams());
proxyClass.field(JMod.PRIVATE | JMod.FINAL, usedValueClassType, "implementation");
constructor.param(usedValueClassType, "implementation");
constructor.body().assign(JExpr._this().ref("implementation"), JExpr.ref("implementation"));
JMethod acceptMethod = proxyClass.method(JMod.PUBLIC, types._void, "accept");
acceptMethod.annotate(Override.class);
JTypeVar visitorResultType = visitorInterface.getResultTypeParameter();
JTypeVar resultType = Types.generifyWithBoundsFrom(acceptMethod, visitorResultType.name(), visitorResultType);
acceptMethod.type(resultType);
JTypeVar visitorExceptionType = visitorInterface.getExceptionTypeParameter();
JTypeVar exceptionType = null;
if (visitorExceptionType != null) {
exceptionType = Types.generifyWithBoundsFrom(acceptMethod, visitorExceptionType.name(), visitorExceptionType);
acceptMethod._throws(exceptionType);
}
AbstractJClass usedVisitorType = visitorInterface.narrowed(usedValueClassType, resultType, exceptionType);
acceptMethod.param(usedVisitorType, "visitor");
JInvocation invocation = JExpr.ref("implementation").invoke("accept");
invocation.arg(JExpr.ref("visitor"));
acceptMethod.body()._return(invocation);
return proxyClass;