private void addToString(JDefinedClass jclass) {
    Map<String, JFieldVar> fields = jclass.fields();
    JMethod toString = jclass.method(JMod.PUBLIC, String.class, "toString");
    //noinspection SSBasedInspection
    Set<String> excludes = new HashSet<>(Arrays.asList(ruleFactory.getGenerationConfig().getToStringExcludes()));

    JBlock body = toString.body();

    // The following toString implementation roughly matches the commons ToStringBuilder for
    // backward compatibility
    JClass stringBuilderClass = jclass.owner().ref(StringBuilder.class);
    JVar sb = body.decl(stringBuilderClass, "sb", JExpr._new(stringBuilderClass));

    // Write the header, e.g.: example.domain.MyClass@85e382a7[
    body.add(sb
               .invoke("append").arg(jclass.dotclass().invoke("getName"))
               .invoke("append").arg(JExpr.lit('@'))
               .invoke("append").arg(
        jclass.owner().ref(Integer.class).staticInvoke("toHexString").arg(
          jclass.owner().ref(System.class).staticInvoke("identityHashCode").arg(JExpr._this())))
               .invoke("append").arg(JExpr.lit('[')));

    // If this has a parent class, include its toString()
    if (!jclass._extends().fullName().equals(Object.class.getName())) {
      JVar baseLength = body.decl(jclass.owner().INT, "baseLength", sb.invoke("length"));
      JVar superString = body.decl(jclass.owner().ref(String.class), "superString", JExpr._super().invoke("toString"));

      JBlock superToStringBlock = body._if(superString.ne(JExpr._null()))._then();

      // If super.toString() is in the Clazz@2ee6529d[field=10] format, extract the fields
      // from the wrapper
      JVar contentStart = superToStringBlock.decl(jclass.owner().INT, "contentStart",
                                                  superString.invoke("indexOf").arg(JExpr.lit('[')));
      JVar contentEnd = superToStringBlock.decl(jclass.owner().INT, "contentEnd",
                                                superString.invoke("lastIndexOf").arg(JExpr.lit(']')));

      JConditional superToStringInnerConditional = superToStringBlock._if(
        contentStart.gte(JExpr.lit(0)).cand(contentEnd.gt(contentStart)));

      superToStringInnerConditional._then().add(
        sb.invoke("append")
          .arg(superString)
          .arg(contentStart.plus(JExpr.lit(1)))
          .arg(contentEnd));

      // Otherwise, just append super.toString()
      superToStringInnerConditional._else().add(sb.invoke("append").arg(superString));

      // Append a comma if needed
      body._if(sb.invoke("length").gt(baseLength))
        ._then().add(sb.invoke("append").arg(JExpr.lit(',')));
    }

    // For each included instance field, add to the StringBuilder in the field=value format
    for (JFieldVar fieldVar : fields.values()) {
      if (excludes.contains(fieldVar.name()) || (fieldVar.mods().getValue() & JMod.STATIC) == JMod.STATIC) {
        continue;
      }

      body.add(sb.invoke("append").arg(fieldVar.name()));
      body.add(sb.invoke("append").arg(JExpr.lit('=')));

      if (fieldVar.type().isPrimitive()) {
        body.add(sb.invoke("append").arg(JExpr.refthis(fieldVar.name())));
      }
      else if (fieldVar.type().isArray()) {
        // Only primitive arrays are supported
        if (!fieldVar.type().elementType().isPrimitive()) {
          throw new UnsupportedOperationException("Only primitive arrays are supported");
        }

        // Leverage Arrays.toString()
        body.add(sb.invoke("append")
                   .arg(JOp.cond(
                     JExpr.refthis(fieldVar.name()).eq(JExpr._null()),
                     JExpr.lit("<null>"),
                     jclass.owner().ref(Arrays.class).staticInvoke("toString")
                       .arg(JExpr.refthis(fieldVar.name()))
                       .invoke("replace").arg(JExpr.lit('[')).arg(JExpr.lit('{'))
                       .invoke("replace").arg(JExpr.lit(']')).arg(JExpr.lit('}'))
                       .invoke("replace").arg(JExpr.lit(", ")).arg(JExpr.lit(",")))));
      }
      else {
        body.add(sb.invoke("append")
                   .arg(JOp.cond(
                     JExpr.refthis(fieldVar.name()).eq(JExpr._null()),
                     JExpr.lit("<null>"),
                     JExpr.refthis(fieldVar.name()))));
      }

      body.add(sb.invoke("append").arg(JExpr.lit(',')));
    }

    // Add the trailer
    JConditional trailerConditional = body._if(
      sb.invoke("charAt").arg(sb.invoke("length").minus(JExpr.lit(1)))
        .eq(JExpr.lit(',')));

    trailerConditional._then().add(
      sb.invoke("setCharAt")
        .arg(sb.invoke("length").minus(JExpr.lit(1)))
        .arg(JExpr.lit(']')));

    trailerConditional._else().add(
      sb.invoke("append").arg(JExpr.lit(']')));


    body._return(sb.invoke("toString"));

    toString.annotate(Override.class);
  }
private void addToString(JDefinedClass jclass)