Statement dataFieldElements, Statement fieldsMap) {
/*
* In case of constructor injection, search for the data binder parameter annotated with @AutoBound
*/
Statement dataBinderRef = null;
MetaClass dataModelType = null;
BeanMetric beanMetric = InjectUtil.analyzeBean(ctx.getInjectionContext(), ctx.getEnclosingType());
MetaConstructor mc = beanMetric.getInjectorConstructor();
if (mc != null) {
for (MetaParameter mp : mc.getParameters()) {
if (mp.getType().getErased().isAssignableTo(MetaClassFactory.get(DataBinder.class))
&& mp.isAnnotationPresent(AutoBound.class)) {
dataModelType = (MetaClass) mp.getType().getParameterizedType().getTypeParameters()[0];
if (dataBinderRef != null) {
throw new GenerationException("Multiple @AutoBound data binders found in constructor of " +
mc.getDeclaringClass());
}
dataBinderRef = ctx.getInjectionContext().getInlineBeanReference(mp);
}
}
}
/*
* Search for data binder fields annotated with @AutoBound
*/
MetaField dataBinderField = null;
for (MetaField field : ctx.getInjector().getInjectedType().getFields()) {
if (field.getType().getErased().equals(MetaClassFactory.get(DataBinder.class))
&& field.isAnnotationPresent(AutoBound.class)) {
if (dataBinderField != null) {
throw new GenerationException("Multiple @AutoBound data binder fields found in class "
+ ctx.getInjector().getInjectedType());
}
if (dataBinderRef != null) {
throw new GenerationException(
"Multiple @AutoBound data binders found (check constructors and fields) in class "
+ ctx.getInjector().getInjectedType());
}
dataModelType = (MetaClass) field.getType().getParameterizedType().getTypeParameters()[0];
dataBinderField = field;
dataBinderRef = Stmt.invokeStatic(ctx.getInjectionContext().getProcessingContext().getBootstrapClass(),
PrivateAccessUtil.getPrivateFieldInjectorName(dataBinderField),
Variable.get(ctx.getInjector().getInstanceVarName()));
}
}
/*
* Create a reference to the composite's data binder
*/
if (dataBinderRef != null) {
builder.append(Stmt.declareVariable("binder", DataBinder.class, dataBinderRef));
}
/*
* Merge each field's Widget Element into the DOM in place of the
* corresponding data-field
*/
Map<String, Statement> dataFields = DecoratorDataField.aggregateDataFieldMap(ctx, ctx.getType());
for (Entry<String, Statement> field : dataFields.entrySet()) {
builder.append(Stmt.invokeStatic(TemplateUtil.class, "compositeComponentReplace", ctx.getType()
.getFullyQualifiedName(), getTemplateFileName(ctx.getType()), Cast.to(Widget.class, field.getValue()),
dataFieldElements, field.getKey()));
}
/*
* Add each field to the Collection of children of the new Composite
* Template
*/
for (Entry<String, Statement> field : dataFields.entrySet()) {
builder.append(Stmt.nestedCall(fieldsMap).invoke("put", field.getKey(), field.getValue()));
}
/*
* Bind each bound data field if data binder is found and has been initialized.
*/
Map<String, BoundDataField> boundDataFields = DecoratorDataField.aggregateDataFieldBoundMap(ctx, ctx.getType());
BlockBuilder<ElseBlockBuilder> binderBlock = If.isNotNull(Variable.get("binder"));
for (Entry<String, BoundDataField> boundDataField : boundDataFields.entrySet()) {
Bound bound = boundDataField.getValue().getBound();
if (dataBinderRef != null) {
String property = bound.property().equals("") ? boundDataField.getKey() : bound.property();
// Check if bound property exists in data model type
if (!DataBindingValidator.isValidPropertyChain(dataModelType, property)) {
throw new GenerationException("Invalid binding of DataField " + boundDataField.getValue().getName()
+ " in class " + ctx.getInjector().getInjectedType() + "! Property " + property
+ " not resolvable from class " + dataModelType +
". Hint: All types in a property chain must be @Bindable!");
}
Statement converter =
bound.converter().equals(Bound.NO_CONVERTER.class) ? null : Stmt.newObject(bound.converter());
binderBlock.append(Stmt.loadVariable("binder")
.invoke("bind", boundDataField.getValue().getWidgetStatement(), property, converter));
}
else {