/** * Tries to find a reference for an injected {@link AutoBound} data binder. * * @return the data binder reference or null if not found. */ private static DataBinderRef lookupAutoBoundBinder(final InjectableInstance<?> inst) { Statement dataBinderRef = null; MetaClass dataModelType = null; InjectUtil.BeanMetric beanMetric = InjectUtil.getFilteredBeanMetric( inst.getInjectionContext(), inst.getInjector().getInjectedType(), AutoBound.class); final Collection<Object> allInjectors = beanMetric.getAllInjectors(); if (allInjectors.size() > 1) { throw new GenerationException( "Multiple @AutoBound data binders injected in " + inst.getEnclosingType()); } else if (allInjectors.size() == 1) { final Object injectorElement = allInjectors.iterator().next(); if (injectorElement instanceof MetaConstructor || injectorElement instanceof MetaMethod) { final MetaParameter mp = beanMetric.getConsolidatedMetaParameters().iterator().next(); assertTypeIsDataBinder(mp.getType()); dataModelType = (MetaClass) mp.getType().getParameterizedType().getTypeParameters()[0]; dataBinderRef = inst.getInjectionContext().getInlineBeanReference(mp); inst.ensureMemberExposed(); } else { final MetaField field = (MetaField) allInjectors.iterator().next(); assertTypeIsDataBinder(field.getType()); dataModelType = (MetaClass) field.getType().getParameterizedType().getTypeParameters()[0]; dataBinderRef = Stmt.invokeStatic( inst.getInjectionContext().getProcessingContext().getBootstrapClass(), PrivateAccessUtil.getPrivateFieldInjectorName(field), Variable.get(inst.getInjector().getInstanceVarName())); inst.getInjectionContext().addExposedField(field, PrivateAccessType.Both); } } else { final MetaClass declaringClass = inst.getInjector().getInjectedType(); for (final MetaField field : declaringClass.getFields()) { if (field.isAnnotationPresent(AutoBound.class)) { assertTypeIsDataBinder(field.getType()); dataModelType = (MetaClass) field.getType().getParameterizedType().getTypeParameters()[0]; dataBinderRef = Stmt.invokeStatic( inst.getInjectionContext().getProcessingContext().getBootstrapClass(), PrivateAccessUtil.getPrivateFieldInjectorName(field), Variable.get(inst.getInjector().getInstanceVarName())); inst.getInjectionContext().addExposedField(field, PrivateAccessType.Both); break; } } } return (dataBinderRef != null) ? new DataBinderRef(dataModelType, dataBinderRef) : null; }
private static Statement paramFromStringStatement(MetaClass toType, Statement stringValue) { // make sure it's really a string stringValue = Stmt.castTo(String.class, stringValue); if (toType.isAssignableTo(String.class)) { return stringValue; } else if (toType.asBoxed().isAssignableTo(Number.class)) { return Stmt.invokeStatic(toType.asBoxed(), "valueOf", stringValue); } else if (toType.asBoxed().isAssignableTo(Boolean.class)) { return Stmt.invokeStatic(Boolean.class, "valueOf", stringValue); } else { throw new UnsupportedOperationException( "@PageState fields of type " + toType.getFullyQualifiedName() + " are not supported"); } }
private void appendPageShowMethod( AnonymousClassStructureBuilder pageImplBuilder, MetaClass pageClass, Class<? extends Annotation> annotation, boolean addPrivateAccessors) { BlockBuilder<?> method = pageImplBuilder .publicMethod( void.class, createMethodNameFromAnnotation(annotation), Parameter.of(pageClass, "widget"), Parameter.of(HistoryToken.class, "state")) .body(); int idx = 0; method.append(Stmt.declareFinalVariable("pageState", Map.class, new HashMap<String, Object>())); for (MetaField field : pageClass.getFieldsAnnotatedWith(PageState.class)) { PageState psAnno = field.getAnnotation(PageState.class); String fieldName = field.getName(); String queryParamName = psAnno.value(); if (queryParamName == null || queryParamName.trim().isEmpty()) { queryParamName = fieldName; } if (addPrivateAccessors) { PrivateAccessUtil.addPrivateAccessStubs( PrivateAccessType.Write, "jsni", pageImplBuilder, field, new Modifier[] {}); } String injectorName = PrivateAccessUtil.getPrivateFieldInjectorName(field); MetaClass erasedFieldType = field.getType().getErased(); if (erasedFieldType.isAssignableTo(Collection.class)) { MetaClass elementType = MarshallingGenUtil.getConcreteCollectionElementType(field.getType()); if (elementType == null) { throw new UnsupportedOperationException( "Found a @PageState field with a Collection type but without a concrete type parameter. " + "Collection-typed @PageState fields must specify a concrete type parameter."); } if (erasedFieldType.equals(MetaClassFactory.get(Set.class))) { method.append(Stmt.declareVariable(fieldName, Stmt.newObject(HashSet.class))); } else if (erasedFieldType.equals(MetaClassFactory.get(List.class)) || erasedFieldType.equals(MetaClassFactory.get(Collection.class))) { method.append(Stmt.declareVariable(fieldName, Stmt.newObject(ArrayList.class))); } else { throw new UnsupportedOperationException( "Found a @PageState field which is a collection of type " + erasedFieldType.getFullyQualifiedName() + ". For collection-valued fields, only the exact types java.util.Collection, java.util.Set, and " + "java.util.List are supported at this time."); } // for (String fv{idx} : state.get({fieldName})) method.append( Stmt.loadVariable("state") .invoke("getState") .invoke("get", queryParamName) .foreach("elem", Object.class) .append( Stmt.declareVariable( "fv" + idx, Stmt.castTo(String.class, Stmt.loadVariable("elem")))) .append( Stmt.loadVariable(fieldName) .invoke( "add", paramFromStringStatement(elementType, Stmt.loadVariable("fv" + idx)))) .append( Stmt.loadVariable("pageState") .invoke("put", fieldName, Stmt.loadVariable(fieldName))) .finish()); method.append( Stmt.loadVariable("this") .invoke(injectorName, Stmt.loadVariable("widget"), Stmt.loadVariable(fieldName))); } else { method.append( Stmt.declareFinalVariable( "fv" + idx, Collection.class, Stmt.loadVariable("state").invoke("getState").invoke("get", queryParamName))); method.append( If.cond( Bool.or( Bool.isNull(Stmt.loadVariable("fv" + idx)), Stmt.loadVariable("fv" + idx).invoke("isEmpty"))) .append( Stmt.loadVariable("this") .invoke( injectorName, Stmt.loadVariable("widget"), defaultValueStatement(erasedFieldType))) .finish() .else_() .append( Stmt.loadVariable("this") .invoke( injectorName, Stmt.loadVariable("widget"), paramFromStringStatement( erasedFieldType, Stmt.loadVariable("fv" + idx).invoke("iterator").invoke("next")))) .append( Stmt.loadVariable("pageState") .invoke( "put", fieldName, Stmt.loadVariable("fv" + idx).invoke("iterator").invoke("next"))) .finish()); } idx++; } if (addPrivateAccessors) { method.append( Stmt.invokeStatic( CDI.class, "fireEvent", Stmt.newObject(NavigationEvent.class) .withParameters( Stmt.newObject(PageRequest.class) .withParameters( getPageName(pageClass), Stmt.loadVariable("pageState"))))); } checkMethodAndAddPrivateAccessors( pageImplBuilder, method, pageClass, annotation, HistoryToken.class, "state"); method.finish(); }