List<PsiFieldMember> finalFields = new ArrayList<PsiFieldMember>();
List<PsiFieldMember> nonFinalFields = new ArrayList<PsiFieldMember>();
PsiElement addedField = null;
for (Iterator<PsiFieldMember> iterator = fieldMembers.iterator(); iterator.hasNext(); ) {
PsiFieldMember member = iterator.next();
PsiField field = member.getElement();
addedField = addField(builderClass, addedField, field.getName(), field.getType());
if (field.hasModifierProperty(PsiModifier.FINAL) && !finalSetters) {
if (!finalFields.isEmpty()) {
typedFinalFields.append(", ");
untypedFinalFields.append(", ");
untypedFinalFieldsCopy.append(", ");
}
finalFields.add(member);
((PsiField) addedField).getModifierList().setModifierProperty(PsiModifier.FINAL, true);
typedFinalFields.append(member.getElement().getType().getCanonicalText()).append(" ").append(member.getElement().getName());
untypedFinalFields.append(member.getElement().getName());
untypedFinalFieldsCopy.append("copy.").append(member.getElement().getName());
} else {
nonFinalFields.add(member);
}
}
// builder constructor, accepting the final fields
StringBuilder builderConstructorText = new StringBuilder();
String builderConstructorContructorAccess = newBuilderMethod ? "private" : "public";
builderConstructorText.append(builderConstructorContructorAccess + " " + builderClass.getName() + "(").append(typedFinalFields).append(") {");
for (PsiFieldMember field : finalFields) {
builderConstructorText.append("this.").append(field.getElement().getName()).append("=").append(field.getElement().getName()).append(";");
}
builderConstructorText.append("}");
addMethod(builderClass, null, builderConstructorText.toString());
if (newBuilderMethod) {
StringBuilder newBuilderText = new StringBuilder();
newBuilderText.append("public static " + builderClass.getName() + " newBuilder(").append(typedFinalFields).append(") {");
newBuilderText.append("return new ").append(builderClass.getName()).append("(").append(untypedFinalFields).append(");");
newBuilderText.append("}");
addMethod(clazz, null, newBuilderText.toString());
}
// COPY CONSTRUCTOR
if (copyConstructor) {
StringBuilder copyConstructorText = new StringBuilder();
if (newBuilderMethod) {
copyConstructorText.append("public static ").append(builderClass.getName()).append(" newBuilder(");
copyConstructorText.append(clazz.getQualifiedName()).append(" copy) { ").append(builderClass.getName()).append(" builder = new ")
.append(builderClass.getName()).append("(").append(untypedFinalFieldsCopy).append(");");
} else {
copyConstructorText.append("public ").append(builderClass.getName()).append("(");
copyConstructorText.append(clazz.getQualifiedName()).append(" copy) {");
}
for (PsiFieldMember member : fieldMembers) {
if (member.getElement().getModifierList().hasModifierProperty(PsiModifier.FINAL) && !finalSetters) continue;
if (newBuilderMethod) copyConstructorText.append("builder.");
copyConstructorText.append(member.getElement().getName()).append("= copy.").append(member.getElement().getName()).append(";");
}
if (newBuilderMethod) copyConstructorText.append("return builder;");
copyConstructorText.append("}");
addMethod(newBuilderMethod ? clazz : builderClass, null, copyConstructorText.toString(), true);
}
PsiElement added = null;
// builder methods
for (PsiFieldMember member : nonFinalFields) {
PsiField field = member.getElement();
String methodName = withNotation ? "with" + capitalize(field.getName()) : field.getName();
String builderMethod = new StringBuilder("public Builder ")
.append(methodName).append("(").append(field.getType().getCanonicalText()).append(" ")
.append(field.getName()).append("){").append("this.").append(field.getName()).append("=")