protected int generateToString(Writer writer, int shift, AnnotationMirror annotation, ClassDefinition definition, String className, boolean isHavinsSuperClass, TypeElement targetInterface) throws IOException {
        boolean threadSafe = isThreadSafe(annotation);
        Types typeUtils = processingEnv.getTypeUtils();
        
        writer.append(indent(shift)).append("@Override\n")
              .append(indent(shift++)).append("public String toString() {\n");

        if(threadSafe) {
            writer.append(indent(shift)).append(INSTANCE_LOCK).append(".readLock().lock();\n")
                  .append(indent(shift++)).append("try {\n");
        }

        writer.append(indent(shift)).append("return getClass().getSimpleName()").append(" + \"{\"\n");

        shift++;
        boolean isFirst = true;
        
        for (Field field : definition.getInnerFields(typeUtils)) {
            //We must generate toString() for all inner fields including 'ignore=true' fields.
            shift = generateToStringForOneAttribute(isFirst, field, writer, shift);
            if(isFirst) isFirst = false;
        }
        
        for (Property property : definition.getProperties()) {
            if(!property.isIgnored()) {
                shift = generateToStringForOneAttribute(isFirst, property, writer, shift);
                if(isFirst) isFirst = false;
            }
        }
        if(isHavinsSuperClass) {
            writer.append(indent(shift)).append(" + \"");
            if(!isFirst) writer.append(", ");
            writer.append("superClass=\" + ").append("super.toString()\n");

        }
        writer.append(indent(shift)).append(" + '}';\n");
        shift--;

        if(threadSafe) {
            writer.append(indent(--shift)).append("} finally {\n")
                  .append(indent(++shift)).append(INSTANCE_LOCK).append(".readLock().unlock();\n")
                  .append(indent(--shift)).append("}\n");
        }

        writer.append(indent(--shift)).append("}\n\n");

        return shift;
    }