/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.spine3.validate;

import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Utility class for working with {@link ConstraintViolation}s.
 *
 * @author Alexander Yevsyukov
 */
public class ConstraintViolations {

    private ConstraintViolations() {
    }

    /**
     * Returns a formatted string using the format string and parameters from the violation.
     *
     * @param violation violation which contains the format string and
     *                  arguments referenced by the format specifiers in it
     * @return a formatted string
     * @see String#format(String, Object...)
     */
    public static String toText(ConstraintViolation violation) {
        checkNotNull(violation);

        final String format = violation.getMsgFormat();
        final List<String> params = violation.getParamList();
        final String parentViolationFormatted = String.format(format, params.toArray());

        final StringBuilder resultBuilder = new StringBuilder(parentViolationFormatted);
        if (violation.getViolationCount() > 0) {
            resultBuilder.append(toText(violation.getViolationList()));
        }
        return resultBuilder.toString();
    }

    /**
     * Returns a formatted string using the format string and parameters from each of
     * the violations passed.
     *
     * @param violations violations which contain the format string and
     *                   arguments referenced by the format specifiers in each of them
     * @return a formatted string
     * @see #toText(ConstraintViolation)
     */
    @SuppressWarnings("HardcodedLineSeparator")     // required for better formatting.
    public static String toText(Iterable<ConstraintViolation> violations) {
        checkNotNull(violations);

        final StringBuilder resultBuilder = new StringBuilder("Violation list:");

        for (ConstraintViolation childViolation : violations) {
            final String childViolationFormatted = toText(childViolation);
            resultBuilder.append("\n  ")
                         .append(childViolationFormatted);
        }
        return resultBuilder.toString();
    }

    /**
     * Returns a formatted string using the specified format string and parameters
     * from the violation.
     *
     * @param format    a format string
     * @param violation violation which contains arguments referenced by the format
     *                  specifiers in the format string
     * @return a formatted string
     * @see String#format(String, Object...)
     */
    @SuppressWarnings("HardcodedLineSeparator")     // required for better formatting.
    public static String toText(String format, ConstraintViolation violation) {
        checkNotNull(format);
        checkNotNull(violation);

        final List<String> params = violation.getParamList();
        final String parentViolationFormatted = String.format(format, params.toArray());

        final StringBuilder resultBuilder = new StringBuilder(parentViolationFormatted);
        if (violation.getViolationCount() > 0) {
            resultBuilder.append(toText(format, violation.getViolationList()));
        }

        return resultBuilder.toString();
    }

    /**
     * Returns a formatted string using the specified format string and parameters from
     * each of the violations passed.
     *
     * @param format     a format string
     * @param violations violations which contain the arguments referenced by the format
     *                   specifiers in the format string
     * @return a formatted string
     * @see String#format(String, Object...)
     */
    @SuppressWarnings("HardcodedLineSeparator")     // required for better formatting.
    public static String toText(String format, Iterable<ConstraintViolation> violations) {
        checkNotNull(format);
        checkNotNull(violations);

        final StringBuilder resultBuilder = new StringBuilder("Violations:");

        for (ConstraintViolation childViolation : violations) {
            final String childViolationFormatted = toText(format, childViolation);
            resultBuilder.append("\n  ")
                         .append(childViolationFormatted);
        }
        return resultBuilder.toString();
    }
}

@@ -1273,16 +1273,180 @@
 ions %7B%0A%0A
+    @SuppressWarnings(%22HardcodedLineSeparator%22) // required for better violation message formatting.%0A    private static final String VIOLATION_DELIMITER = %22%5Cn  %22;%0A%0A
     priv
@@ -1470,24 +1470,24 @@
 lations() %7B%0A
-
     %7D%0A%0A    /
@@ -3216,38 +3216,51 @@
 tBuilder.append(
-%22%5Cn  %22
+VIOLATION_DELIMITER
 )%0A              
@@ -3758,95 +3758,8 @@
  */%0A
-    @SuppressWarnings(%22HardcodedLineSeparator%22)     // required for better formatting.%0A
     
@@ -4746,95 +4746,8 @@
  */%0A
-    @SuppressWarnings(%22HardcodedLineSeparator%22)     // required for better formatting.%0A
     
@@ -5157,22 +5157,35 @@
 .append(
-%22%5Cn  %22
+VIOLATION_DELIMITER
 )%0A      

Use a constant instead of an inline `\n` symbol.