001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2018 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029package edu.wisc.ssec.mcidasv.util; 030 031import java.util.Arrays; 032import java.util.Objects; 033 034/** 035 * Utility class for {@code toString()} methods. 036 * 037 * <p>Largely taken from Guava's {@code toStringHelper()}, with some 038 * formatting differences as well as the hash code for the given instance.</p> 039 */ 040public class MakeToString { 041 042 private final ValueHolder head = new ValueHolder(); 043 private final String className; 044 private final int instanceHashCode; 045 046 private boolean omitNullValues = false; 047 private ValueHolder tail = head; 048 049 private MakeToString(Object instance) { 050 Objects.requireNonNull(instance, "Cannot generate toString for a null object"); 051 className = instance.getClass().getSimpleName(); 052 instanceHashCode = instance.hashCode(); 053 } 054 055 private MakeToString(String clazzName) { 056 className = clazzName; 057 instanceHashCode = -1; 058 } 059 060 public static MakeToString fromInstance(Object instance) { 061 return new MakeToString(instance); 062 } 063 064 public static MakeToString fromClass(Class<?> clazz) { 065 return new MakeToString(clazz.getSimpleName()); 066 } 067 068 public MakeToString omitNullValues() { 069 omitNullValues = true; 070 return this; 071 } 072 073 public MakeToString addQuoted(String name, Object value) { 074 return addHolder(name, '"' + String.valueOf(value) + '"'); 075 } 076 077 public MakeToString add(String name, Object value) { 078 return addHolder(name, String.valueOf(value)); 079 } 080 081 public MakeToString add(String name, long value) { 082 return addHolder(name, String.valueOf(value)); 083 } 084 085 public MakeToString add(String name, boolean value) { 086 return addHolder(name, String.valueOf(value)); 087 } 088 089 public MakeToString add(String name, int value) { 090 return addHolder(name, String.valueOf(value)); 091 } 092 093 public MakeToString add(String name, char value) { 094 return addHolder(name, String.valueOf(value)); 095 } 096 097 public MakeToString add(String name, float value) { 098 return addHolder(name, String.valueOf(value)); 099 } 100 101 public MakeToString add(String name, double value) { 102 return addHolder(name, String.valueOf(value)); 103 } 104 105 private ValueHolder addHolder() { 106 ValueHolder valueHolder = new ValueHolder(); 107 tail = tail.next = valueHolder; 108 return valueHolder; 109 } 110 111 private MakeToString addHolder(String name, Object value) { 112 ValueHolder valueHolder = addHolder(); 113 valueHolder.name = Objects.requireNonNull(name); 114 valueHolder.value = value; 115 return this; 116 } 117 118 /** 119 * After calling this method, you can keep adding more properties to 120 * later call toString() again and get a more complete representation of 121 * the same object; but properties cannot be removed, so this only allows 122 * limited reuse of the helper instance. The helper allows duplication of 123 * properties (multiple name/value pairs with the same name can be added). 124 */ 125 @Override public String toString() { 126 boolean omitNullValuesSnapshot = omitNullValues; 127 String hex = Integer.toHexString(instanceHashCode); 128 StringBuilder builder = 129 new StringBuilder((className.length() + hex.length()) * 10); 130 builder.append('[').append(className); 131 if (instanceHashCode != -1) { 132 builder.append('@').append(hex); 133 } 134 builder.append(": "); 135 String nextSeparator = ""; 136 for (ValueHolder valueHolder = head.next; 137 valueHolder != null; 138 valueHolder = valueHolder.next) 139 { 140 Object value = valueHolder.value; 141 if (!omitNullValuesSnapshot || (value != null)) { 142 builder.append(nextSeparator); 143 nextSeparator = ", "; 144 145 if (valueHolder.name != null) { 146 builder.append(valueHolder.name).append('='); 147 } 148 if ((value != null) && value.getClass().isArray()) { 149 Object[] objectArray = { value }; 150 String arrayString = Arrays.deepToString(objectArray); 151 builder.append(arrayString, 1, arrayString.length() - 1); 152 } else { 153 builder.append(value); 154 } 155 } 156 } 157 return builder.append(']').toString(); 158 } 159 160 private static final class ValueHolder { 161 String name; 162 Object value; 163 ValueHolder next; 164 } 165}