Package com.alibaba.citrus.util

Source Code of com.alibaba.citrus.util.ToStringBuilder$CollectionBuilder

/*
* Copyright 2010 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.citrus.util;

import static com.alibaba.citrus.util.CollectionUtil.*;
import static com.alibaba.citrus.util.ObjectUtil.*;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.alibaba.citrus.util.internal.IndentableStringBuilder;

/**
* ����ʵ��<code>toString()</code>������
*
* @author Michael Zhou
*/
public class ToStringBuilder {
    private static final String NULL_STR = "<null>";
    private static final int ARRAY_ITEMS_PER_LINE = 10;
    private final IndentableStringBuilder out;
    private final Formatter formatter;
    private boolean printDescription;

    public ToStringBuilder() {
        this(-1);
    }

    public ToStringBuilder(int indent) {
        this.out = new IndentableStringBuilder(indent);
        this.formatter = new Formatter(out);
    }

    /**
     * ����������ݡ�
     */
    public void clear() {
        out.clear();
        printDescription = false;
    }

    /**
     * ȡ�õײ�indentable string builder��
     */
    public IndentableStringBuilder out() {
        return out;
    }

    /**
     * ��ӡ����ʱ���Ƿ��ӡ��������
     */
    public boolean isPrintDescription() {
        return printDescription;
    }

    /**
     * ��ӡ����ʱ���Ƿ��ӡ��������
     */
    public ToStringBuilder setPrintDescription(boolean printDescription) {
        this.printDescription = printDescription;
        return this;
    }

    /**
     * ����һ��������
     */
    public ToStringBuilder start() {
        out.start();
        return this;
    }

    /**
     * ����һ��������
     */
    public ToStringBuilder start(String beginQuote, String endQuote) {
        out.start(beginQuote, endQuote);
        return this;
    }

    /**
     * ����һ��������ע�⣬������֮ǰ�������ٵ���һ��end()����ȷ�����Ļ��п��Ա������
     */
    public ToStringBuilder end() {
        out.end();
        return this;
    }

    public ToStringBuilder format(String format, Object... args) {
        formatter.format(format, args);
        return this;
    }

