private JClass mapType(Filter filter) throws JClassAlreadyExistsException {
   if (!(filter.getOption() == null || filter.getOption().isEmpty())) {
     return getParamTypeEnum(filter);
   }
   String type = filter.getType();
   Class<?> typeCls = typeMap.get(type);
   checkState(typeCls != null, "Unexpected type: %s", type);
   return model.ref(typeCls);
 }
 private void addVarArgsWither(
     Filter filter, JMethod wither, JDefinedClass bldrCls, JClass paramType)
     throws JClassAlreadyExistsException {
   JMethod method = bldrCls.method(wither.mods().getValue(), wither.type(), wither.name());
   if (filter.getTitle() != null) {
     method.javadoc().add(String.format("<p>%s</p>", filter.getTitle()));
   }
   JVar param = method.varParam(paramType, wither.listParams()[0].name());
   method
       .body()
       ._return(JExpr.invoke(wither).arg(immutableList.staticInvoke("copyOf").arg(param)));
 }
 private JMethod addIterableWither(
     Filter filter, JDefinedClass bldrCls, JVar paramBuilder, JFieldVar field, JClass paramType)
     throws JClassAlreadyExistsException {
   JMethod method = createWitherMethod(filter, bldrCls);
   if (filter.getTitle() != null) {
     method.javadoc().add(String.format("<p>%s</p>", filter.getTitle()));
   }
   JVar param = addParam(filter, method, iterable(paramType));
   JBlock mthdBody = method.body();
   mthdBody.add(
       paramBuilder.invoke("put").arg(field).arg(immutableList.staticInvoke("copyOf").arg(param)));
   mthdBody._return(JExpr._this());
   return method;
 }
  private void addWithersFor(Filter filter, JDefinedClass bldrCls, JVar paramBuilder)
      throws ClassNotFoundException, JClassAlreadyExistsException {
    JDefinedClass cls = (JDefinedClass) bldrCls.parentContainer();

    JFieldVar field =
        cls.field(privateStaticFinal, String.class, sanitize(filter.getName().toUpperCase()));
    field.init(JExpr.lit(filter.getName()));

    JClass paramType = mapType(filter);
    if (Boolean.TRUE.equals(filter.isMultipleValues())) {
      JMethod iterableWither = addIterableWither(filter, bldrCls, paramBuilder, field, paramType);
      addVarArgsWither(filter, iterableWither, bldrCls, paramType);
    } else {
      addWither(filter, bldrCls, paramBuilder, field, paramType);
    }
  }
  private JDefinedClass addBuilderCls(Feed feed, JDefinedClass cls)
      throws JClassAlreadyExistsException, ClassNotFoundException {
    JDefinedClass bldrCls = cls._class(JMod.PUBLIC | JMod.STATIC | JMod.FINAL, "Builder");
    JVar paramBuilder =
        bldrCls
            .field(JMod.PRIVATE | JMod.FINAL, immutableMapBldr, "params")
            .init(immutableMap.staticInvoke("builder"));

    for (Filter filter : feed.getFilters().getFilter()) {
      if (!Boolean.TRUE.equals(filter.isDeprecated())) {
        addWithersFor(filter, bldrCls, paramBuilder);
      }
    }

    if (feed.getMixins() != null && feed.getMixins().getMixin() != null) {
      JDefinedClass mixinEnum = getMixinEnum(feed);
      for (Mixin mixin : feed.getMixins().getMixin()) {
        String mixinName = mixin.getName().toUpperCase().replace(' ', '_');
        JEnumConstant mixinCnst = mixinEnum.enumConstant(mixinName);
        mixinCnst.arg(JExpr.lit(mixin.getName().replace(' ', '+')));
      }
      JFieldVar field = cls.field(privateStaticFinal, String.class, "MIXIN");
      field.init(JExpr.lit("mixin"));
      JMethod iterWither = bldrCls.method(JMod.PUBLIC, bldrCls, "withMixins");
      JVar param = iterWither.param(iterable(mixinEnum), "mixins");
      JBlock mthdBody = iterWither.body();
      mthdBody.add(
          paramBuilder
              .invoke("put")
              .arg(field)
              .arg(immutableList.staticInvoke("copyOf").arg(param)));
      mthdBody._return(JExpr._this());
      JMethod varArgWither = bldrCls.method(JMod.PUBLIC, bldrCls, "withMixins");
      param = varArgWither.varParam(mixinEnum, "mixins");
      varArgWither
          .body()
          ._return(JExpr.invoke(iterWither).arg(immutableList.staticInvoke("copyOf").arg(param)));
    }

    JMethod bldMthd = bldrCls.method(JMod.PUBLIC, cls, "build");
    bldMthd.body()._return(JExpr._new(cls).arg(paramBuilder.invoke("build")));

    // TODO: add sorts
    return bldrCls;
  }
  private JClass getParamTypeEnum(Filter filter) throws JClassAlreadyExistsException {
    String enumName = camel(filter.getName(), true) + "Option";
    if (pkg.isDefined(enumName)) {
      return pkg._getClass(enumName);
    }
    List<Option> options = filter.getOption();
    if (options.size() == 1) {
      /*turn into '*Only' method?*/
    }
    if (options.size() == 2) {
      if (ImmutableSet.of("true", "false")
          .equals(
              ImmutableSet.of(
                  options.get(0).getValue().toLowerCase(),
                  options.get(1).getValue().toLowerCase()))) {
        return model.ref(Boolean.class);
      }
    }

    JDefinedClass valueEnum = pkg._enum(enumName);

    JFieldVar valField = valueEnum.field(JMod.PRIVATE | JMod.FINAL, String.class, "value");
    JMethod ctor = valueEnum.constructor(JMod.PRIVATE);
    JVar param = ctor.param(String.class, "val");
    ctor.body().assign(valField, param);

    JMethod toString = valueEnum.method(JMod.PUBLIC, String.class, "toString");
    toString.annotate(Override.class);
    toString.body()._return(valField);

    for (Option option : options) {
      String optionName = option.getValue().toUpperCase().replace(' ', '_');
      JEnumConstant optionCst = valueEnum.enumConstant(optionName);
      optionCst.arg(JExpr.lit(option.getValue().replace(' ', '+')));
    }
    return valueEnum;
  }
 private void addWither(
     Filter filter, JDefinedClass bldrCls, JVar paramBuilder, JFieldVar field, JClass paramType)
     throws JClassAlreadyExistsException {
   JMethod method = createWitherMethod(filter, bldrCls);
   if (filter.getTitle() != null) {
     method.javadoc().add(String.format("<p>%s</p>", filter.getTitle()));
   }
   JVar param = addParam(filter, method, paramType);
   JBlock mthdBody = method.body();
   boolean needsNullCheck = true;
   if (filter.getMinValue() != null) {
     mthdBody.add(precs.staticInvoke("checkNotNull").arg(param));
     needsNullCheck = false;
     int min = filter.getMinValue().intValue();
     mthdBody.add(
         precs
             .staticInvoke("checkArgument")
             .arg(JExpr.lit(min).lte(param))
             .arg(JExpr.lit(param.name() + ": %s < " + min))
             .arg(param));
   }
   if (filter.getMaxValue() != null) {
     if (needsNullCheck) {
       mthdBody.add(precs.staticInvoke("checkNotNull").arg(param));
       needsNullCheck = false;
     }
     int max = filter.getMaxValue().intValue();
     mthdBody.add(
         precs
             .staticInvoke("checkArgument")
             .arg(JExpr.lit(max).gte(param))
             .arg(JExpr.lit(param.name() + ": %s > " + max))
             .arg(param));
   }
   JInvocation putIntoMap = paramBuilder.invoke("put").arg(field);
   if (needsNullCheck) {
     putIntoMap.arg(precs.staticInvoke("checkNotNull").arg(param));
   } else {
     putIntoMap.arg(param);
   }
   mthdBody.add(putIntoMap);
   mthdBody._return(JExpr._this());
 }
 private JMethod createWitherMethod(Filter filter, JDefinedClass bldrCls) {
   String filterMethodName = "with" + camel(sanitize(filter.getName()), true);
   return bldrCls.method(JMod.PUBLIC, bldrCls, filterMethodName);
 }
 private JVar addParam(Filter filter, JMethod method, JType paramType) {
   return method.param(paramType, camel(sanitize(filter.getName()), false));
 }