private Statement defaultValueStatement(MetaClass type) {
   if (type.isPrimitive()) {
     if (type.asBoxed().isAssignableTo(Number.class)) {
       return Stmt.castTo(type, Stmt.load(0));
     } else if (type.isAssignableTo(boolean.class)) {
       return Stmt.load(false);
     } else {
       throw new UnsupportedOperationException(
           "Don't know how to make a default value for @PageState field of type "
               + type.getFullyQualifiedName());
     }
   } else {
     return Stmt.load(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();
  }