alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (AssertionRenderer.java)

This example Groovy source code file (AssertionRenderer.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

arraylist, assertionrenderer, assertionrenderer, class, comparator, illegalargumentexception, list, string, string, stringbuilder, stringbuilder, util, value, value, valuerecorder

The Groovy AssertionRenderer.java source code

/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.codehaus.groovy.runtime.powerassert;

import java.util.*;

import org.codehaus.groovy.runtime.DefaultGroovyMethods;

/**
 * Creates a string representation of an assertion and its recorded values.
 *
 * @author Peter Niederwieser
 */
public final class AssertionRenderer {
    private final String text;
    private final ValueRecorder recorder;
    private final List<StringBuilder> lines = new ArrayList();
    // startColumns.get(i) is the first non-empty column of lines.get(i)
    private final List<Integer> startColumns = new ArrayList();

    private AssertionRenderer(String text, ValueRecorder recorder) {
        if (text.contains("\n"))
            throw new IllegalArgumentException("source text may not contain line breaks");

        this.text = text;
        this.recorder = recorder;
    }

    /**
     * Creates a string representation of an assertion and its recorded values.
     *
     * @param text     the assertion's source text
     * @param recorder a recorder holding the values recorded during evaluation
     *                 of the assertion
     * @return a string representation of the assertion and its recorded values
     */
    public static String render(String text, ValueRecorder recorder) {
        return new AssertionRenderer(text, recorder).render();
    }

    private String render() {
        renderText();
        sortValues();
        renderValues();
        return linesToString();
    }

    private void renderText() {
        lines.add(new StringBuilder(text));
        startColumns.add(0);
        lines.add(new StringBuilder()); // empty line
        startColumns.add(0);
    }

    private void sortValues() {
        // it's important to use a stable sort here, otherwise
        // renderValues() will skip the wrong values
        Collections.sort(recorder.getValues(),
                new Comparator<Value>() {
                    public int compare(Value v1, Value v2) {
                        return v2.getColumn() - v1.getColumn();
                    }
                }
        );
    }

    private void renderValues() {
        List<Value> values = recorder.getValues();

        nextValue:
        for (int i = 0; i < values.size(); i++) {
            Value value = values.get(i);
            int startColumn = value.getColumn();
            if (startColumn < 1) continue; // skip values with unknown source position

            // if multiple values are associated with the same column, only
            // render the value which was recorded last (i.e. the value
            // corresponding to the outermost expression)
            // important for GROOVY-4344
            Value next = i + 1 < values.size() ? values.get(i + 1) : null;
            if (next != null && next.getColumn() == value.getColumn()) continue;

            String str = valueToString(value.getValue());
            if (str == null) continue; // null signals the value shouldn't be rendered

            String[] strs = str.split("\r\n|\r|\n");
            int endColumn = strs.length == 1 ?
                    value.getColumn() + str.length() : // exclusive
                    Integer.MAX_VALUE; // multi-line strings are always placed on new lines

            for (int j = 1; j < lines.size(); j++)
                if (endColumn < startColumns.get(j)) {
                    placeString(lines.get(j), str, startColumn);
                    startColumns.set(j, startColumn);
                    continue nextValue;
                } else {
                    placeString(lines.get(j), "|", startColumn);
                    if (j > 1) // make sure that no values are ever placed on empty line
                        startColumns.set(j, startColumn + 1); // + 1: no whitespace required between end of value and "|"
                }

            // value could not be placed on existing lines, so place it on new line(s)
            for (String s : strs) {
                StringBuilder newLine = new StringBuilder();
                lines.add(newLine);
                placeString(newLine, s, startColumn);
                startColumns.add(startColumn);
            }
        }
    }

    private String linesToString() {
        StringBuilder firstLine = lines.get(0);
        for (int i = 1; i < lines.size(); i++)
            firstLine.append('\n').append(lines.get(i).toString());
        return firstLine.toString();
    }

    private static void placeString(StringBuilder line, String str, int column) {
        while (line.length() < column)
            line.append(' ');
        line.replace(column - 1, column - 1 + str.length(), str);
    }

    /**
     * Returns a string representation of the given value, or <tt>null if
     * the value should not be included (because it does not add any valuable
     * information).
     *
     * @param value a value
     * @return a string representation of the given value
     */
    private static String valueToString(Object value) {
        String toString;

        try {
            toString = DefaultGroovyMethods.toString(value);
        } catch (Exception e) {
            return String.format("%s (toString() threw %s)",
                    javaLangObjectToString(value), e.getClass().getName());
        }

        if (toString == null) {
            return String.format("%s (toString() == null)", javaLangObjectToString(value));
        }

        if (toString.equals("")) {
            if (hasStringLikeType(value)) return "\"\"";
            return String.format("%s (toString() == \"\")", javaLangObjectToString(value));
        }

        return toString;
    }

    private static boolean hasStringLikeType(Object value) {
        Class<?> clazz = value.getClass();
        return clazz == String.class || clazz == StringBuffer.class || clazz == StringBuilder.class;
    }

    private static String javaLangObjectToString(Object value) {
        String hash = Integer.toHexString(System.identityHashCode(value));
        return value.getClass().getName() + "@" + hash;
    }
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy AssertionRenderer.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.