com.landawn.abacus.util.N Maven / Gradle / Ivy
Show all versions of abacus-android Show documentation
/*
* Copyright (c) 2015, Haiyang Li.
*
* 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.landawn.abacus.util;
import static com.landawn.abacus.util.D._BACKSLASH;
import static com.landawn.abacus.util.D._QUOTATION_D;
import static com.landawn.abacus.util.D._QUOTATION_S;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.Normalizer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.RandomAccess;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import com.landawn.abacus.DataSet;
import com.landawn.abacus.DirtyMarker;
import com.landawn.abacus.EntityId;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.Internal;
import com.landawn.abacus.core.EntityManagerUtil;
import com.landawn.abacus.core.MapEntity;
import com.landawn.abacus.core.RowDataSet;
import com.landawn.abacus.exception.AbacusException;
import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.exception.UncheckedSQLException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.parser.JSONDeserializationConfig;
import com.landawn.abacus.parser.JSONParser;
import com.landawn.abacus.parser.JSONSerializationConfig;
import com.landawn.abacus.parser.JSONSerializationConfig.JSC;
import com.landawn.abacus.parser.KryoParser;
import com.landawn.abacus.parser.ParserFactory;
import com.landawn.abacus.parser.XMLDeserializationConfig;
import com.landawn.abacus.parser.XMLParser;
import com.landawn.abacus.parser.XMLSerializationConfig;
import com.landawn.abacus.parser.XMLSerializationConfig.XSC;
import com.landawn.abacus.type.EntityType;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.type.TypeFactory;
import com.landawn.abacus.util.Pair.IntPair;
import com.landawn.abacus.util.Retry.Retry0;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.BooleanPredicate;
import com.landawn.abacus.util.function.BytePredicate;
import com.landawn.abacus.util.function.CharPredicate;
import com.landawn.abacus.util.function.Consumer;
import com.landawn.abacus.util.function.DoublePredicate;
import com.landawn.abacus.util.function.FloatPredicate;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IndexedBiFunction;
import com.landawn.abacus.util.function.IndexedConsumer;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.IntPredicate;
import com.landawn.abacus.util.function.LongPredicate;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.ShortPredicate;
import com.landawn.abacus.util.function.ToBooleanFunction;
import com.landawn.abacus.util.function.ToByteFunction;
import com.landawn.abacus.util.function.ToCharFunction;
import com.landawn.abacus.util.function.ToDoubleFunction;
import com.landawn.abacus.util.function.ToFloatFunction;
import com.landawn.abacus.util.function.ToIntFunction;
import com.landawn.abacus.util.function.ToLongFunction;
import com.landawn.abacus.util.function.ToShortFunction;
import com.landawn.abacus.util.stream.DoubleStream;
import com.landawn.abacus.util.stream.FloatStream;
import com.landawn.abacus.util.stream.Stream;
/**
*
* Note: This class includes codes copied from Apache Commons Lang, Google Guava and other open source projects under the Apache License 2.0.
* The methods copied from other libraries/frameworks/projects may be modified in this class.
*
* Class N
is a general java utility class. It provides the most daily used operations for Object/primitive types/String/Array/Collection/Map/Entity/Date...:
*
*
*
* - =======================================================================
*
- String operations:
* stringOf/valueOf/join/isNullOrEmpty/notNullOrEmpty/
* checkNullOrEmpty/indexOfXXX/lastIndexOfXXX
* /ordinalIndexOf/startsWithXXX/endsWithXXX
* /containsXXX/commonPrefix/commonSuffix/difference/equals/equalsIgnoreCase/trim
* /strip/capitalize/uncapitalize/lowerCase/upperCase/swapCase/padStart/padEnd
* /repeat/reverse/replace/replaceAll/replacePattern/unicodeEscaped/formatQuotation
* /normalizeSpace/deleteWhitespace/chomp/chop/abbreviate/...
*
*
*
* - =======================================================================
*
- Array operations:
* newArray/asArray/asXXX/array2XXX/isNullOrEmpty
* /notNullOrEmpty/checkNullOrEmpty/sort/parallelSort/binarySearch
* /copy/copyOf/copyOfRange/clone
* /indexOfXXX/lastIndexOfXXX/containsXXX/fill/concat/add
* /addAll/insert/remove/removeAll/delete/deleteAll/replaceAll
* /reverse/swap/rotate/shuffle
* /sum/avg/min/max/median/join/filter/...
*
*
*
* - =======================================================================
*
- Collection operations:
* newXXX/asXXX/sort/parallelSort/binarySearch/isNullOrEmpty
* /notNullOrEmpty/checkNullOrEmpty/indexOfXXX/containsXXX
* /xxx2String/string2XXX/fill/reverse/swap/sum/avg/min/max/median/filter/...
*
*
*
* - =======================================================================
*
- Map operations:
* newXXX/asXXX/isNullOrEmpty/notNullOrEmpty/checkNullOrEmpty/entity2Map/
* deepEntity2Map/entity2FlatMap/map2Entity/filter/...
*
*
*
* - =======================================================================
*
- Entity/Properties operations:
* newXXX/asXXX/copy/clone/erase/eraseAll/getPropValue/setPropValue/
* setPropValueByGet/entity2Map/deepEntity2Map/entity2FlatMap/map2Entity/formalizePropName/getPropNameByMethod/...
* -
*
*
*
* - =======================================================================
*
- Date/Calendar operations:
* asXXX/format/currentXXX/roll/...
*
*
*
* - =======================================================================
*
- primitive types operations:
* arrayOf/listOf/isPrimitive/isPrimitiveWapper/isPrimitiveOrWapper/sum/avg/min/max/median/unwrap/wrap/...
*
*
*
* - =======================================================================
*
- Factory(create/new) operations/:
* newXXX/createXXX/asXXX/...
*
*
*
* - =======================================================================
*
- Reflect Class/Method operations:
* newXXX/getPackage/getPackageName/forClass/getClassName/getSimpleClassName
* /getCanonicalClassName /getDeclaredConstructor
* /getDeclaredMethod/findDeclaredMethodByName
* /getEnclosingClass/getPropField/getPropGetMethod/getPropGetMethodList
* /getPropSetMethod/getPropSetMethodList/invokeConstructor/invokeMethod/...
*
*
*
* - =======================================================================
*
- General Object operations:
* stringOf/valueOf/toString/hashCod/equals/deepToString/deepHashCodee
* /deepEquals/compare/json2XML/xml2JSON
* /base64XXXEncode/base64XXXDecode/urlEncode
* /urlDecode/getDefaultValue/uuid/enumListOf/enumSetOf
* /registerNonEntityClass/registerPropGetSetMethod/registerXMLBindingClassForPropGetSetMethod/getType
* /asyncExecute/getCharsForReadOnly/sleep/println/...
*
*
*
*
*
* When to throw exception? It's designed to avoid throwing any unnecessary
* exception if the contract defined by method is not broken. for example, if
* user tries to reverse a null or empty String. the input String will be
* returned. But exception will be thrown if trying to repeat/swap a null or
* empty string or operate Array/Collection by adding/removing...
*
* @author Haiyang Li
*
* @version $Revision: 0.8 $ 07/03/10
*/
public final class N {
private static final Logger logger = LoggerFactory.getLogger(N.class);
private static final AsyncExecutor asyncExecutor = new AsyncExecutor(256, 300L, TimeUnit.SECONDS);
// ... it has to be big enough to make it's safety to add element to
// ArrayBlockingQueue.
private static final int POOL_SIZE;
static {
int multi = (int) (Runtime.getRuntime().maxMemory() / ((1024 * 1024) * 256));
POOL_SIZE = N.max(1000, N.min(1000 * multi, 8192));
}
public static final String HOST_NAME;
static {
String hostName = null;
final boolean IS_PLATFORM_ANDROID = System.getProperty("java.vendor").toUpperCase().contains("ANDROID")
|| System.getProperty("java.vm.vendor").toUpperCase().contains("ANDROID");
// implementation for android support
if (IS_PLATFORM_ANDROID) {
try {
hostName = asyncExecute(new Callable() {
@Override
public String call() throws Exception {
return InetAddress.getLocalHost().getHostName();
}
}).get();
} catch (Throwable e) {
logger.error("Failed to get host name");
}
} else {
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (Throwable e) {
logger.error("Failed to get host name");
}
}
HOST_NAME = hostName;
}
public static final int CPU_CORES = Runtime.getRuntime().availableProcessors();
public static final int MAX_MEMORY_IN_MB = (int) (Runtime.getRuntime().maxMemory() / (1024 * 1024));
// ...
public static final String OS_NAME = System.getProperty("os.name");
public static final String OS_VERSION = System.getProperty("os.version");
public static final String OS_ARCH = System.getProperty("os.arch");
//...
public static final boolean IS_OS_WINDOWS = OS_NAME.toUpperCase().contains("WINDOWS");
public static final boolean IS_OS_MAC = OS_NAME.toUpperCase().contains("MAC");
public static final boolean IS_OS_MAC_OSX = OS_NAME.toUpperCase().contains("MAC OS X");
public static final boolean IS_OS_LINUX = OS_NAME.toUpperCase().contains("LINUX");
public static final boolean IS_PLATFORM_ANDROID = System.getProperty("java.vendor").toUpperCase().contains("ANDROID")
|| System.getProperty("java.vm.vendor").toUpperCase().contains("ANDROID");
// ...
public static final String JAVA_HOME = System.getProperty("java.home");
public static final String JAVA_VERSION = System.getProperty("java.version");
public static final String JAVA_VENDOR = System.getProperty("java.vendor");
static final String JAVA_VENDOR_URL = System.getProperty("java.vendor.url");
public static final String JAVA_CLASS_PATH = System.getProperty("java.class.path");
public static final String JAVA_CLASS_VERSION = System.getProperty("java.class.version");
static final String JAVA_LIBRARY_PATH = System.getProperty("java.library.path");
public static final String JAVA_RUNTIME_NAME = System.getProperty("java.runtime.name");
public static final String JAVA_RUNTIME_VERSION = System.getProperty("java.runtime.version");
public static final String JAVA_SPECIFICATION_NAME = System.getProperty("java.specification.name");
public static final String JAVA_SPECIFICATION_VENDOR = System.getProperty("java.specification.vendor");
public static final String JAVA_SPECIFICATION_VERSION = System.getProperty("java.specification.version");
public static final String JAVA_VM_INFO = System.getProperty("java.vm.info");
public static final String JAVA_VM_NAME = System.getProperty("java.vm.name");
public static final String JAVA_VM_SPECIFICATION_NAME = System.getProperty("java.vm.specification.name");
public static final String JAVA_VM_SPECIFICATION_VENDOR = System.getProperty("java.vm.specification.vendor");
public static final String JAVA_VM_SPECIFICATION_VERSION = System.getProperty("java.vm.specification.version");
public static final String JAVA_VM_VENDOR = System.getProperty("java.vm.vendor");
public static final String JAVA_VM_VERSION = System.getProperty("java.vm.version");
static final String JAVA_COMPILER = System.getProperty("java.compiler");
static final String JAVA_ENDORSED_DIRS = System.getProperty("java.endorsed.dirs");
static final String JAVA_EXT_DIRS = System.getProperty("java.ext.dirs");
// ...
static final String JAVA_AWT_FONTS = System.getProperty("java.awt.fonts");
static final String JAVA_AWT_GRAPHICSENV = System.getProperty("java.awt.graphicsenv");
static final String JAVA_AWT_HEADLESS = System.getProperty("java.awt.headless");
static final String JAVA_AWT_PRINTERJOB = System.getProperty("java.awt.printerjob");
public static final String JAVA_IO_TMPDIR = System.getProperty("java.io.tmpdir");
static final String JAVA_UTIL_PREFS_PREFERENCES_FACTORY = System.getProperty("java.util.prefs.PreferencesFactory");
// ...
public static final String USER_DIR = System.getProperty("user.dir");
public static final String USER_HOME = System.getProperty("user.home");
public static final String USER_NAME = System.getProperty("user.name");
public static final String USER_TIMEZONE = System.getProperty("user.timezone");
public static final String USER_LANGUAGE = System.getProperty("user.language");
public static final String USER_COUNTRY = System.getProperty("user.country") == null ? System.getProperty("user.region")
: System.getProperty("user.country");
// ...
public static final String PATH_SEPARATOR = System.getProperty("path.separator");
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
// ...
static final String ELEMENT_SEPARATOR = Type.ELEMENT_SEPARATOR;
static final char[] ELEMENT_SEPARATOR_CHAR_ARRAY = Type.ELEMENT_SEPARATOR_CHAR_ARRAY;
/**
* An empty immutable {@code Boolean} array.
*/
static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
/**
* An empty immutable {@code Character} array.
*/
static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
/**
* An empty immutable {@code Byte} array.
*/
static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
/**
* An empty immutable {@code Short} array.
*/
static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
/**
* An empty immutable {@code Integer} array.
*/
static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
/**
* An empty immutable {@code Long} array.
*/
static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
/**
* An empty immutable {@code Float} array.
*/
static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
/**
* An empty immutable {@code Double} array.
*/
static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
/**
* An empty immutable {@code Class} array.
*/
static final Class>[] EMPTY_CLASS_ARRAY = new Class[0];
static final String NULL_STRING = "null".intern();
static final char[] NULL_CHAR_ARRAY = NULL_STRING.toCharArray();
static final String TRUE = Boolean.TRUE.toString().intern();
static final char[] TRUE_CHAR_ARRAY = TRUE.toCharArray();
static final String FALSE = Boolean.FALSE.toString().intern();
static final char[] FALSE_CHAR_ARRAY = FALSE.toCharArray();
// ...
static final char CHAR_0 = D.CHAR_0;
/**
*
* @see JLF:
* Escape Sequences for Character and String Literals
* @since 2.2
*/
static final char CHAR_LF = D.CHAR_LF;
/**
*
* @see JLF:
* Escape Sequences for Character and String Literals
* @since 2.2
*/
static final char CHAR_CR = D.CHAR_CR;
// ...
/**
* The index value when an element is not found in a list or array:
* {@code -1}. This value is returned by methods in this class and can also
* be used in comparisons with values returned by various method from
* {@link java.util.List} .
*/
static final int INDEX_NOT_FOUND = -1;
// ...
public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
/**
* The system default time zone
*/
public static final TimeZone LOCAL_TIME_ZONE = Calendar.getInstance().getTimeZone();
/**
* Date format.
*/
public static final String LOCAL_YEAR_FORMAT = "yyyy";
public static final String LOCAL_MONTH_DAY_FORMAT = "MM-dd";
static final String LOCAL_MONTH_DAY_FORMAT_SLASH = "MM/dd";
public static final String LOCAL_DATE_FORMAT = "yyyy-MM-dd";
static final String LOCAL_DATE_FORMAT_SLASH = "yyyy/MM/dd";
public static final String LOCAL_TIME_FORMAT = "HH:mm:ss";
public static final String LOCAL_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
static final String LOCAL_DATETIME_FORMAT_SLASH = "yyyy/MM/dd HH:mm:ss";
public static final String LOCAL_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
static final String LOCAL_TIMESTAMP_FORMAT_SLASH = "yyyy/MM/dd HH:mm:ss.SSS";
/**
* It's default date/time format.
*/
public static final String ISO_8601_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
/**
* It's default timestamp format.
*/
public static final String ISO_8601_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final Map> dfPool = new ObjectPool<>(64);
private static final Map> calendarPool = new ObjectPool<>(64);
private static final Queue utcTimestampDFPool = new ArrayBlockingQueue<>(POOL_SIZE);
private static final Queue utcDateTimeDFPool = new ArrayBlockingQueue<>(POOL_SIZE);
private static final Queue utcCalendarPool = new ArrayBlockingQueue<>(POOL_SIZE);
// ...
private static final Queue utcTimestampFormatCharsPool = new ArrayBlockingQueue<>(POOL_SIZE);
private static final DatatypeFactory dataTypeFactory;
static {
DatatypeFactory temp = null;
try {
temp = DatatypeFactory.newInstance();
} catch (Exception e) {
// ignore.
// logger.error("Failed to initialize XMLGregorianCalendarType: " +
// e.getMessage(), e);
}
dataTypeFactory = temp;
}
/**
* An empty immutable {@code boolean} array.
*/
public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
/**
* An empty immutable {@code char} array.
*/
public static final char[] EMPTY_CHAR_ARRAY = new char[0];
/**
* An empty immutable {@code byte} array.
*/
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/**
* An empty immutable {@code short} array.
*/
public static final short[] EMPTY_SHORT_ARRAY = new short[0];
/**
* An empty immutable {@code int} array.
*/
public static final int[] EMPTY_INT_ARRAY = new int[0];
/**
* An empty immutable {@code long} array.
*/
public static final long[] EMPTY_LONG_ARRAY = new long[0];
/**
* An empty immutable {@code float} array.
*/
public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
/**
* An empty immutable {@code double} array.
*/
public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
/**
* An empty immutable {@code String} array.
*/
public static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* An empty immutable {@code Object} array.
*/
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
@SuppressWarnings("rawtypes")
public static final List EMPTY_LIST = Collections.EMPTY_LIST;
@SuppressWarnings("rawtypes")
public static final Set EMPTY_SET = Collections.EMPTY_SET;
@SuppressWarnings("rawtypes")
public static final Map EMPTY_MAP = Collections.EMPTY_MAP;
@SuppressWarnings("rawtypes")
public static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator();
// ...
public static final String EMPTY_STRING = "".intern();
// ...
public static final Object NULL_MASK = new NullMask();
// ...
private static final char[][][] cbufOfSTDInt = new char[5][][];
static {
for (int i = 0, j = 1; i < 5; i++, j = j * 10) {
cbufOfSTDInt[i] = new char[j][];
for (int k = 0; k < j; k++) {
if (i == 1) {
cbufOfSTDInt[i][k] = String.valueOf(k).toCharArray();
} else if (i == 2) {
if (k < 10) {
cbufOfSTDInt[i][k] = ("0" + String.valueOf(k)).toCharArray();
} else {
cbufOfSTDInt[i][k] = String.valueOf(k).toCharArray();
}
} else if (i == 3) {
if (k < 10) {
cbufOfSTDInt[i][k] = ("00" + String.valueOf(k)).toCharArray();
} else if (k < 100) {
cbufOfSTDInt[i][k] = ("0" + String.valueOf(k)).toCharArray();
} else {
cbufOfSTDInt[i][k] = String.valueOf(k).toCharArray();
}
} else if (i == 4) {
if (k < 10) {
cbufOfSTDInt[i][k] = ("000" + String.valueOf(k)).toCharArray();
} else if (k < 100) {
cbufOfSTDInt[i][k] = ("00" + String.valueOf(k)).toCharArray();
} else if (k < 1000) {
cbufOfSTDInt[i][k] = ("0" + String.valueOf(k)).toCharArray();
} else {
cbufOfSTDInt[i][k] = String.valueOf(k).toCharArray();
}
}
}
}
}
static final String BACKSLASH_ASTERISK = "*";
// ...
private static final int REVERSE_THRESHOLD = 18;
private static final int FILL_THRESHOLD = 25;
private static final int REPLACEALL_THRESHOLD = 11;
// ...
static final Random RAND = new SecureRandom();
@SuppressWarnings("rawtypes")
private static final Comparator NULL_MIN_COMPARATOR = Comparators.nullsFirst();
@SuppressWarnings("rawtypes")
private static final Comparator NULL_MAX_COMPARATOR = Comparators.nullsLast();
@SuppressWarnings("rawtypes")
private static final Comparator OBJ_COMPARATOR = Comparators.OBJ_COMPARATOR;
// ...
static final Map, Object> CLASS_EMPTY_ARRAY = new ConcurrentHashMap<>();
static {
CLASS_EMPTY_ARRAY.put(boolean.class, N.EMPTY_BOOLEAN_ARRAY);
CLASS_EMPTY_ARRAY.put(Boolean.class, N.EMPTY_BOOLEAN_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(char.class, N.EMPTY_CHAR_ARRAY);
CLASS_EMPTY_ARRAY.put(Character.class, N.EMPTY_CHARACTER_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(byte.class, N.EMPTY_BYTE_ARRAY);
CLASS_EMPTY_ARRAY.put(Byte.class, N.EMPTY_BYTE_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(short.class, N.EMPTY_SHORT_ARRAY);
CLASS_EMPTY_ARRAY.put(Short.class, N.EMPTY_SHORT_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(int.class, N.EMPTY_INT_ARRAY);
CLASS_EMPTY_ARRAY.put(Integer.class, N.EMPTY_INTEGER_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(long.class, N.EMPTY_LONG_ARRAY);
CLASS_EMPTY_ARRAY.put(Long.class, N.EMPTY_LONG_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(float.class, N.EMPTY_FLOAT_ARRAY);
CLASS_EMPTY_ARRAY.put(Float.class, N.EMPTY_FLOAT_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(double.class, N.EMPTY_DOUBLE_ARRAY);
CLASS_EMPTY_ARRAY.put(Double.class, N.EMPTY_DOUBLE_OBJECT_ARRAY);
CLASS_EMPTY_ARRAY.put(String.class, N.EMPTY_STRING_ARRAY);
CLASS_EMPTY_ARRAY.put(Object.class, N.EMPTY_OBJECT_ARRAY);
}
// ...
static final Map, Integer> CLASS_TYPE_ENUM = new HashMap<>();
static {
CLASS_TYPE_ENUM.put(boolean.class, 1);
CLASS_TYPE_ENUM.put(char.class, 2);
CLASS_TYPE_ENUM.put(byte.class, 3);
CLASS_TYPE_ENUM.put(short.class, 4);
CLASS_TYPE_ENUM.put(int.class, 5);
CLASS_TYPE_ENUM.put(long.class, 6);
CLASS_TYPE_ENUM.put(float.class, 7);
CLASS_TYPE_ENUM.put(double.class, 8);
CLASS_TYPE_ENUM.put(String.class, 9);
CLASS_TYPE_ENUM.put(boolean[].class, 11);
CLASS_TYPE_ENUM.put(char[].class, 12);
CLASS_TYPE_ENUM.put(byte[].class, 13);
CLASS_TYPE_ENUM.put(short[].class, 14);
CLASS_TYPE_ENUM.put(int[].class, 15);
CLASS_TYPE_ENUM.put(long[].class, 16);
CLASS_TYPE_ENUM.put(float[].class, 17);
CLASS_TYPE_ENUM.put(double[].class, 18);
CLASS_TYPE_ENUM.put(String[].class, 19);
CLASS_TYPE_ENUM.put(Boolean.class, 21);
CLASS_TYPE_ENUM.put(Character.class, 22);
CLASS_TYPE_ENUM.put(Byte.class, 23);
CLASS_TYPE_ENUM.put(Short.class, 24);
CLASS_TYPE_ENUM.put(Integer.class, 25);
CLASS_TYPE_ENUM.put(Long.class, 26);
CLASS_TYPE_ENUM.put(Float.class, 27);
CLASS_TYPE_ENUM.put(Double.class, 28);
}
// ...
private static final Map>, List extends Enum>>> enumListPool = new ObjectPool<>(POOL_SIZE);
private static final Map>, Set extends Enum>>> enumSetPool = new ObjectPool<>(POOL_SIZE);
private static final Map>, BiMap extends Enum>, String>> enumMapPool = new ObjectPool<>(POOL_SIZE);
private static final Map> nameTypePool = new ObjectPool<>(POOL_SIZE);
private static final Map, Type>> clsTypePool = new ObjectPool<>(POOL_SIZE);
// ...
private static final Map, Boolean> entityClassPool = new ObjectPool<>(POOL_SIZE);
private static final Map, Boolean> dirtyMarkerClassPool = new ObjectPool<>(POOL_SIZE);
private static final Map, Boolean> dirtyMarkerEntityClassPool = new ObjectPool<>(POOL_SIZE);
private static final JSONParser jsonParser = ParserFactory.createJSONParser();
private static final XMLParser abacusXMLParser = ParserFactory.isAbacusXMLAvailable() ? ParserFactory.createAbacusXMLParser() : null;
private static final XMLParser xmlParser = ParserFactory.isXMLAvailable() ? ParserFactory.createXMLParser() : null;
private static final KryoParser kryoParser = ParserFactory.isKryoAvailable() ? ParserFactory.createKryoParser() : null;
private static final JSONSerializationConfig jsc = JSC.of(true, true);
private static final XMLSerializationConfig xscForClone = XSC.create().setIgnoreTypeInfo(false);
// ...
static final Field strValueField;
static volatile boolean isStringCharsGettable = true;
static final Constructor sharedStringConstructor;
static final Field listElementDataField;
static final Field listSizeField;
static volatile boolean isListElementDataFieldGettable = true;
static volatile boolean isListElementDataFieldSettable = true;
static {
Field tmp = null;
try {
tmp = String.class.getDeclaredField("offset");
} catch (Exception e) {
// ignore.
}
if (tmp == null) {
try {
tmp = String.class.getDeclaredField("count");
} catch (Exception e) {
// ignore.
}
}
if (tmp == null) {
try {
tmp = String.class.getDeclaredField("value");
} catch (Exception e) {
// ignore.
}
}
strValueField = ((tmp != null) && tmp.getName().equals("value") && tmp.getType().equals(char[].class)) ? tmp : null;
if (strValueField != null) {
strValueField.setAccessible(true);
}
Constructor tmpConstructor = null;
try {
tmpConstructor = String.class.getDeclaredConstructor(char[].class, boolean.class);
tmpConstructor.setAccessible(true);
} catch (Exception e) {
// ignore.
}
sharedStringConstructor = tmpConstructor;
tmp = null;
try {
tmp = ArrayList.class.getDeclaredField("elementData");
} catch (Exception e) {
// ignore.
}
listElementDataField = tmp != null && tmp.getType().equals(Object[].class) ? tmp : null;
if (listElementDataField != null) {
listElementDataField.setAccessible(true);
}
tmp = null;
try {
tmp = ArrayList.class.getDeclaredField("size");
} catch (Exception e) {
// ignore.
}
listSizeField = tmp != null && tmp.getType().equals(int.class) ? tmp : null;
if (listSizeField != null) {
listSizeField.setAccessible(true);
}
}
/**
* A regex pattern for recognizing blocks of whitespace characters. The
* apparent convolutedness of the pattern serves the purpose of ignoring
* "blocks" consisting of only a single space: the pattern is used only to
* normalize whitespace, condensing "blocks" down to a single space, thus
* matching the same would likely cause a great many noop replacements.
*/
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("(?: |\\u00A0|\\s|[\\s&&[^ ]])\\s*");
static final String[] charStringCache = new String[128];
static final int intStringCacheLow = -1001;
static final int intStringCacheHigh = 10001;
static final String[] intStringCache = new String[intStringCacheHigh - intStringCacheLow];
static final Map stringIntCache = new HashMap<>((int) (intStringCache.length * 1.5));
static {
for (int i = 0, j = intStringCacheLow, len = intStringCache.length; i < len; i++, j++) {
intStringCache[i] = Integer.valueOf(j).toString();
stringIntCache.put(intStringCache[i], j);
}
for (int i = 0; i < charStringCache.length; i++) {
charStringCache[i] = String.valueOf((char) i);
}
}
static final Type booleanType = N.typeOf(boolean.class);
static final Type charType = N.typeOf(char.class);
static final Type byteType = N.typeOf(byte.class);
static final Type shortType = N.typeOf(short.class);
static final Type intType = N.typeOf(int.class);
static final Type longType = N.typeOf(long.class);
static final Type floatType = N.typeOf(float.class);
static final Type doubleType = N.typeOf(double.class);
/**
* Constructor for
*/
private N() {
// no instance();
}
@SuppressWarnings("unchecked")
public static Type typeOf(final String typeName) {
if (typeName == null) {
return null;
}
Type> type = nameTypePool.get(typeName);
if (type == null) {
type = TypeFactory.getType(typeName);
nameTypePool.put(typeName, type);
}
return (Type) type;
}
@SuppressWarnings("unchecked")
public static Type typeOf(final Class> cls) {
if (cls == null) {
return null;
}
Type> type = clsTypePool.get(cls);
if (type == null) {
type = TypeFactory.getType(cls);
clsTypePool.put(cls, type);
}
return (Type) type;
}
@SuppressWarnings("unchecked")
@SafeVarargs
public static List> typeOf(final Class>... classes) {
final List> result = new ArrayList<>(classes.length);
for (int i = 0, len = classes.length; i < len; i++) {
result.add((Type) typeOf(classes[i]));
}
return result;
}
@SuppressWarnings("unchecked")
public static List> typeOf(final Collection extends Class>> classes) {
final List> result = new ArrayList<>(classes.size());
for (Class> cls : classes) {
result.add((Type) typeOf(cls));
}
return result;
}
public static String stringOf(final boolean val) {
return String.valueOf(val);
}
public static String stringOf(final char val) {
if (val < 128) {
return charStringCache[val];
}
return String.valueOf(val);
}
public static String stringOf(final byte val) {
if (val > intStringCacheLow && val < intStringCacheHigh) {
return intStringCache[val - intStringCacheLow];
}
return String.valueOf(val);
}
public static String stringOf(final short val) {
if (val > intStringCacheLow && val < intStringCacheHigh) {
return intStringCache[val - intStringCacheLow];
}
return String.valueOf(val);
}
public static String stringOf(final int val) {
if (val > intStringCacheLow && val < intStringCacheHigh) {
return intStringCache[val - intStringCacheLow];
}
return String.valueOf(val);
}
public static String stringOf(final long val) {
if (val > intStringCacheLow && val < intStringCacheHigh) {
return intStringCache[(int) (val - intStringCacheLow)];
}
return String.valueOf(val);
}
public static String stringOf(final float val) {
return String.valueOf(val);
}
public static String stringOf(final double val) {
return String.valueOf(val);
}
/**
*
* @param obj
* @return null
if the specified object is null.
*/
public static String stringOf(final Object obj) {
return (obj == null) ? null : N.typeOf(obj.getClass()).stringOf(obj);
}
/**
*
* @param targetClass
* @param str
* @return the default value of the specified targetClass
if the specified string is null.
*/
@SuppressWarnings("unchecked")
public static T valueOf(final Class targetClass, final String str) {
return (str == null) ? defaultValueOf(targetClass) : (T) N.typeOf(targetClass).valueOf(str);
}
@SuppressWarnings("unchecked")
public static T defaultValueOf(final Class cls) {
return (T) N.typeOf(cls).defaultValue();
}
public static > List enumListOf(final Class enumClass) {
List enumList = (List) enumListPool.get(enumClass);
if (enumList == null) {
enumList = ImmutableList.of(N.asList(enumClass.getEnumConstants()));
enumListPool.put(enumClass, enumList);
}
return enumList;
}
public static > Set enumSetOf(final Class enumClass) {
Set enumSet = (Set) enumSetPool.get(enumClass);
if (enumSet == null) {
enumSet = ImmutableSet.of(EnumSet.allOf(enumClass));
enumSetPool.put(enumClass, enumSet);
}
return enumSet;
}
public static > BiMap enumMapOf(final Class enumClass) {
BiMap enumMap = (BiMap) enumMapPool.get(enumClass);
if (enumMap == null) {
final EnumMap keyMap = new EnumMap<>(enumClass);
final Map valueMap = new HashMap<>();
for (final E e : enumClass.getEnumConstants()) {
keyMap.put(e, e.name());
valueMap.put(e.name(), e);
}
enumMap = new BiMap<>(ImmutableMap.of(keyMap), ImmutableMap.of(valueMap));
enumMapPool.put(enumClass, enumMap);
}
return enumMap;
}
/**
* Method newInstance.
*
* @param cls
* @return T
*/
public static T newInstance(final Class cls) {
if (Modifier.isAbstract(cls.getModifiers())) {
if (cls.equals(Map.class)) {
return (T) new HashMap<>();
} else if (cls.equals(List.class)) {
return (T) new ArrayList<>();
} else if (cls.equals(Set.class)) {
return (T) new HashSet<>();
} else if (cls.equals(Queue.class)) {
return (T) new ArrayDeque<>();
} else if (cls.equals(SortedSet.class)) {
return (T) new TreeSet<>();
} else if (cls.equals(SortedMap.class)) {
return (T) new TreeMap<>();
}
}
try {
if (Modifier.isStatic(cls.getModifiers()) == false && (cls.isAnonymousClass() || cls.isMemberClass())) {
// http://stackoverflow.com/questions/2097982/is-it-possible-to-create-an-instance-of-nested-class-using-java-reflection
final List> toInstantiate = new ArrayList<>();
Class> parent = cls.getEnclosingClass();
do {
toInstantiate.add(parent);
parent = parent.getEnclosingClass();
} while (parent != null && Modifier.isStatic(parent.getModifiers()) == false && (parent.isAnonymousClass() || parent.isMemberClass()));
if (parent != null) {
toInstantiate.add(parent);
}
N.reverse(toInstantiate);
Object instance = null;
for (Class> current : toInstantiate) {
instance = instance == null ? invoke(RefUtil.getDeclaredConstructor(current))
: invoke(RefUtil.getDeclaredConstructor(current, instance.getClass()), instance);
}
return invoke(RefUtil.getDeclaredConstructor(cls, instance.getClass()), instance);
} else {
return invoke(RefUtil.getDeclaredConstructor(cls));
}
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw N.toRuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private static T invoke(final Constructor c, final Object... args)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (c.isAccessible() == false) {
c.setAccessible(true);
}
return c.newInstance(args);
}
public static T newProxyInstance(final Class interfaceClass, final InvocationHandler h) {
return newProxyInstance(N.asArray(interfaceClass), h);
}
/**
* Refer to {@code java.lang.reflect}
*
* @param interfaceClasses
* @param h
* @return
*/
public static T newProxyInstance(final Class>[] interfaceClasses, final InvocationHandler h) {
return (T) Proxy.newProxyInstance(N.class.getClassLoader(), interfaceClasses, h);
}
/**
* Method newArray.
*
* @param componentType
* @param length
* @return T[]
*/
@SuppressWarnings("unchecked")
public static T newArray(final Class> componentType, final int length) {
// if (length == 0) {
// final Object result = CLASS_EMPTY_ARRAY.get(componentType);
//
// if (result != null) {
// return (T) result;
// }
// }
return (T) Array.newInstance(componentType, length);
}
@SuppressWarnings("unchecked")
public static T newEntity(final Class cls) {
return newEntity(cls, null);
}
public static T newEntity(final Class cls, final String entityName) {
if (MapEntity.class.isAssignableFrom(cls)) {
return (T) asMapEntity(entityName);
}
final Class> enclosingClass = RefUtil.getEnclosingClass(cls);
if (enclosingClass == null || Modifier.isStatic(cls.getModifiers())) {
return newInstance(cls);
} else {
return RefUtil.invokeConstructor(RefUtil.getDeclaredConstructor(cls, enclosingClass), newInstance(enclosingClass));
}
}
/**
*
* @param a
* the specified array should not be modified after it's used to
* create the new String.
* @param share
* the same array will be shared with the new created ArrayList
* if it's true.
* @return
*/
@Internal
static String newString(final char[] a, final boolean share) {
if (share && sharedStringConstructor != null) {
try {
return sharedStringConstructor.newInstance(a, true);
} catch (Exception e) {
throw new AbacusException(e);
}
} else {
return String.valueOf(a);
}
}
/**
* Returns a set backed by the specified map.
*
* @param map the backing map
* @return the set backed by the map
* @see Collections#newSetFromMap(Map)
*/
public static Set newSetFromMap(final Map map) {
return Collections.newSetFromMap(map);
}
public static int initHashCapacity(final int size) {
return size < MAX_HASH_LENGTH ? (int) (size * 1.25) + 1 : MAX_ARRAY_SIZE;
}
public static ArrayList newArrayList() {
return new ArrayList<>();
}
public static ArrayList newArrayList(int initialCapacity) {
return new ArrayList<>(initialCapacity);
}
public static ArrayList newArrayList(Collection extends T> c) {
return new ArrayList<>(c);
}
public static LinkedList newLinkedList() {
return new LinkedList<>();
}
public static LinkedList newLinkedList(Collection extends T> c) {
return new LinkedList<>(c);
}
public static HashSet newHashSet() {
return new HashSet<>();
}
/**
*
* @param initialCapacity multiply 1.25 as the initial capacity of new HashSet
* @return
*/
public static HashSet newHashSet(int initialCapacity) {
return new HashSet<>(initHashCapacity(initialCapacity));
}
public static HashSet newHashSet(Collection extends T> c) {
return new HashSet<>(c);
}
public static LinkedHashSet newLinkedHashSet() {
return new LinkedHashSet<>();
}
/**
*
* @param initialCapacity multiply 1.25 as the initial capacity of new HashSet
* @return
*/
public static LinkedHashSet newLinkedHashSet(int initialCapacity) {
return new LinkedHashSet<>(initHashCapacity(initialCapacity));
}
public static LinkedHashSet newLinkedHashSet(Collection extends T> c) {
return new LinkedHashSet<>(c);
}
public static HashMap newHashMap() {
return new HashMap<>();
}
/**
*
* @param initialCapacity multiply 1.25 as the initial capacity of new HashSet
* @return
*/
public static HashMap newHashMap(int initialCapacity) {
return new HashMap<>(initHashCapacity(initialCapacity));
}
public static HashMap newHashMap(Map extends K, ? extends V> m) {
return new HashMap<>(m);
}
public static HashMap newHashMap(final Collection extends V> c, final Function super V, ? extends K> keyExtractor) {
N.requireNonNull(keyExtractor);
if (isNullOrEmpty(c)) {
return new HashMap<>();
}
final HashMap result = new HashMap<>(N.initHashCapacity(c.size()));
for (V v : c) {
result.put(keyExtractor.apply(v), v);
}
return result;
}
public static LinkedHashMap newLinkedHashMap() {
return new LinkedHashMap<>();
}
/**
*
* @param initialCapacity multiply 1.25 as the initial capacity of new HashSet
* @return
*/
public static LinkedHashMap newLinkedHashMap(int initialCapacity) {
return new LinkedHashMap<>(initHashCapacity(initialCapacity));
}
public static LinkedHashMap newLinkedHashMap(Map extends K, ? extends V> m) {
return new LinkedHashMap<>(m);
}
public static LinkedHashMap newLinkedHashMap(final Collection extends V> c, final Function super V, ? extends K> keyExtractor) {
N.requireNonNull(keyExtractor);
if (isNullOrEmpty(c)) {
return new LinkedHashMap<>();
}
final LinkedHashMap result = new LinkedHashMap<>(N.initHashCapacity(c.size()));
for (V v : c) {
result.put(keyExtractor.apply(v), v);
}
return result;
}
public static ConcurrentHashMap newConcurrentHashMap() {
return new ConcurrentHashMap<>();
}
/**
*
* @param initCapacity multiply 1.25 as the initial capacity of new HashSet
* @return
*/
public static ConcurrentHashMap newConcurrentHashMap(int initialCapacity) {
return new ConcurrentHashMap<>(initHashCapacity(initialCapacity));
}
public static ConcurrentHashMap newConcurrentHashMap(Map extends K, ? extends V> m) {
return new ConcurrentHashMap<>(m);
}
public static Multimap> newListMultimap() {
return new Multimap<>(new HashMap>(), ArrayList.class);
}
public static Multimap> newListMultimap(final int initialCapacity) {
return new Multimap<>(new HashMap>(initialCapacity < 0 ? 9 : initialCapacity), ArrayList.class);
}
public static Multimap> newListMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new HashMap>(), ArrayList.class);
multiMap.putAll(m);
return multiMap;
}
public static Multimap> newListLinkedMultimap() {
return new Multimap<>(new LinkedHashMap>(), ArrayList.class);
}
public static Multimap> newListLinkedMultimap(final int initialCapacity) {
return new Multimap<>(new LinkedHashMap>(initialCapacity < 0 ? 9 : initialCapacity), ArrayList.class);
}
public static Multimap> newListLinkedMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new LinkedHashMap>(), ArrayList.class);
multiMap.putAll(m);
return multiMap;
}
public static Multimap> newListSortedMultimap() {
return new Multimap<>(new TreeMap>(), ArrayList.class);
}
public static Multimap> newListSortedMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new TreeMap>(), ArrayList.class);
multiMap.putAll(m);
return multiMap;
}
public static Multimap> newSetMultimap() {
return new Multimap<>(new HashMap>(), HashSet.class);
}
public static Multimap> newSetMultimap(final int initialCapacity) {
return new Multimap<>(new HashMap>(initialCapacity < 0 ? 9 : initialCapacity), HashSet.class);
}
public static Multimap> newSetMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new HashMap>(), HashSet.class);
multiMap.putAll(m);
return multiMap;
}
public static Multimap> newSetLinkedMultimap() {
return new Multimap<>(new LinkedHashMap>(), HashSet.class);
}
public static Multimap> newSetLinkedMultimap(final int initialCapacity) {
return new Multimap<>(new LinkedHashMap>(initialCapacity < 0 ? 9 : initialCapacity), HashSet.class);
}
public static Multimap> newSetLinkedMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new LinkedHashMap>(), HashSet.class);
multiMap.putAll(m);
return multiMap;
}
public static Multimap> newSetSortedMultimap() {
return new Multimap<>(new TreeMap>(), HashSet.class);
}
public static Multimap> newSetSortedMultimap(final Map extends K, ? extends E> m) {
final Multimap> multiMap = new Multimap<>(new TreeMap>(), HashSet.class);
multiMap.putAll(m);
return multiMap;
}
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
static final int MAX_HASH_LENGTH = (int) (MAX_ARRAY_SIZE / 1.25) - 1;
public static DataSet newDataSet(final String keyColumnName, final String valueColumnName, final Map, ?> m) {
return newDataSet(null, null, keyColumnName, valueColumnName, m);
}
/**
* Convert the specified Map to a two columns DataSet
: one column is for keys and one column is for values
*
* @param entityName
* @param entityClass
* @param keyColumnName
* @param valueColumnName
* @param m
* @return
*/
public static DataSet newDataSet(final String entityName, final Class> entityClass, final String keyColumnName, final String valueColumnName,
final Map, ?> m) {
final List