    public ToStringBuilder append(boolean value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(byte value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(char value) {
        out.append(value);
        return this;
    }

    public ToStringBuilder append(double value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(float value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(int value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(long value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder append(short value) {
        out.append(String.valueOf(value));
        return this;
    }

    public ToStringBuilder appendNull() {
        out.append(NULL_STR);
        return this;
    }

    public ToStringBuilder append(Object value) {
        if (value == null) {
            appendNull();
        } else if (value instanceof Object[]) {
            appendArray((Object[]) value);
        } else if (value.getClass().isArray()) {
            appendPrimitiveArray(value, -1);
        } else if (value instanceof Collection<?>) {
            appendCollection((Collection<?>) value);
        } else if (value instanceof Map<?, ?>) {
            appendMap((Map<?, ?>) value);
        } else if (value instanceof StructureBuilder) {
            ((StructureBuilder) value).appendTo(this);
        } else {
            out.append(value.toString());
        }

        return this;
    }

    public ToStringBuilder appendDescription(Object value) {
        if (value != null) {
            if (value.getClass().isArray()) {
                format("%s[%d]", value.getClass().getComponentType().getCanonicalName(), Array.getLength(value));
            } else {
                format("%s@%x", value.getClass().getCanonicalName(), System.identityHashCode(value));
            }
        }

        return this;
    }

    public ToStringBuilder appendHangingIndent(Object value) {
        return appendHangingIndent(value, -1);
    }

    private ToStringBuilder appendHangingIndent(Object value, int hangingIndent) {
        out.startHangingIndent(hangingIndent);
        append(value);
        out.end();

        return this;
    }

    public ToStringBuilder appendMap(Map<?, ?> map) {
        return appendMap(map, false);
    }

    public ToStringBuilder appendMap(Map<?, ?> map, boolean sort) {
        if (map == null) {
            appendNull();
        } else {
            new MapBuilder().setSortKeys(sort).setPrintCount(true).appendAll(map).appendTo(this);
        }

        return this;
    }

    public ToStringBuilder appendCollection(Collection<?> list) {
        return appendCollection(list, false);
    }

    public ToStringBuilder appendCollection(Collection<?> list, boolean oneLine) {
        if (list == null) {
            appendNull();
        } else {
            new CollectionBuilder().setPrintCount(true).setOneLine(oneLine).appendAll(list).appendTo(this);
        }

        return this;
    }

    public ToStringBuilder appendArray(Object[] list) {
        if (isPrintDescription()) {
            appendDescription(list);
        }

        return appendCollection(asList(list));
    }

    public ToStringBuilder appendArray(boolean[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(boolean[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(byte[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(byte[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(char[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(char[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(double[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(double[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(float[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(float[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(int[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(int[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(long[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(long[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    public ToStringBuilder appendArray(short[] list) {
        return appendPrimitiveArray(list, -1);
    }

    public ToStringBuilder appendArray(short[] list, int offset, int length) {
        return appendPrimitiveArray(list, -1, offset, length);
    }

    private ToStringBuilder appendPrimitiveArray(Object primitiveList, int itemsPerLine) {
        return appendPrimitiveArray(primitiveList, itemsPerLine, -1, -1);
    }

    private ToStringBuilder appendPrimitiveArray(Object primitiveList, int itemsPerLine, int offset, int length) {
        if (primitiveList == null) {
            return appendNull();
        }

        if (itemsPerLine <= 0) {
            itemsPerLine = ARRAY_ITEMS_PER_LINE;
        }

        int arrayLength = Array.getLength(primitiveList);

        if (offset < 0) {
            offset = 0;
        }

        if (length < 0 || offset + length > arrayLength) {
            length = arrayLength - offset;
        }

        int lengthWidth = String.valueOf(length).length();
        String countPattern = "[%0" + lengthWidth + "d-%0" + lengthWidth + "d/%" + lengthWidth + "d] ";

        if (isPrintDescription()) {
            appendDescription(primitiveList).append(" ");
        }

        if (length == 0) {
            if (!isPrintDescription()) {
                append("[]");
            }

            return this;
        } else if (length <= itemsPerLine) {
            append("[");

            for (int i = 0; i < length; i++) {
                appendPrimitive(Array.get(primitiveList, i), false);

                if (i < length - 1) {
                    append(", ");
                }
            }

            append("]");
        } else {
            start("[", "]");

            int lines = (length + itemsPerLine - 1) / itemsPerLine;

            for (int l = 0; l < lines; l++) {
                int start = l * itemsPerLine + offset;
                int end = Math.min((l + 1) * itemsPerLine, length) + offset;

                format(countPattern, start + 1, end, arrayLength);

                for (int i = start; i < end; i++) {
                    Object value = Array.get(primitiveList, i);
                    appendPrimitive(value, true);

                    if (i < end - 1) {
                        format(" ");
                    }
                }

                if (l < lines - 1) {
                    format("%n");
                }
            }

            end();
        }

        return this;
    }

    private void appendPrimitive(Object value, boolean fixedWidth) {
        String pattern;

        if (value instanceof Byte) {
            pattern = fixedWidth ? "%02x" : "%x";
        } else if (value instanceof Boolean) {
            pattern = fixedWidth ? "%-5s" : "%s";
        } else {
            pattern = "%s";
        }

        format(pattern, value);
    }

    @Override
    public String toString() {
        return out.toString();
    }

    /**
     * ����������һ���ṹ��builder�����磺map��collection�ȡ�
     *
     * @author Michael Zhou
     */
    public static interface StructureBuilder {
        ToStringBuilder appendTo(ToStringBuilder toStringBuilder);
    }

    /**
     * ����һϵ��key/valueֵ�ԡ�
     */
    public static class MapBuilder implements StructureBuilder {
        private final Map<String, Object> map = createLinkedHashMap();
        private boolean sortKeys;
        private boolean printCount;

        public MapBuilder clear() {
            map.clear();
            sortKeys = false;
            printCount = false;
            return this;
        }

        public boolean isSortKeys() {
            return sortKeys;
        }

        public MapBuilder setSortKeys(boolean sortKeys) {
            this.sortKeys = sortKeys;
            return this;
        }

        public boolean isPrintCount() {
            return printCount;
        }

        public MapBuilder setPrintCount(boolean printCount) {
            this.printCount = printCount;
            return this;
        }

        public MapBuilder append(String key, Object value) {
            key = defaultIfNull(key, NULL_STR);
            map.put(key, value);
            return this;
        }

        public MapBuilder appendAll(Map<?, ?> map) {
            if (map != null) {
                for (Map.Entry<?, ?> entry : map.entrySet()) {
                    String key = entry.getKey() == null ? NULL_STR : entry.getKey().toString();

                    append(key, entry.getValue());
                }
            }

            return this;
        }

        public void remove(String key) {
            map.remove(key);
        }

        public ToStringBuilder appendTo(ToStringBuilder toStringBuilder) {
            if (map.isEmpty()) {
                toStringBuilder.append("{}");
                return toStringBuilder;
            }

            List<String> keys = createArrayList(map.keySet());

            if (sortKeys) {
                Collections.sort(keys);
            }

            int maxKeyLength = 0;

            for (String key : keys) {
                maxKeyLength = Math.max(maxKeyLength, key.length());
            }

            String pattern;

            if (printCount) {
                int size = keys.size();
                int sizeWidth = String.valueOf(size).length();

                pattern = "[%" + sizeWidth + "d/" + size + "] %-" + maxKeyLength + "s = ";
            } else {
                pattern = "%-" + maxKeyLength + "s = ";
            }

            int count = 1;

            toStringBuilder.start("{", "}");

            for (String key : keys) {
                Object value = map.get(key);

                if (printCount) {
                    toStringBuilder.format(pattern, count++, key);
                } else {
                    toStringBuilder.format(pattern, key);
                }

                toStringBuilder.out().startHangingIndent();
                toStringBuilder.append(value);
                toStringBuilder.out().end();
            }

            return toStringBuilder.end();
        }

        @Override
        public String toString() {
            return appendTo(new ToStringBuilder()).toString();
        }
    }

    /**
     * ����ֵ���б�
     */
    public static class CollectionBuilder implements StructureBuilder {
        private final List<Object> list = createLinkedList();
        private boolean sort;
        private boolean printCount;
        private boolean oneLine;

        public CollectionBuilder clear() {
            list.clear();
            sort = false;
            printCount = false;
            oneLine = false;
            return this;
        }

        public boolean isSort() {
            return sort;
        }

        public CollectionBuilder setSort(boolean sort) {
            this.sort = sort;
            return this;
        }

        public boolean isPrintCount() {
            return printCount;
        }

        public CollectionBuilder setPrintCount(boolean printCount) {
            this.printCount = printCount;
            return this;
        }

        public boolean isOneLine() {
            return oneLine;
        }

        public CollectionBuilder setOneLine(boolean oneLine) {
            this.oneLine = oneLine;
            return this;
        }

        public CollectionBuilder append(Object value) {
            list.add(value);
            return this;
        }

        public CollectionBuilder appendAll(Collection<?> list) {
            if (list != null) {
                for (Object value : list) {
                    append(value);
                }
            }

            return this;
        }

        public CollectionBuilder appendAll(Object[] list) {
            return appendAll(asList(list));
        }

        public ToStringBuilder appendTo(ToStringBuilder toStringBuilder) {
            if (list.isEmpty()) {
                toStringBuilder.append("[]");
                return toStringBuilder;
            }

            List<Object> list = this.list;

            if (sort) {
                list = createArrayList(list);

                Collections.sort(list, new Comparator<Object>() {
                    @SuppressWarnings({ "unchecked", "rawtypes" })
                    public int compare(Object o1, Object o2) {
                        if (o1 instanceof Comparable<?> && o2 instanceof Comparable<?>) {
                            return ((Comparable) o1).compareTo(o2);
                        }

                        return 0;
                    }
                });
            }

            if (oneLine) {
                toStringBuilder.append("[");

                for (Iterator<Object> i = list.iterator(); i.hasNext();) {
                    toStringBuilder.append(i.next());

                    if (i.hasNext()) {
                        toStringBuilder.append(", ");
                    }
                }

                toStringBuilder.append("]");

                return toStringBuilder;
            }

            int size = list.size();
            int sizeWidth = String.valueOf(size).length();
            String pattern = "[%" + sizeWidth + "d/" + size + "] ";
            int count = 1;

            toStringBuilder.start("[", "]");

            for (Object value : list) {
                if (printCount) {
                    toStringBuilder.format(pattern, count++);
                }

                toStringBuilder.out().startHangingIndent();
                toStringBuilder.append(value);
                toStringBuilder.out().end();
            }

            return toStringBuilder.end();
        }

        @Override
        public String toString() {
            return appendTo(new ToStringBuilder()).toString();
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.util.ToStringBuilder$CollectionBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.