| /*=============================================================================# |
| # Copyright (c) 2015, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.jcommons.lang; |
| |
| import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.FIELD; |
| import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.PARAMETER; |
| import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.RETURN_TYPE; |
| |
| import java.util.Collection; |
| import java.util.Formatter; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.function.Supplier; |
| |
| |
| @NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD }) |
| public final class ObjectUtils { |
| |
| |
| public static class ToStringBuilder { |
| |
| |
| private static final String INDENT= " "; //$NON-NLS-1$ |
| private static final String CONT_INDENT= INDENT + INDENT; |
| |
| private static final String LINE_PREFIX= "\n"; |
| private static final String PROP_PREFIX= LINE_PREFIX + INDENT; |
| private static final String PROP_ASSIGN= "= "; //$NON-NLS-1$ |
| |
| private static final Object NULL= "<null>"; //$NON-NLS-1$ |
| |
| |
| private final StringBuilder sb; |
| |
| private @Nullable Formatter formatter; |
| |
| |
| public ToStringBuilder() { |
| this.sb= new StringBuilder(); |
| } |
| |
| public ToStringBuilder(final String name) { |
| this.sb= new StringBuilder(name); |
| } |
| |
| public ToStringBuilder(final String name, final Class<?> clazz) { |
| this.sb= new StringBuilder(name); |
| |
| this.sb.append(" ("); //$NON-NLS-1$ |
| this.sb.append(clazz.getName()); |
| this.sb.append(")"); //$NON-NLS-1$ |
| } |
| |
| public ToStringBuilder(final Class<?> defClazz, final Class<?> clazz) { |
| this(defClazz.getSimpleName(), clazz); |
| } |
| |
| public ToStringBuilder(final Class<?> defClazz) { |
| this(defClazz.getSimpleName()); |
| } |
| |
| |
| public StringBuilder getStringBuilder() { |
| return this.sb; |
| } |
| |
| public final void append(final String s) { |
| this.sb.append(s); |
| } |
| |
| public final void append(final String s, final int begin, final int end) { |
| this.sb.append(s, begin, end); |
| } |
| |
| public final void append(final char c) { |
| this.sb.append(c); |
| } |
| |
| public final void append(final int number) { |
| this.sb.append(number); |
| } |
| |
| public final void append(final long number) { |
| this.sb.append(number); |
| } |
| |
| public final void append(final char sep, final String s) { |
| this.sb.append(sep); |
| this.sb.append(s); |
| } |
| |
| public final void append(final char sep, final int number) { |
| this.sb.append(sep); |
| this.sb.append(number); |
| } |
| |
| public final void append(final char sep, final long number) { |
| this.sb.append(sep); |
| this.sb.append(number); |
| } |
| |
| public final void append(final char open, final String s, final char close) { |
| this.sb.append(open); |
| this.sb.append(s); |
| this.sb.append(close); |
| } |
| |
| public final void append(final char open, final int number, final char close) { |
| this.sb.append(open); |
| this.sb.append(number); |
| this.sb.append(close); |
| } |
| |
| public final void append(final char open, final long number, final char close) { |
| this.sb.append(open); |
| this.sb.append(number); |
| this.sb.append(close); |
| } |
| |
| public final void appendFormat(final String valueFormat, final @Nullable Object... valueArgs) { |
| Formatter formatter= this.formatter; |
| if (formatter == null) { |
| formatter= new Formatter(this.sb, Locale.ENGLISH); |
| this.formatter= formatter; |
| } |
| formatter.format(valueFormat, valueArgs); |
| } |
| |
| public final void appendLines(final String lines) { |
| appendLines(lines, LINE_PREFIX + CONT_INDENT); |
| } |
| |
| public final void appendLines(final char sep, final String lines) { |
| this.sb.append(sep); |
| appendLines(lines, LINE_PREFIX + CONT_INDENT); |
| } |
| |
| public final void appendLines(final List<@NonNull String> lines) { |
| final int n= lines.size(); |
| if (n == 0) { |
| return; |
| } |
| append(lines.get(0)); |
| for (int i= 1; i < n; i++) { |
| append(LINE_PREFIX + CONT_INDENT); |
| lines.get(i); |
| } |
| } |
| |
| private void appendLines(final String s, final String contPrefix) { |
| int start= 0; |
| int end= s.indexOf('\n', start); |
| |
| if (end < 0) { |
| append(s); |
| return; |
| } |
| |
| if (end > 0 && s.charAt(end - 1) == '\r') { |
| append(s, start, end - 1); |
| } |
| else { |
| append(s, start, end); |
| } |
| start= end + 1; |
| while ((end= s.indexOf('\n', start)) >= 0) { |
| append(contPrefix); |
| if (end > 0 && s.charAt(end - 1) == '\r') { |
| append(s, start, end - 1); |
| } |
| else { |
| append(s, start, end); |
| } |
| start= end + 1; |
| } |
| if (start < s.length()) { |
| append(contPrefix); |
| append(s, start, s.length()); |
| } |
| } |
| |
| |
| public void addProp(final String name) { |
| this.sb.append(PROP_PREFIX); |
| this.sb.append(name); |
| this.sb.append(PROP_ASSIGN); |
| } |
| |
| public void addProp(final String name, final @Nullable String value) { |
| addProp(name); |
| |
| if (value == null) { |
| this.sb.append(NULL); |
| return; |
| } |
| appendLines(value, PROP_PREFIX + CONT_INDENT); |
| } |
| |
| |
| public void addProp(final String name, final boolean value) { |
| addProp(name); |
| |
| this.sb.append(value); |
| } |
| |
| public void addProp(final String name, final int value) { |
| addProp(name); |
| |
| this.sb.append(value); |
| } |
| |
| public void addProp(final String name, final long value) { |
| addProp(name); |
| |
| this.sb.append(value); |
| } |
| |
| public void addProp(final String name, final float value) { |
| addProp(name); |
| |
| this.sb.append(value); |
| } |
| |
| public void addProp(final String name, final double value) { |
| addProp(name); |
| |
| this.sb.append(value); |
| } |
| |
| |
| public void addProp(final String name, final @Nullable Object value) { |
| addProp(name); |
| |
| if (value == null) { |
| this.sb.append(NULL); |
| return; |
| } |
| appendLines(value.toString(), PROP_PREFIX + CONT_INDENT); |
| } |
| |
| public void addProp(final String name, final @Nullable Collection<?> value) { |
| addProp(name); |
| |
| if (value == null) { |
| this.sb.append(NULL); |
| return; |
| } |
| if (value instanceof List) { |
| this.sb.append('['); |
| } |
| else { |
| this.sb.append('{'); |
| } |
| if (!value.isEmpty()) { |
| for (final Object e : value) { |
| this.sb.append(PROP_PREFIX + INDENT); |
| if (e == null) { |
| this.sb.append(NULL); |
| continue; |
| } |
| appendLines(e.toString(), PROP_PREFIX + INDENT + CONT_INDENT); |
| } |
| this.sb.append(PROP_PREFIX); |
| } |
| if (value instanceof List) { |
| this.sb.append(']'); |
| } |
| else { |
| this.sb.append('}'); |
| } |
| } |
| |
| public void addProp(final String name, final String valueFormat, final @Nullable Object... valueArgs) { |
| addProp(name); |
| |
| appendFormat(valueFormat, valueArgs); |
| } |
| |
| public String build() { |
| return this.sb.toString(); |
| } |
| |
| @Override |
| public String toString() { |
| return this.sb.toString(); |
| } |
| |
| } |
| |
| |
| public static final Class<@NonNull Object> NonNull_Object_TYPE= Object.class; |
| @SuppressWarnings("null") |
| public static final Class<@Nullable Object> Nullable_Object_TYPE= Object.class; |
| |
| public static final Class<@NonNull String> NonNull_String_TYPE= String.class; |
| @SuppressWarnings("null") |
| public static final Class<@Nullable String> Nullable_String_TYPE= String.class; |
| |
| |
| public static boolean isNull(final @Nullable Object object) { |
| return (object == null); |
| } |
| |
| public static boolean isAnyNull(final @Nullable Object object1, final @Nullable Object object2) { |
| return (object1 == null || object2 == null); |
| } |
| |
| @SafeVarargs |
| public static <T> boolean isAnyNull(final T... objects) { |
| for (int i= 0; i < objects.length; i++) { |
| if (objects[i] == null) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| public static <T> @NonNull T nonNullAssert(final @Nullable T object) { |
| if (object == null) { |
| throw new NullPointerException(); |
| } |
| return object; |
| } |
| |
| public static <T> @NonNull T nonNullElse(final @Nullable T object, final @NonNull T elseObj) { |
| return (object != null) ? object : elseObj; |
| } |
| |
| public static <T> @NonNull T nonNullElse(final @Nullable T object, |
| final Supplier<? extends @NonNull T> elseSupplier) { |
| return (object != null) ? object : elseSupplier.get(); |
| } |
| |
| /** |
| * Marks a @NonNull field as late initialized. |
| * |
| * @param <T> the type |
| * @return <code>null</code> |
| */ |
| @SuppressWarnings("null") |
| public static <T> @NonNull T nonNullLateInit() { |
| return null; |
| } |
| |
| public static <T> @Nullable T nullable(final @Nullable T object) { |
| return object; |
| } |
| |
| |
| private ObjectUtils() {} |
| |
| } |