diff --git a/modules/org.jkiss.utils/build.properties b/modules/org.jkiss.utils/build.properties index 3335c5d9..cd6259cb 100644 --- a/modules/org.jkiss.utils/build.properties +++ b/modules/org.jkiss.utils/build.properties @@ -1,3 +1,3 @@ -source.. = src/ +source.. = src/main/java output.. = target/classes/ bin.includes = META-INF/,. diff --git a/modules/org.jkiss.utils/pom.xml b/modules/org.jkiss.utils/pom.xml index 6a15dbc8..b7db76b6 100644 --- a/modules/org.jkiss.utils/pom.xml +++ b/modules/org.jkiss.utils/pom.xml @@ -21,6 +21,40 @@ com.google.code.gson gson + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.platform + junit-platform-engine + test + + + org.junit.platform + junit-platform-commons + test + + + + org.mockito + mockito-core + test + @@ -48,7 +82,24 @@ - ${project.basedir}/src/ + ${project.basedir}/src/main/java + ${project.basedir}/src/test/java + + + + org.apache.maven.plugins + maven-surefire-plugin + + + test + test + + test + + + + + diff --git a/modules/org.jkiss.utils/src/org/jkiss/api/CompositeObjectId.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/CompositeObjectId.java similarity index 97% rename from modules/org.jkiss.utils/src/org/jkiss/api/CompositeObjectId.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/api/CompositeObjectId.java index 70cb3244..4e7bcc2b 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/api/CompositeObjectId.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/CompositeObjectId.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/api/FileSystemPathProvider.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/FileSystemPathProvider.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/api/FileSystemPathProvider.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/api/FileSystemPathProvider.java index 12dc4edd..2701ecf2 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/api/FileSystemPathProvider.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/FileSystemPathProvider.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/api/ObjectWithContextParameters.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/ObjectWithContextParameters.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/api/ObjectWithContextParameters.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/api/ObjectWithContextParameters.java index 3acd2e07..353fd036 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/api/ObjectWithContextParameters.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/ObjectWithContextParameters.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/api/verification/FileSystemAccessVerifyer.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/FileSystemAccessVerifyer.java similarity index 94% rename from modules/org.jkiss.utils/src/org/jkiss/api/verification/FileSystemAccessVerifyer.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/FileSystemAccessVerifyer.java index ced64f41..3ada9b88 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/api/verification/FileSystemAccessVerifyer.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/FileSystemAccessVerifyer.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/api/verification/ObjectWithVerification.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/ObjectWithVerification.java similarity index 93% rename from modules/org.jkiss.utils/src/org/jkiss/api/verification/ObjectWithVerification.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/ObjectWithVerification.java index 2d37c587..aaa331e4 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/api/verification/ObjectWithVerification.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/api/verification/ObjectWithVerification.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/code/DynamicCall.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/code/DynamicCall.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/code/DynamicCall.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/code/DynamicCall.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/code/NotNull.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/code/NotNull.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/code/NotNull.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/code/NotNull.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/code/NotNullWhen.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/code/NotNullWhen.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/code/NotNullWhen.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/code/NotNullWhen.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/code/Nullable.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/code/Nullable.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/code/Nullable.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/code/Nullable.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/AlphanumericComparator.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/AlphanumericComparator.java index c0b7b234..e828d03a 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/AlphanumericComparator.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ public int compare(CharSequence o1, CharSequence o2) { return compare(o1, o2, false); } - public int compareIgnoreCase(@NotNull CharSequence o1,@NotNull CharSequence o2) { + public int compareIgnoreCase(@NotNull CharSequence o1, @NotNull CharSequence o2) { return compare(o1, o2, true); } @@ -80,7 +80,7 @@ private static int compare(@NotNull CharBuffer b1, @NotNull CharBuffer b2, boole return ignoreCase ? compareLettersIgnoreCase(b1, b2) : b1.compareTo(b2); } - private static int compareLettersIgnoreCase(@NotNull CharBuffer b1,@NotNull CharBuffer b2) { + private static int compareLettersIgnoreCase(@NotNull CharBuffer b1, @NotNull CharBuffer b2) { int len = Math.min(b1.remaining(), b2.remaining()); for (int i = 0; i < len; i++) { char c1 = Character.toUpperCase(b1.get(b1.position() + i)); diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArgumentTokenizer.java similarity index 72% rename from modules/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArgumentTokenizer.java index 46e12bd0..d0582092 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArgumentTokenizer.java @@ -1,35 +1,18 @@ /* - * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others * - * This software is Open Source Initiative approved Open Source Software. - * Open Source Initative Approved is a trademark of the Open Source Initiative. - * - * This file is part of DrJava. Download the current version of this project - * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/ + * 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.jkiss.utils; @@ -117,27 +100,27 @@ public static List tokenize(String arguments, boolean stringify) { currArg.append(c); } break; -// case NORMAL_TOKEN_STATE: -// if (Character.isWhitespace(c)) { -// // Whitespace ends the token; start a new one -// argList.add(currArg.toString()); -// currArg = new StringBuffer(); -// state = NO_TOKEN_STATE; -// } -// else if (c == '\\') { -// // Backslash in a normal token: escape the next character -// escaped = true; -// } -// else if (c == '\'') { -// state = SINGLE_QUOTE_STATE; -// } -// else if (c == '"') { -// state = DOUBLE_QUOTE_STATE; -// } -// else { -// currArg.append(c); -// } -// break; + // case NORMAL_TOKEN_STATE: + // if (Character.isWhitespace(c)) { + // // Whitespace ends the token; start a new one + // argList.add(currArg.toString()); + // currArg = new StringBuffer(); + // state = NO_TOKEN_STATE; + // } + // else if (c == '\\') { + // // Backslash in a normal token: escape the next character + // escaped = true; + // } + // else if (c == '\'') { + // state = SINGLE_QUOTE_STATE; + // } + // else if (c == '"') { + // state = DOUBLE_QUOTE_STATE; + // } + // else { + // currArg.append(c); + // } + // break; case NO_TOKEN_STATE: case NORMAL_TOKEN_STATE: switch (c) { diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArrayUtils.java similarity index 85% rename from modules/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArrayUtils.java index d2636eba..4fbbe6e9 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ArrayUtils.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,13 +33,11 @@ public class ArrayUtils { - public static boolean isEmpty(@Nullable Object[] arr) - { + public static boolean isEmpty(@Nullable Object[] arr) { return arr == null || arr.length == 0; } - public static boolean isEmpty(@Nullable short[] array) - { + public static boolean isEmpty(@Nullable short[] array) { return array == null || array.length == 0; } @@ -47,88 +45,92 @@ public static boolean isArray(@Nullable Object value) { return value != null && value.getClass().isArray(); } - public static boolean contains(@Nullable short[] array, short value) - { - if (array == null) + public static boolean contains(@Nullable short[] array, short value) { + if (array == null) { return false; + } for (short item : array) { - if (item == value) + if (item == value) { return true; + } } return false; } - public static boolean contains(@Nullable char[] array, char value) - { - if (array == null || array.length == 0) + public static boolean contains(@Nullable char[] array, char value) { + if (array == null || array.length == 0) { return false; + } for (char c : array) { - if (c == value) + if (c == value) { return true; + } } return false; } - public static boolean isEmpty(@Nullable int[] array) - { + public static boolean isEmpty(@Nullable int[] array) { return array == null || array.length == 0; } - public static boolean contains(@Nullable int[] array, int value) - { - if (array == null) + public static boolean contains(@Nullable int[] array, int value) { + if (array == null) { return false; + } for (int v : array) { - if (v == value) + if (v == value) { return true; + } } return false; } - public static boolean isEmpty(@Nullable long[] array) - { + public static boolean isEmpty(@Nullable long[] array) { return array == null || array.length == 0; } - public static boolean contains(@Nullable long[] array, long value) - { - if (array == null) + public static boolean contains(@Nullable long[] array, long value) { + if (array == null) { return false; + } for (long v : array) { - if (v == value) + if (v == value) { return true; + } } return false; } - public static boolean contains(OBJECT_TYPE[] array, OBJECT_TYPE value) - { - if (isEmpty(array)) + public static boolean contains(OBJECT_TYPE[] array, OBJECT_TYPE value) { + if (isEmpty(array)) { return false; + } for (OBJECT_TYPE object_type : array) { - if (CommonUtils.equalObjects(value, object_type)) + if (CommonUtils.equalObjects(value, object_type)) { return true; + } } return false; } - public static boolean containsIgnoreCase(String[] array, String value) - { - if (isEmpty(array) || value == null) + public static boolean containsIgnoreCase(String[] array, String value) { + if (isEmpty(array) || value == null) { return false; + } for (String s : array) { - if (value.equalsIgnoreCase(s)) + if (value.equalsIgnoreCase(s)) { return true; + } } return false; } - public static boolean containsRef(@NotNull OBJECT_TYPE[] array, @Nullable OBJECT_TYPE value) - { + public static boolean containsRef(@NotNull OBJECT_TYPE[] array, @Nullable OBJECT_TYPE value) { final int length = array.length; for (OBJECT_TYPE object_type : array) { - if (value == object_type) + if (value == object_type) { return true; + } } return false; } @@ -137,8 +139,9 @@ public static boolean containsRef(@NotNull OBJECT_TYPE[] array, @N public static boolean containsAny(OBJECT_TYPE[] array, OBJECT_TYPE... values) { for (OBJECT_TYPE item : array) { for (OBJECT_TYPE value : values) { - if (CommonUtils.equalObjects(item, value)) + if (CommonUtils.equalObjects(item, value)) { return true; + } } } return false; @@ -150,23 +153,22 @@ public static boolean containsAll(OBJECT_TYPE[] array, OBJECT_TYPE return false; } for (OBJECT_TYPE value : values) { - if (!ArrayUtils.contains(array, value)) + if (!ArrayUtils.contains(array, value)) { return false; + } } return true; } @NotNull - public static T[] concatArrays(@NotNull T[] first, @NotNull T[] second) - { + public static T[] concatArrays(@NotNull T[] first, @NotNull T[] second) { T[] result = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, result, first.length, second.length); return result; } @NotNull - public static List safeArray(@Nullable T[] array) - { + public static List safeArray(@Nullable T[] array) { if (array == null) { return Collections.emptyList(); } else { @@ -175,7 +177,7 @@ public static List safeArray(@Nullable T[] array) } /** - * Returns index of the first found element satisfying a given predicate in the provided array + * Returns index of the first found element satisfying a given predicate in the provided array */ public static int indexOf(@NotNull T[] array, @NotNull Predicate condition) { for (int i = 0; i < array.length; i++) { diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/Base64.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Base64.java similarity index 56% rename from modules/org.jkiss.utils/src/org/jkiss/utils/Base64.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Base64.java index d936daa7..f5df5bb8 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/Base64.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Base64.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,12 @@ public final class Base64 { private static final char[] S_BASE64CHAR = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; @@ -39,34 +39,41 @@ public final class Base64 { private static final byte[] S_DECODETABLE = new byte[128]; static { - for (int i = 0; i < S_DECODETABLE.length; i ++) + for (int i = 0; i < S_DECODETABLE.length; i++) { S_DECODETABLE[i] = Byte.MAX_VALUE; // 127 - for (int i = 0; i < S_BASE64CHAR.length; i ++) // 0 to 63 - S_DECODETABLE[S_BASE64CHAR[i]] = (byte)i; + } + for (int i = 0; i < S_BASE64CHAR.length; i++) // 0 to 63 + { + S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i; + } } private static int decode0(char[] ibuf, byte[] obuf, int wp) { int outlen = 3; - if (ibuf[3] == S_BASE64PAD) outlen = 2; - if (ibuf[2] == S_BASE64PAD) outlen = 1; + if (ibuf[3] == S_BASE64PAD) { + outlen = 2; + } + if (ibuf[2] == S_BASE64PAD) { + outlen = 1; + } int b0 = S_DECODETABLE[ibuf[0]]; int b1 = S_DECODETABLE[ibuf[1]]; int b2 = S_DECODETABLE[ibuf[2]]; int b3 = S_DECODETABLE[ibuf[3]]; switch (outlen) { - case 1: - obuf[wp] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - return 1; - case 2: - obuf[wp++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - obuf[wp] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - return 2; - case 3: - default: - obuf[wp++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - obuf[wp++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - obuf[wp] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f); - return 3; + case 1: + obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + return 1; + case 2: + obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); + return 2; + case 3: + default: + obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); + obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f); + return 3; } } @@ -76,9 +83,9 @@ private static int decode0(char[] ibuf, byte[] obuf, int wp) { public static byte[] decode(char[] data, int off, int len) { char[] ibuf = new char[4]; int ibufcount = 0; - byte[] obuf = new byte[len/4*3+3]; + byte[] obuf = new byte[len / 4 * 3 + 3]; int obufcount = 0; - for (int i = off; i < off+len; i ++) { + for (int i = off; i < off + len; i++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { @@ -89,8 +96,9 @@ public static byte[] decode(char[] data, int off, int len) { } } } - if (obufcount == obuf.length) + if (obufcount == obuf.length) { return obuf; + } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; @@ -102,9 +110,9 @@ public static byte[] decode(char[] data, int off, int len) { public static byte[] decode(String data) { char[] ibuf = new char[4]; int ibufcount = 0; - byte[] obuf = new byte[data.length()/4*3+3]; + byte[] obuf = new byte[data.length() / 4 * 3 + 3]; int obufcount = 0; - for (int i = 0; i < data.length(); i ++) { + for (int i = 0; i < data.length(); i++) { char ch = data.charAt(i); if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { @@ -115,8 +123,9 @@ public static byte[] decode(String data) { } } } - if (obufcount == obuf.length) + if (obufcount == obuf.length) { return obuf; + } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; @@ -129,7 +138,7 @@ public static void decode(char[] data, int off, int len, OutputStream ostream) t char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[3]; - for (int i = off; i < off+len; i ++) { + for (int i = off; i < off + len; i++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { @@ -150,7 +159,7 @@ public static void decode(String data, OutputStream ostream) throws IOException char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[3]; - for (int i = 0; i < data.length(); i ++) { + for (int i = 0; i < data.length(); i++) { char ch = data.charAt(i); if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { @@ -178,35 +187,36 @@ public static String splitLines(String bigString, int lineLength) { /** * Returns base64 representation of specified byte array. */ - public static String encode(byte[] data, int off, int len) - { - if (len <= 0) return ""; - char[] out = new char[len/3*4+4]; + public static String encode(byte[] data, int off, int len) { + if (len <= 0) { + return ""; + } + char[] out = new char[len / 3 * 4 + 4]; int rindex = off; int windex = 0; - int rest = len-off; + int rest = len - off; while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[windex++] = S_BASE64CHAR[i>>18]; - out[windex++] = S_BASE64CHAR[(i>>12)&0x3f]; - out[windex++] = S_BASE64CHAR[(i>>6)&0x3f]; - out[windex++] = S_BASE64CHAR[i&0x3f]; + int i = ((data[rindex] & 0xff) << 16) + + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[windex++] = S_BASE64CHAR[i >> 18]; + out[windex++] = S_BASE64CHAR[(i >> 12) & 0x3f]; + out[windex++] = S_BASE64CHAR[(i >> 6) & 0x3f]; + out[windex++] = S_BASE64CHAR[i & 0x3f]; rindex += 3; rest -= 3; } if (rest == 1) { - int i = data[rindex]&0xff; - out[windex++] = S_BASE64CHAR[i>>2]; - out[windex++] = S_BASE64CHAR[(i<<4)&0x3f]; + int i = data[rindex] & 0xff; + out[windex++] = S_BASE64CHAR[i >> 2]; + out[windex++] = S_BASE64CHAR[(i << 4) & 0x3f]; out[windex++] = S_BASE64PAD; out[windex++] = S_BASE64PAD; } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[windex++] = S_BASE64CHAR[i>>10]; - out[windex++] = S_BASE64CHAR[(i>>4)&0x3f]; - out[windex++] = S_BASE64CHAR[(i<<2)&0x3f]; + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[windex++] = S_BASE64CHAR[i >> 10]; + out[windex++] = S_BASE64CHAR[(i >> 4) & 0x3f]; + out[windex++] = S_BASE64CHAR[(i << 2) & 0x3f]; out[windex++] = S_BASE64PAD; } return new String(out, 0, windex); @@ -216,35 +226,37 @@ public static String encode(byte[] data, int off, int len) * Outputs base64 representation of the specified byte array to a byte stream. */ public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException { - if (len <= 0) return; + if (len <= 0) { + return; + } byte[] out = new byte[4]; int rindex = off; - int rest = len-off; + int rest = len - off; while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[0] = (byte)S_BASE64CHAR[i>>18]; - out[1] = (byte)S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = (byte)S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = (byte)S_BASE64CHAR[i&0x3f]; + int i = ((data[rindex] & 0xff) << 16) + + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[0] = (byte) S_BASE64CHAR[i >> 18]; + out[1] = (byte) S_BASE64CHAR[(i >> 12) & 0x3f]; + out[2] = (byte) S_BASE64CHAR[(i >> 6) & 0x3f]; + out[3] = (byte) S_BASE64CHAR[i & 0x3f]; ostream.write(out, 0, 4); rindex += 3; rest -= 3; } if (rest == 1) { - int i = data[rindex]&0xff; - out[0] = (byte)S_BASE64CHAR[i>>2]; - out[1] = (byte)S_BASE64CHAR[(i<<4)&0x3f]; - out[2] = (byte)S_BASE64PAD; - out[3] = (byte)S_BASE64PAD; + int i = data[rindex] & 0xff; + out[0] = (byte) S_BASE64CHAR[i >> 2]; + out[1] = (byte) S_BASE64CHAR[(i << 4) & 0x3f]; + out[2] = (byte) S_BASE64PAD; + out[3] = (byte) S_BASE64PAD; ostream.write(out, 0, 4); } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[0] = (byte)S_BASE64CHAR[i>>10]; - out[1] = (byte)S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = (byte)S_BASE64CHAR[(i<<2)&0x3f]; - out[3] = (byte)S_BASE64PAD; + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[0] = (byte) S_BASE64CHAR[i >> 10]; + out[1] = (byte) S_BASE64CHAR[(i >> 4) & 0x3f]; + out[2] = (byte) S_BASE64CHAR[(i << 2) & 0x3f]; + out[3] = (byte) S_BASE64PAD; ostream.write(out, 0, 4); } } @@ -253,18 +265,20 @@ public static void encode(byte[] data, int off, int len, OutputStream ostream) t * Outputs base64 representation of the specified byte array to a character stream. */ public static void encode(byte[] data, int off, int len, Writer writer) throws IOException { - if (len <= 0) return; + if (len <= 0) { + return; + } char[] out = new char[4]; int rindex = off; - int rest = len-off; + int rest = len - off; while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[0] = S_BASE64CHAR[i>>18]; - out[1] = S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = S_BASE64CHAR[i&0x3f]; + int i = ((data[rindex] & 0xff) << 16) + + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[0] = S_BASE64CHAR[i >> 18]; + out[1] = S_BASE64CHAR[(i >> 12) & 0x3f]; + out[2] = S_BASE64CHAR[(i >> 6) & 0x3f]; + out[3] = S_BASE64CHAR[i & 0x3f]; writer.write(out, 0, 4); rindex += 3; rest -= 3; @@ -274,17 +288,17 @@ public static void encode(byte[] data, int off, int len, Writer writer) throws I */ } if (rest == 1) { - int i = data[rindex]&0xff; - out[0] = S_BASE64CHAR[i>>2]; - out[1] = S_BASE64CHAR[(i<<4)&0x3f]; + int i = data[rindex] & 0xff; + out[0] = S_BASE64CHAR[i >> 2]; + out[1] = S_BASE64CHAR[(i << 4) & 0x3f]; out[2] = S_BASE64PAD; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[0] = S_BASE64CHAR[i>>10]; - out[1] = S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = S_BASE64CHAR[(i<<2)&0x3f]; + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[0] = S_BASE64CHAR[i >> 10]; + out[1] = S_BASE64CHAR[(i >> 4) & 0x3f]; + out[2] = S_BASE64CHAR[(i << 2) & 0x3f]; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } @@ -293,35 +307,36 @@ public static void encode(byte[] data, int off, int len, Writer writer) throws I /** * Outputs base64 representation of the specified input stream to a character stream. */ - public static void encode(InputStream stream, long len, Writer writer) - throws IOException - { - if (len <= 0) return; + public static void encode(InputStream stream, long len, Writer writer) + throws IOException { + if (len <= 0) { + return; + } char[] out = new char[4]; long rest = len; while (rest >= 3) { - int i = ((stream.read()&0xff)<<16) - +((stream.read()&0xff)<<8) - +(stream.read()&0xff); - out[0] = S_BASE64CHAR[i>>18]; - out[1] = S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = S_BASE64CHAR[i&0x3f]; + int i = ((stream.read() & 0xff) << 16) + + ((stream.read() & 0xff) << 8) + + (stream.read() & 0xff); + out[0] = S_BASE64CHAR[i >> 18]; + out[1] = S_BASE64CHAR[(i >> 12) & 0x3f]; + out[2] = S_BASE64CHAR[(i >> 6) & 0x3f]; + out[3] = S_BASE64CHAR[i & 0x3f]; writer.write(out, 0, 4); rest -= 3; } if (rest == 1) { - int i = stream.read()&0xff; - out[0] = S_BASE64CHAR[i>>2]; - out[1] = S_BASE64CHAR[(i<<4)&0x3f]; + int i = stream.read() & 0xff; + out[0] = S_BASE64CHAR[i >> 2]; + out[1] = S_BASE64CHAR[(i << 4) & 0x3f]; out[2] = S_BASE64PAD; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } else if (rest == 2) { - int i = ((stream.read()&0xff)<<8)+(stream.read()&0xff); - out[0] = S_BASE64CHAR[i>>10]; - out[1] = S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = S_BASE64CHAR[(i<<2)&0x3f]; + int i = ((stream.read() & 0xff) << 8) + (stream.read() & 0xff); + out[0] = S_BASE64CHAR[i >> 10]; + out[1] = S_BASE64CHAR[(i >> 4) & 0x3f]; + out[2] = S_BASE64CHAR[(i << 2) & 0x3f]; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/BeanUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/BeanUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/BeanUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/BeanUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ByteNumberFormat.java similarity index 82% rename from modules/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ByteNumberFormat.java index f858287a..66dce55c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ByteNumberFormat.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ public static int computeIndex(double bytes) { int index = 0; for (int i = 0; i < UNITS.length; i++) { - int result = (int)(bytes / 1024); + int result = (int) (bytes / 1024); if (result == 0) { break; } else { @@ -68,8 +68,7 @@ public static int computeIndex(double bytes) { /** * Returns a string representing the bytes. * - * @param bytes the number of bytes. - * + * @param bytes the number of bytes. * @return A string. */ public String getBytes(double bytes) { @@ -90,8 +89,8 @@ public String getBytes(double bytes) { String str; - if ((long)intBytes >= 10) { - str = String.valueOf((long)intBytes); + if ((long) intBytes >= 10) { + str = String.valueOf((long) intBytes); } else { str = fpFormat.format(intBytes); } @@ -105,30 +104,32 @@ public String getBytes(double bytes) { /** * Formats a number into the specified string buffer. * - * @param number the number to format. - * @param toAppendTo the string buffer. - * @param pos the field position (ignored here). - * + * @param number the number to format. + * @param toAppendTo the string buffer. + * @param pos the field position (ignored here). * @return The string buffer. */ @Override - public StringBuffer format(double number, StringBuffer toAppendTo, - FieldPosition pos) { + public StringBuffer format( + double number, StringBuffer toAppendTo, + FieldPosition pos + ) { return toAppendTo.append(getBytes(number)); } /** * Formats a number into the specified string buffer. * - * @param number the number to format. - * @param toAppendTo the string buffer. - * @param pos the field position (ignored here). - * + * @param number the number to format. + * @param toAppendTo the string buffer. + * @param pos the field position (ignored here). * @return The string buffer. */ @Override - public StringBuffer format(long number, StringBuffer toAppendTo, - FieldPosition pos) { + public StringBuffer format( + long number, StringBuffer toAppendTo, + FieldPosition pos + ) { return toAppendTo.append(getBytes(number)); } @@ -136,9 +137,8 @@ public StringBuffer format(long number, StringBuffer toAppendTo, * This method returns null for all inputs. This class cannot * be used for parsing. * - * @param source the source string. - * @param parsePosition the parse position. - * + * @param source the source string. + * @param parsePosition the parse position. * @return null. */ @Override diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/CommonUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/CommonUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/CommonUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/CommonUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/GsonUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/GsonUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/GsonUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/GsonUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/HttpConstants.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/HttpConstants.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/HttpConstants.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/HttpConstants.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IOUtils.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IOUtils.java index d0433b54..7978e00b 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IOUtils.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,8 +112,9 @@ public static void flipBuffer(Buffer buffer) { public static void copyStream( java.io.InputStream inputStream, - java.io.OutputStream outputStream) - throws IOException { + java.io.OutputStream outputStream + ) + throws IOException { copyStream(inputStream, outputStream, DEFAULT_BUFFER_SIZE); } @@ -124,8 +125,9 @@ public static void copyStream( public static void copyStream( java.io.InputStream inputStream, java.io.OutputStream outputStream, - int bufferSize) - throws IOException { + int bufferSize + ) + throws IOException { try { byte[] writeBuffer = new byte[bufferSize]; for (int br = inputStream.read(writeBuffer); br != -1; br = inputStream.read(writeBuffer)) { @@ -145,8 +147,9 @@ public static void copyStreamPortion( java.io.InputStream inputStream, java.io.OutputStream outputStream, int portionSize, - int bufferSize) - throws IOException { + int bufferSize + ) + throws IOException { if (bufferSize > portionSize) { bufferSize = portionSize; } @@ -183,8 +186,9 @@ public static String toString(File file, String encoding) throws IOException { public static void copyText( java.io.Reader reader, java.io.Writer writer, - int bufferSize) - throws IOException { + int bufferSize + ) + throws IOException { char[] writeBuffer = new char[bufferSize]; for (int br = reader.read(writeBuffer); br != -1; br = reader.read(writeBuffer)) { writer.write(writeBuffer, 0, br); @@ -194,8 +198,9 @@ public static void copyText( public static void copyText( java.io.Reader reader, - java.io.Writer writer) - throws IOException { + java.io.Writer writer + ) + throws IOException { copyText(reader, writer, DEFAULT_BUFFER_SIZE); } @@ -221,8 +226,9 @@ public static void writeFileFromString(File file, String str) throws IOException public static int readStreamToBuffer( java.io.InputStream inputStream, - byte[] buffer) - throws IOException { + byte[] buffer + ) + throws IOException { int totalRead = 0; while (totalRead != buffer.length) { int br = inputStream.read(buffer, totalRead, buffer.length - totalRead); @@ -235,7 +241,7 @@ public static int readStreamToBuffer( } public static String readLine(java.io.InputStream input) - throws IOException { + throws IOException { StringBuilder linebuf = new StringBuilder(); for (int b = input.read(); b != '\n'; b = input.read()) { if (b == -1) { @@ -253,7 +259,7 @@ public static String readLine(java.io.InputStream input) } public static String readFullLine(java.io.InputStream input) - throws IOException { + throws IOException { StringBuilder linebuf = new StringBuilder(); for (int b = input.read(); ; b = input.read()) { if (b == -1) { @@ -303,8 +309,7 @@ public static String readToString(Reader is) throws IOException { } static void copyZipStream(InputStream inputStream, OutputStream outputStream) - throws IOException - { + throws IOException { byte[] writeBuffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; for (int br = inputStream.read(writeBuffer); br != -1; br = inputStream.read(writeBuffer)) { outputStream.write(writeBuffer, 0, br); @@ -386,8 +391,10 @@ private static void processFolder(final File folder, final ZipOutputStream zipOu } } } + public static void deleteDirectory(@NotNull Path path) throws IOException { - Files.walkFileTree(path, + Files.walkFileTree( + path, new SimpleFileVisitor<>() { @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { @@ -400,7 +407,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO Files.delete(file); return FileVisitResult.CONTINUE; } - }); + } + ); } @Nullable diff --git a/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IntKeyMap.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IntKeyMap.java new file mode 100644 index 00000000..861f21ac --- /dev/null +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/IntKeyMap.java @@ -0,0 +1,845 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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.jkiss.utils; + +import java.util.*; + +/** + * Map with int key. + */ +@SuppressWarnings("unchecked") +public class IntKeyMap implements Map { + /** + * The default initial capacity - MUST be a power of two. + */ + static final int DEFAULT_INITIAL_CAPACITY = 16; + + /** + * The maximum capacity, used if a higher value is implicitly specified + * by either of the constructors with arguments. + * MUST be a power of two <= 1<<30. + */ + static final int MAXIMUM_CAPACITY = 1 << 30; + + /** + * The load fast used when none specified in constructor. + **/ + static final float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The table, resized as necessary. Length MUST Always be a power of two. + */ + transient IntEntry[] table; + + /** + * The number of key-value mappings contained in this identity hash map. + */ + transient int size; + + /** + * The next size value at which to resize (capacity * load factor). + * + * @serial + */ + int threshold; + + /** + * The load factor for the hash table. + * + * @serial + */ + final float loadFactor; + + /** + * The number of times this IntKeyMap has been structurally modified + */ + transient volatile int modCount; + + /** + * Constructs an empty IntKeyMap with the specified initial + * capacity and load factor. + * + * @param initialCapacity The initial capacity. + * @param loadFactor The load factor. + * @throws IllegalArgumentException if the initial capacity is negative + * or the load factor is nonpositive. + */ + public IntKeyMap(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) { + throw new IllegalArgumentException("Illegal initial capacity: " + + initialCapacity); + } + if (initialCapacity > MAXIMUM_CAPACITY) { + initialCapacity = MAXIMUM_CAPACITY; + } + if (loadFactor <= 0 || Float.isNaN(loadFactor)) { + throw new IllegalArgumentException("Illegal load factor: " + + loadFactor); + } + + // Find a power of 2 >= initialCapacity + int capacity = 1; + while (capacity < initialCapacity) { + capacity <<= 1; + } + + this.loadFactor = loadFactor; + threshold = (int) (capacity * loadFactor); + table = new IntEntry[capacity]; + } + + /** + * Constructs an empty IntKeyMap with the specified initial + * capacity and the default load factor (0.75). + * + * @param initialCapacity the initial capacity. + * @throws IllegalArgumentException if the initial capacity is negative. + */ + public IntKeyMap(int initialCapacity) { + this(initialCapacity, DEFAULT_LOAD_FACTOR); + } + + /** + * Constructs an empty IntKeyMap with the default initial capacity + * (16) and the default load factor (0.75). + */ + public IntKeyMap() { + this.loadFactor = DEFAULT_LOAD_FACTOR; + threshold = DEFAULT_INITIAL_CAPACITY; + table = new IntEntry[DEFAULT_INITIAL_CAPACITY]; + } + + static int hash(long x) { + int h = (int) (x ^ (x >>> 32)); + h += ~(h << 9); + h ^= (h >>> 14); + h += (h << 4); + h ^= (h >>> 10); + return h; + } + + /** + * Returns index for hash code h. + */ + static int indexFor(int h, int length) { + return h & (length - 1); + } + + /** + * Returns the number of key-value mappings in this map. + * + * @return the number of key-value mappings in this map. + */ + @Override + public int size() { + return size; + } + + /** + * Returns true if this map contains no key-value mappings. + * + * @return true if this map contains no key-value mappings. + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public boolean containsKey(Object key) { + return containsKey(((Number) key).intValue()); + } + + /** + * Returns the value to which the specified key is mapped in this identity + * hash map, or null if the map contains no mapping for this key. + * A return value of null does not necessarily indicate + * that the map contains no mapping for the key; it is also possible that + * the map explicitly maps the key to null. The + * containsKey method may be used to distinguish these two cases. + * + * @param key the key whose associated value is to be returned. + * @return the value to which this map maps the specified key, or + * null if the map contains no mapping for this key. + * @see #put(int, Object) + */ + public VALUE get(int key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + IntEntry e = table[i]; + while (true) { + if (e == null) { + return null; + } + if (e.hash == hash && key == e.key) { + return e.value; + } + e = e.next; + } + } + + /** + * Returns true if this map contains a mapping for the + * specified key. + */ + public boolean containsKey(int key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + IntEntry e = table[i]; + while (e != null) { + if (e.hash == hash && key == e.key) { + return true; + } + e = e.next; + } + return false; + } + + /** + * Returns the entry associated with the specified key in the + * IntKeyMap. Returns null if the IntKeyMap contains no mapping + * for this key. + */ + IntEntry getEntry(int key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + IntEntry e = table[i]; + while (e != null && !(e.hash == hash && key == e.key)) { + e = e.next; + } + return e; + } + + /** + * Associates the specified value with the specified key in this map. + * If the map previously contained a mapping for this key, the old + * value is replaced. + * + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * @return previous value associated with specified key, or null + * if there was no mapping for key. A null return can + * also indicate that the IntKeyMap previously associated + * null with the specified key. + */ + public VALUE put(int key, VALUE value) { + int hash = hash(key); + int i = indexFor(hash, table.length); + + for (IntEntry e = table[i]; e != null; e = e.next) { + if (e.hash == hash && key == e.key) { + VALUE oldValue = e.value; + e.value = value; + return oldValue; + } + } + + modCount++; + addEntry(hash, key, value, i); + return null; + } + + /** + * This method is used instead of put by constructors and + * pseudoconstructors (clone, readObject). It does not resize the table, + * check for comodification, etc. It calls createEntry rather than + * addEntry. + */ + private void putForCreate(int key, VALUE value) { + int hash = hash(key); + int i = indexFor(hash, table.length); + + /** + * Look for preexisting entry for key. This will never happen for + * clone or deserialize. It will only happen for construction if the + * input Map is a sorted map whose ordering is inconsistent w/ equals. + */ + for (IntEntry e = table[i]; e != null; e = e.next) { + if (e.hash == hash && key == e.key) { + e.value = value; + return; + } + } + + createEntry(hash, key, value, i); + } + + void putAllForCreate(IntKeyMap m) { + for (Iterator i = m.entrySet().iterator(); i.hasNext(); ) { + IntEntry e = (IntEntry) i.next(); + putForCreate(e.key, e.value); + } + } + + /** + * Rehashes the contents of this map into a new IntKeyMap instance + * with a larger capacity. This method is called automatically when the + * number of keys in this map exceeds its capacity and load factor. + * + * @param newCapacity the new capacity, MUST be a power of two. + */ + void resize(int newCapacity) { + // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 + IntEntry[] oldTable = table; + int oldCapacity = oldTable.length; + + // check if needed + if (size < threshold || oldCapacity > newCapacity) { + return; + } + + IntEntry[] newTable = new IntEntry[newCapacity]; + transfer(newTable); + table = newTable; + threshold = (int) (newCapacity * loadFactor); + } + + /** + * Transfer all entries from current table to newTable. + */ + void transfer(IntEntry[] newTable) { + IntEntry[] src = table; + int newCapacity = newTable.length; + for (int j = 0; j < src.length; j++) { + IntEntry e = src[j]; + if (e != null) { + src[j] = null; + do { + IntEntry next = e.next; + int i = indexFor(e.hash, newCapacity); + e.next = newTable[i]; + newTable[i] = e; + e = next; + } while (e != null); + } + } + } + + /** + * Copies all of the mappings from the specified map to this map + * These mappings will replace any mappings that + * this map had for any of the keys currently in the specified map. + * + * @param t mappings to be stored in this map. + * @throws NullPointerException if the specified map is null. + */ + public void putAll(IntKeyMap t) { + // Expand enough to hold t's elements without resizing. + int n = t.size(); + if (n == 0) { + return; + } + if (n >= threshold) { + n = (int) (n / loadFactor + 1); + if (n > MAXIMUM_CAPACITY) { + n = MAXIMUM_CAPACITY; + } + int capacity = table.length; + while (capacity < n) { + capacity <<= 1; + } + resize(capacity); + } + + for (Iterator i = t.entrySet().iterator(); i.hasNext(); ) { + IntEntry e = (IntEntry) i.next(); + put(e.key, e.value); + } + } + + /** + * Removes the mapping for this key from this map if present. + * + * @param key key whose mapping is to be removed from the map. + * @return previous value associated with specified key, or null + * if there was no mapping for key. A null return can + * also indicate that the map previously associated null + * with the specified key. + */ + public VALUE remove(int key) { + IntEntry e = removeEntryForKey(key); + return (e == null ? null : e.value); + } + + /** + * Removes and returns the entry associated with the specified key + * in the IntKeyMap. Returns null if the IntKeyMap contains no mapping + * for this key. + */ + IntEntry removeEntryForKey(int key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + IntEntry prev = table[i]; + IntEntry e = prev; + + while (e != null) { + IntEntry next = e.next; + if (e.hash == hash && key == e.key) { + modCount++; + size--; + if (prev == e) { + table[i] = next; + } else { + prev.next = next; + } + return e; + } + prev = e; + e = next; + } + + return e; + } + + /** + * Special version of remove for EntrySet. + */ + IntEntry removeMapping(Object o) { + if (!(o instanceof IntEntry)) { + return null; + } + + IntEntry entry = (IntEntry) o; + int hash = hash(entry.key); + int i = indexFor(hash, table.length); + IntEntry prev = table[i]; + IntEntry e = prev; + + while (e != null) { + IntEntry next = e.next; + if (e.hash == hash && e.equals(entry)) { + modCount++; + size--; + if (prev == e) { + table[i] = next; + } else { + prev.next = next; + } + return e; + } + prev = e; + e = next; + } + + return e; + } + + /** + * Removes all mappings from this map. + */ + @Override + public void clear() { + modCount++; + IntEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + tab[i] = null; + } + size = 0; + } + + /** + * Returns true if this map maps one or more keys to the + * specified value. + * + * @param value value whose presence in this map is to be tested. + * @return true if this map maps one or more keys to the + * specified value. + */ + @Override + public boolean containsValue(Object value) { + if (value == null) { + return containsNullValue(); + } + + IntEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + for (IntEntry e = tab[i]; e != null; e = e.next) { + if (value.equals(e.value)) { + return true; + } + } + } + return false; + } + + @Override + public VALUE get(Object key) { + return get(((Number) key).intValue()); + } + + @Override + public VALUE put(Integer key, VALUE value) { + return put(key.intValue(), value); + } + + @Override + public VALUE remove(Object key) { + return remove(((Number) key).intValue()); + } + + @Override + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + /** + * Special-case code for containsValue with null argument + **/ + private boolean containsNullValue() { + IntEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + for (IntEntry e = tab[i]; e != null; e = e.next) { + if (e.value == null) { + return true; + } + } + } + return false; + } + + public static class IntEntry implements Entry { + final int key; + VALUE value; + final int hash; + IntEntry next; + + /** + * Create new entry. + */ + IntEntry(int h, int k, VALUE v, IntEntry n) { + value = v; + next = n; + key = k; + hash = h; + } + + public int getInt() { + return key; + } + + @Override + public Integer getKey() { + return key; + } + + @Override + public VALUE getValue() { + return value; + } + + @Override + public VALUE setValue(VALUE newValue) { + VALUE oldValue = value; + value = newValue; + return oldValue; + } + + public boolean equals(Object o) { + if (!(o instanceof IntEntry)) { + return false; + } + IntEntry e = (IntEntry) o; + if (key == e.key) { + VALUE v1 = getValue(); + VALUE v2 = e.getValue(); + if (v1 == v2 || (v1 != null && v1.equals(v2))) { + return true; + } + } + return false; + } + + public int hashCode() { + return hash(key) ^ (value == null ? 0 : value.hashCode()); + } + + public String toString() { + return String.valueOf(key) + "=" + getValue(); + } + + } + + /** + * Add a new entry with the specified key, value and hash code to + * the specified bucket. It is the responsibility of this + * method to resize the table if appropriate. + *

+ * Subclass overrides this to alter the behavior of put method. + */ + void addEntry(int hash, int key, VALUE value, int bucketIndex) { + table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); + if (size++ >= threshold) { + resize(2 * table.length); + } + } + + /** + * Like addEntry except that this version is used when creating entries + * as part of Map construction or "pseudo-construction" (cloning, + * deserialization). This version needn't worry about resizing the table. + *

+ * Subclass overrides this to alter the behavior of IntKeyMap(Map), + * clone, and readObject. + */ + void createEntry(int hash, int key, VALUE value, int bucketIndex) { + table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); + size++; + } + + private abstract class HashIterator implements Iterator { + IntEntry next; // next entry to return + int expectedModCount; // For fast-fail + int index; // current slot + IntEntry current; // current entry + + HashIterator() { + expectedModCount = modCount; + IntEntry[] t = table; + int i = t.length; + IntEntry n = null; + if (size != 0) { // advance to first entry + while (i > 0 && (n = t[--i]) == null) + ; + } + next = n; + index = i; + } + + @Override + public boolean hasNext() { + return next != null; + } + + IntEntry nextEntry() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + IntEntry e = next; + if (e == null) { + throw new NoSuchElementException(); + } + + IntEntry n = e.next; + IntEntry[] t = table; + int i = index; + while (n == null && i > 0) { + n = t[--i]; + } + index = i; + next = n; + return current = e; + } + + @Override + public void remove() { + if (current == null) { + throw new IllegalStateException(); + } + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + int k = current.key; + current = null; + IntKeyMap.this.removeEntryForKey(k); + expectedModCount = modCount; + } + + } + + private class ValueIterator extends HashIterator { + @Override + public VALUE next() { + return nextEntry().value; + } + } + + private class KeyIterator extends HashIterator { + @Override + public Integer next() { + return nextEntry().key; + } + + public int nextInt() { + return nextEntry().key; + } + } + + private class EntryIterator extends HashIterator> { + @Override + public IntEntry next() { + return nextEntry(); + } + } + + // Subclass overrides these to alter behavior of views' iterator() method + Iterator newKeyIterator() { + return new KeyIterator(); + } + + Iterator newValueIterator() { + return new ValueIterator(); + } + + Iterator> newEntryIterator() { + return new EntryIterator(); + } + + + // Views + + private transient Set> entrySet = null; + transient volatile Set keySet = null; + transient volatile Collection values = null; + + /** + * Returns a set view of the keys contained in this map. The set is + * backed by the map, so changes to the map are reflected in the set, and + * vice-versa. The set supports element removal, which removes the + * corresponding mapping from this map, via the Iterator.remove, + * Set.remove, removeAll, retainAll, and + * clear operations. It does not support the add or + * addAll operations. + * + * @return a set view of the keys contained in this map. + */ + @Override + public Set keySet() { + Set ks = keySet; + return (ks != null ? ks : (keySet = new KeySet())); + } + + private class KeySet extends AbstractSet { + @Override + public Iterator iterator() { + return newKeyIterator(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + if (o instanceof Number) { + return containsKey(((Number) o).intValue()); + } else { + return false; + } + } + + @Override + public boolean remove(Object o) { + if (o instanceof Number) { + return IntKeyMap.this.removeEntryForKey(((Number) o).intValue()) != null; + } else { + return false; + } + } + + @Override + public void clear() { + IntKeyMap.this.clear(); + } + } + + /** + * Returns a collection view of the values contained in this map. The + * collection is backed by the map, so changes to the map are reflected in + * the collection, and vice-versa. The collection supports element + * removal, which removes the corresponding mapping from this map, via the + * Iterator.remove, Collection.remove, + * removeAll, retainAll, and clear operations. + * It does not support the add or addAll operations. + * + * @return a collection view of the values contained in this map. + */ + @Override + public Collection values() { + Collection vs = values; + return (vs != null ? vs : (values = new Values())); + } + + private class Values extends AbstractCollection { + @Override + public Iterator iterator() { + return newValueIterator(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @Override + public void clear() { + IntKeyMap.this.clear(); + } + } + + @Override + public Set entrySet() { + Set> es = entrySet; + return (es != null ? es : (entrySet = new EntrySet())); + } + + private class EntrySet extends AbstractSet> { + @Override + public Iterator> iterator() { + return newEntryIterator(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof IntEntry)) { + return false; + } + IntEntry e = (IntEntry) o; + IntEntry candidate = getEntry(e.key); + return candidate != null && candidate.equals(e); + } + + @Override + public boolean remove(Object o) { + return removeMapping(o) != null; + } + + @Override + public int size() { + return size; + } + + @Override + public void clear() { + IntKeyMap.this.clear(); + } + } + + // These methods are used when serializing HashSets + int capacity() { + return table.length; + } + + float loadFactor() { + return loadFactor; + } +} diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/LazyValue.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LazyValue.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/LazyValue.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LazyValue.java index 9dafb24f..4533d844 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/LazyValue.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LazyValue.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LongKeyMap.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LongKeyMap.java new file mode 100644 index 00000000..adb6518e --- /dev/null +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/LongKeyMap.java @@ -0,0 +1,844 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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.jkiss.utils; + +import java.util.*; + +/** + * Map with long key. + */ +public class LongKeyMap implements Map { + /** + * The default initial capacity - MUST be a power of two. + */ + static final int DEFAULT_INITIAL_CAPACITY = 16; + + /** + * The maximum capacity, used if a higher value is implicitly specified + * by either of the constructors with arguments. + * MUST be a power of two <= 1<<30. + */ + static final int MAXIMUM_CAPACITY = 1 << 30; + + /** + * The load fast used when none specified in constructor. + **/ + static final float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The table, resized as necessary. Length MUST Always be a power of two. + */ + transient LongEntry[] table; + + /** + * The number of key-value mappings contained in this identity hash map. + */ + transient int size; + + /** + * The next size value at which to resize (capacity * load factor). + * + * @serial + */ + int threshold; + + /** + * The load factor for the hash table. + * + * @serial + */ + final float loadFactor; + + /** + * The number of times this LongKeyMap has been structurally modified + */ + transient volatile int modCount; + + /** + * Constructs an empty LongKeyMap with the specified initial + * capacity and load factor. + * + * @param initialCapacity The initial capacity. + * @param loadFactor The load factor. + * @throws IllegalArgumentException if the initial capacity is negative + * or the load factor is nonpositive. + */ + public LongKeyMap(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) { + throw new IllegalArgumentException("Illegal initial capacity: " + + initialCapacity); + } + if (initialCapacity > MAXIMUM_CAPACITY) { + initialCapacity = MAXIMUM_CAPACITY; + } + if (loadFactor <= 0 || Float.isNaN(loadFactor)) { + throw new IllegalArgumentException("Illegal load factor: " + + loadFactor); + } + + // Find a power of 2 >= initialCapacity + int capacity = 1; + while (capacity < initialCapacity) { + capacity <<= 1; + } + + this.loadFactor = loadFactor; + threshold = (int) (capacity * loadFactor); + table = new LongEntry[capacity]; + } + + /** + * Constructs an empty LongKeyMap with the specified initial + * capacity and the default load factor (0.75). + * + * @param initialCapacity the initial capacity. + * @throws IllegalArgumentException if the initial capacity is negative. + */ + public LongKeyMap(int initialCapacity) { + this(initialCapacity, DEFAULT_LOAD_FACTOR); + } + + /** + * Constructs an empty LongKeyMap with the default initial capacity + * (16) and the default load factor (0.75). + */ + public LongKeyMap() { + this.loadFactor = DEFAULT_LOAD_FACTOR; + threshold = DEFAULT_INITIAL_CAPACITY; + table = new LongEntry[DEFAULT_INITIAL_CAPACITY]; + } + + static int hash(long x) { + int h = (int) (x ^ (x >>> 32)); + h += ~(h << 9); + h ^= (h >>> 14); + h += (h << 4); + h ^= (h >>> 10); + return h; + } + + /** + * Returns index for hash code h. + */ + static int indexFor(int h, int length) { + return h & (length - 1); + } + + /** + * Returns the number of key-value mappings in this map. + * + * @return the number of key-value mappings in this map. + */ + @Override + public int size() { + return size; + } + + /** + * Returns true if this map contains no key-value mappings. + * + * @return true if this map contains no key-value mappings. + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public boolean containsKey(Object key) { + return containsKey(((Number) key).longValue()); + } + + /** + * Returns the value to which the specified key is mapped in this identity + * hash map, or null if the map contains no mapping for this key. + * A return value of null does not necessarily indicate + * that the map contains no mapping for the key; it is also possible that + * the map explicitly maps the key to null. The + * containsKey method may be used to distinguish these two cases. + * + * @param key the key whose associated value is to be returned. + * @return the value to which this map maps the specified key, or + * null if the map contains no mapping for this key. + * @see #put(long, Object) + */ + public VALUE get(long key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + LongEntry e = table[i]; + while (true) { + if (e == null) { + return null; + } + if (e.hash == hash && key == e.key) { + return e.value; + } + e = e.next; + } + } + + /** + * Returns true if this map contains a mapping for the + * specified key. + */ + public boolean containsKey(long key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + LongEntry e = table[i]; + while (e != null) { + if (e.hash == hash && key == e.key) { + return true; + } + e = e.next; + } + return false; + } + + /** + * Returns the entry associated with the specified key in the + * LongKeyMap. Returns null if the LongKeyMap contains no mapping + * for this key. + */ + LongEntry getEntry(long key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + LongEntry e = table[i]; + while (e != null && !(e.hash == hash && key == e.key)) { + e = e.next; + } + return e; + } + + /** + * Associates the specified value with the specified key in this map. + * If the map previously contained a mapping for this key, the old + * value is replaced. + * + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * @return previous value associated with specified key, or null + * if there was no mapping for key. A null return can + * also indicate that the LongKeyMap previously associated + * null with the specified key. + */ + public VALUE put(long key, VALUE value) { + int hash = hash(key); + int i = indexFor(hash, table.length); + + for (LongEntry e = table[i]; e != null; e = e.next) { + if (e.hash == hash && key == e.key) { + VALUE oldValue = e.value; + e.value = value; + return oldValue; + } + } + + modCount++; + addEntry(hash, key, value, i); + return null; + } + + /** + * This method is used instead of put by constructors and + * pseudoconstructors (clone, readObject). It does not resize the table, + * check for comodification, etc. It calls createEntry rather than + * addEntry. + */ + private void putForCreate(long key, VALUE value) { + int hash = hash(key); + int i = indexFor(hash, table.length); + + /** + * Look for preexisting entry for key. This will never happen for + * clone or deserialize. It will only happen for construction if the + * input Map is a sorted map whose ordering is inconsistent w/ equals. + */ + for (LongEntry e = table[i]; e != null; e = e.next) { + if (e.hash == hash && key == e.key) { + e.value = value; + return; + } + } + + createEntry(hash, key, value, i); + } + + void putAllForCreate(LongKeyMap m) { + for (Iterator> i = m.entrySet().iterator(); i.hasNext(); ) { + LongEntry e = i.next(); + putForCreate(e.key, e.value); + } + } + + /** + * Rehashes the contents of this map into a new LongKeyMap instance + * with a larger capacity. This method is called automatically when the + * number of keys in this map exceeds its capacity and load factor. + * + * @param newCapacity the new capacity, MUST be a power of two. + */ + void resize(int newCapacity) { + // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 + LongEntry[] oldTable = table; + int oldCapacity = oldTable.length; + + // check if needed + if (size < threshold || oldCapacity > newCapacity) { + return; + } + + LongEntry[] newTable = new LongEntry[newCapacity]; + transfer(newTable); + table = newTable; + threshold = (int) (newCapacity * loadFactor); + } + + /** + * Transfer all entries from current table to newTable. + */ + void transfer(LongEntry[] newTable) { + LongEntry[] src = table; + int newCapacity = newTable.length; + for (int j = 0; j < src.length; j++) { + LongEntry e = src[j]; + if (e != null) { + src[j] = null; + do { + LongEntry next = e.next; + int i = indexFor(e.hash, newCapacity); + e.next = newTable[i]; + newTable[i] = e; + e = next; + } while (e != null); + } + } + } + + /** + * Copies all of the mappings from the specified map to this map + * These mappings will replace any mappings that + * this map had for any of the keys currently in the specified map. + * + * @param t mappings to be stored in this map. + * @throws NullPointerException if the specified map is null. + */ + public void putAll(LongKeyMap t) { + // Expand enough to hold t's elements without resizing. + int n = t.size(); + if (n == 0) { + return; + } + if (n >= threshold) { + n = (int) (n / loadFactor + 1); + if (n > MAXIMUM_CAPACITY) { + n = MAXIMUM_CAPACITY; + } + int capacity = table.length; + while (capacity < n) { + capacity <<= 1; + } + resize(capacity); + } + + for (Iterator> i = t.entrySet().iterator(); i.hasNext(); ) { + LongEntry e = i.next(); + put(e.key, e.value); + } + } + + /** + * Removes the mapping for this key from this map if present. + * + * @param key key whose mapping is to be removed from the map. + * @return previous value associated with specified key, or null + * if there was no mapping for key. A null return can + * also indicate that the map previously associated null + * with the specified key. + */ + public VALUE remove(long key) { + LongEntry e = removeEntryForKey(key); + return (e == null ? null : e.value); + } + + /** + * Removes and returns the entry associated with the specified key + * in the LongKeyMap. Returns null if the LongKeyMap contains no mapping + * for this key. + */ + LongEntry removeEntryForKey(long key) { + int hash = hash(key); + int i = indexFor(hash, table.length); + LongEntry prev = table[i]; + LongEntry e = prev; + + while (e != null) { + LongEntry next = e.next; + if (e.hash == hash && key == e.key) { + modCount++; + size--; + if (prev == e) { + table[i] = next; + } else { + prev.next = next; + } + return e; + } + prev = e; + e = next; + } + + return e; + } + + /** + * Special version of remove for EntrySet. + */ + LongEntry removeMapping(Object o) { + if (!(o instanceof LongEntry)) { + return null; + } + + LongEntry entry = (LongEntry) o; + int hash = hash(entry.key); + int i = indexFor(hash, table.length); + LongEntry prev = table[i]; + LongEntry e = prev; + + while (e != null) { + LongEntry next = e.next; + if (e.hash == hash && e.equals(entry)) { + modCount++; + size--; + if (prev == e) { + table[i] = next; + } else { + prev.next = next; + } + return e; + } + prev = e; + e = next; + } + + return e; + } + + /** + * Removes all mappings from this map. + */ + @Override + public void clear() { + modCount++; + LongEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + tab[i] = null; + } + size = 0; + } + + /** + * Returns true if this map maps one or more keys to the + * specified value. + * + * @param value value whose presence in this map is to be tested. + * @return true if this map maps one or more keys to the + * specified value. + */ + @Override + public boolean containsValue(Object value) { + if (value == null) { + return containsNullValue(); + } + + LongEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + for (LongEntry e = tab[i]; e != null; e = e.next) { + if (value.equals(e.value)) { + return true; + } + } + } + return false; + } + + @Override + public VALUE get(Object key) { + return get(((Number) key).longValue()); + } + + @Override + public VALUE put(Long key, VALUE value) { + return put(key.longValue(), value); + } + + @Override + public VALUE remove(Object key) { + return remove(((Number) key).longValue()); + } + + @Override + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + /** + * Special-case code for containsValue with null argument + **/ + private boolean containsNullValue() { + LongEntry tab[] = table; + for (int i = 0; i < tab.length; i++) { + for (LongEntry e = tab[i]; e != null; e = e.next) { + if (e.value == null) { + return true; + } + } + } + return false; + } + + public static class LongEntry implements Entry { + final long key; + VALUE value; + final int hash; + LongEntry next; + + /** + * Create new entry. + */ + LongEntry(int h, long k, VALUE v, LongEntry n) { + value = v; + next = n; + key = k; + hash = h; + } + + public long getLong() { + return key; + } + + @Override + public Long getKey() { + return key; + } + + @Override + public VALUE getValue() { + return value; + } + + @Override + public VALUE setValue(VALUE newValue) { + VALUE oldValue = value; + value = newValue; + return oldValue; + } + + public boolean equals(Object o) { + if (!(o instanceof LongEntry)) { + return false; + } + LongEntry e = (LongEntry) o; + if (key == e.key) { + VALUE v1 = getValue(); + VALUE v2 = e.getValue(); + if (v1 == v2 || (v1 != null && v1.equals(v2))) { + return true; + } + } + return false; + } + + public int hashCode() { + return hash(key) ^ (value == null ? 0 : value.hashCode()); + } + + public String toString() { + return String.valueOf(key) + "=" + getValue(); + } + + } + + /** + * Add a new entry with the specified key, value and hash code to + * the specified bucket. It is the responsibility of this + * method to resize the table if appropriate. + *

+ * Subclass overrides this to alter the behavior of put method. + */ + void addEntry(int hash, long key, VALUE value, int bucketIndex) { + table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); + if (size++ >= threshold) { + resize(2 * table.length); + } + } + + /** + * Like addEntry except that this version is used when creating entries + * as part of Map construction or "pseudo-construction" (cloning, + * deserialization). This version needn't worry about resizing the table. + *

+ * Subclass overrides this to alter the behavior of LongKeyMap(Map), + * clone, and readObject. + */ + void createEntry(int hash, long key, VALUE value, int bucketIndex) { + table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); + size++; + } + + private abstract class HashIterator implements Iterator { + LongEntry next; // next entry to return + int expectedModCount; // For fast-fail + int index; // current slot + LongEntry current; // current entry + + HashIterator() { + expectedModCount = modCount; + LongEntry[] t = table; + int i = t.length; + LongEntry n = null; + if (size != 0) { // advance to first entry + while (i > 0 && (n = t[--i]) == null) + ; + } + next = n; + index = i; + } + + @Override + public boolean hasNext() { + return next != null; + } + + LongEntry nextEntry() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + LongEntry e = next; + if (e == null) { + throw new NoSuchElementException(); + } + + LongEntry n = e.next; + LongEntry[] t = table; + int i = index; + while (n == null && i > 0) { + n = t[--i]; + } + index = i; + next = n; + return current = e; + } + + @Override + public void remove() { + if (current == null) { + throw new IllegalStateException(); + } + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + long k = current.key; + current = null; + LongKeyMap.this.removeEntryForKey(k); + expectedModCount = modCount; + } + + } + + private class ValueIterator extends HashIterator { + @Override + public VALUE next() { + return nextEntry().value; + } + } + + private class KeyIterator extends HashIterator { + @Override + public Long next() { + return nextEntry().key; + } + + public long nextLong() { + return nextEntry().key; + } + } + + private class EntryIterator extends HashIterator> { + @Override + public LongEntry next() { + return nextEntry(); + } + } + + // Subclass overrides these to alter behavior of views' iterator() method + Iterator newKeyIterator() { + return new KeyIterator(); + } + + Iterator newValueIterator() { + return new ValueIterator(); + } + + Iterator> newEntryIterator() { + return new EntryIterator(); + } + + + // Views + + private transient Set> entrySet = null; + transient volatile Set keySet = null; + transient volatile Collection values = null; + + /** + * Returns a set view of the keys contained in this map. The set is + * backed by the map, so changes to the map are reflected in the set, and + * vice-versa. The set supports element removal, which removes the + * corresponding mapping from this map, via the Iterator.remove, + * Set.remove, removeAll, retainAll, and + * clear operations. It does not support the add or + * addAll operations. + * + * @return a set view of the keys contained in this map. + */ + @Override + public Set keySet() { + Set ks = keySet; + return (ks != null ? ks : (keySet = new KeySet())); + } + + private class KeySet extends AbstractSet { + @Override + public Iterator iterator() { + return newKeyIterator(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + if (o instanceof Number) { + return containsKey(((Number) o).longValue()); + } else { + return false; + } + } + + @Override + public boolean remove(Object o) { + if (o instanceof Number) { + return LongKeyMap.this.removeEntryForKey(((Number) o).longValue()) != null; + } else { + return false; + } + } + + @Override + public void clear() { + LongKeyMap.this.clear(); + } + } + + /** + * Returns a collection view of the values contained in this map. The + * collection is backed by the map, so changes to the map are reflected in + * the collection, and vice-versa. The collection supports element + * removal, which removes the corresponding mapping from this map, via the + * Iterator.remove, Collection.remove, + * removeAll, retainAll, and clear operations. + * It does not support the add or addAll operations. + * + * @return a collection view of the values contained in this map. + */ + @Override + public Collection values() { + Collection vs = values; + return (vs != null ? vs : (values = new Values())); + } + + private class Values extends AbstractCollection { + @Override + public Iterator iterator() { + return newValueIterator(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @Override + public void clear() { + LongKeyMap.this.clear(); + } + } + + @Override + public Set entrySet() { + Set> es = entrySet; + return (es != null ? es : (entrySet = new EntrySet())); + } + + private class EntrySet extends AbstractSet> { + @Override + public Iterator> iterator() { + return newEntryIterator(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof LongEntry)) { + return false; + } + LongEntry e = (LongEntry) o; + LongEntry candidate = getEntry(e.key); + return candidate != null && candidate.equals(e); + } + + @Override + public boolean remove(Object o) { + return removeMapping(o) != null; + } + + @Override + public int size() { + return size; + } + + @Override + public void clear() { + LongKeyMap.this.clear(); + } + } + + // These methods are used when serializing HashSets + int capacity() { + return table.length; + } + + float loadFactor() { + return loadFactor; + } +} diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/MapUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/MapUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/MapUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/MapUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/MimeType.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/MimeType.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/MimeType.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/MimeType.java index 8732a66e..4373849a 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/MimeType.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/MimeType.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/Pair.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Pair.java similarity index 92% rename from modules/org.jkiss.utils/src/org/jkiss/utils/Pair.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Pair.java index 44435f06..278bc10f 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/Pair.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/Pair.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,14 +25,12 @@ public class Pair { private T1 first; private T2 second; - public Pair(T1 first, T2 second) - { + public Pair(T1 first, T2 second) { this.first = first; this.second = second; } - public T1 getFirst() - { + public T1 getFirst() { return first; } @@ -40,8 +38,7 @@ public void setFirst(T1 first) { this.first = first; } - public T2 getSecond() - { + public T2 getSecond() { return second; } @@ -73,6 +70,7 @@ public boolean equals(Object o) { /** * Compute a hash code using the hash codes of the underlying objects + * * @return a hashcode of the Pair */ @Override diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ReaderWriterLock.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ReaderWriterLock.java index 5209d637..00300c39 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/ReaderWriterLock.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,10 +90,12 @@ public void exec( boolean writing, ExceptableConsumer action ) throws EXCEPTION { - this.compute(writing, m -> { - action.accept(m); - return null; - }); + this.compute( + writing, m -> { + action.accept(m); + return null; + } + ); } /** diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/SecurityUtils.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/SecurityUtils.java index e72d1efb..0c8e06c2 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/SecurityUtils.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -126,7 +126,8 @@ public static String generateUniqueId() { public static String makeDigest( String userAlias, - String userPassword) { + String userPassword + ) { try { if (userPassword == null) { userPassword = ""; @@ -142,7 +143,8 @@ public static String makeDigest( } public static String makeDigest( - String userPassword) { + String userPassword + ) { try { MessageDigest md5 = MessageDigest.getInstance(ECRYPTION_ALGORYTHM); diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/StandardConstants.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/StandardConstants.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/StandardConstants.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/StandardConstants.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/StringUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/StringUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/StringUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/StringUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/WSClientUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/WSClientUtils.java similarity index 97% rename from modules/org.jkiss.utils/src/org/jkiss/utils/WSClientUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/WSClientUtils.java index 2b5fd5b7..4c4ce11f 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/WSClientUtils.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/WSClientUtils.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ public class WSClientUtils { private static final String HTTP_PROXY_PORT = "http.proxyPort"; private static final String HTTPS_PROXY_HOST = "https.proxyHost"; private static final String HTTPS_PROXY_PORT = "https.proxyPort"; + @Nullable public static List getHeaders(@Nullable Map> allHeaders, @NotNull String headerName) { if (allHeaders == null) { diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParser.java similarity index 97% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParser.java index 30b7bafb..daee266d 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParser.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -183,8 +183,10 @@ public CSVParser(char separator, char quotechar, char escape, boolean strictQuot * @param ignoreLeadingWhiteSpace if true, white space in front of a quote in a field is ignored * @param ignoreQuotations if true, treat quotations like any other character. */ - public CSVParser(char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, - boolean ignoreQuotations) { + public CSVParser( + char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, + boolean ignoreQuotations + ) { this(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace, ignoreQuotations, DEFAULT_NULL_FIELD_INDICATOR); } @@ -201,8 +203,10 @@ public CSVParser(char separator, char quotechar, char escape, boolean strictQuot * @param nullFieldIndicator which field content will be returned as null: EMPTY_SEPARATORS, EMPTY_QUOTES, * BOTH, NEITHER (default) */ - CSVParser(char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, - boolean ignoreQuotations, CSVReaderNullFieldIndicator nullFieldIndicator) { + CSVParser( + char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, + boolean ignoreQuotations, CSVReaderNullFieldIndicator nullFieldIndicator + ) { if (anyCharactersAreTheSame(separator, quotechar, escape)) { throw new UnsupportedOperationException("The separator, quote, and escape characters must be different!"); } @@ -334,7 +338,7 @@ private String[] parseLine(String nextLine, boolean multi) throws IOException { if (pending != null) { String s = pending; pending = null; - return new String[]{s}; + return new String[] {s}; } else { return null; } diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParserBuilder.java similarity index 94% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParserBuilder.java index b60a0bfe..5ed7acd0 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVParserBuilder.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,7 +61,8 @@ public CSVParserBuilder() { * @return The CSVParserBuilder */ public CSVParserBuilder withSeparator( - final char separator) { + final char separator + ) { this.separator = separator; return this; } @@ -74,7 +75,8 @@ public CSVParserBuilder withSeparator( * @return The CSVParserBuilder */ public CSVParserBuilder withQuoteChar( - final char quoteChar) { + final char quoteChar + ) { this.quoteChar = quoteChar; return this; } @@ -87,7 +89,8 @@ public CSVParserBuilder withQuoteChar( * @return The CSVParserBuilder */ public CSVParserBuilder withEscapeChar( - final char escapeChar) { + final char escapeChar + ) { this.escapeChar = escapeChar; return this; } @@ -101,7 +104,8 @@ public CSVParserBuilder withEscapeChar( * @return The CSVParserBuilder */ public CSVParserBuilder withStrictQuotes( - final boolean strictQuotes) { + final boolean strictQuotes + ) { this.strictQuotes = strictQuotes; return this; } @@ -114,7 +118,8 @@ public CSVParserBuilder withStrictQuotes( * @return The CSVParserBuilder */ public CSVParserBuilder withIgnoreLeadingWhiteSpace( - final boolean ignoreLeadingWhiteSpace) { + final boolean ignoreLeadingWhiteSpace + ) { this.ignoreLeadingWhiteSpace = ignoreLeadingWhiteSpace; return this; } @@ -126,7 +131,8 @@ public CSVParserBuilder withIgnoreLeadingWhiteSpace( * @return The CSVParserBuilder */ public CSVParserBuilder withIgnoreQuotations( - final boolean ignoreQuotations) { + final boolean ignoreQuotations + ) { this.ignoreQuotations = ignoreQuotations; return this; } @@ -144,7 +150,8 @@ public CSVParser build() { strictQuotes, ignoreLeadingWhiteSpace, ignoreQuotations, - nullFieldIndicator); + nullFieldIndicator + ); } /** diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReader.java similarity index 94% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReader.java index ca607285..209da26c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReader.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -105,8 +105,10 @@ public CSVReader(Reader reader, char separator, char quotechar, boolean strictQu * @param escape the character to use for escaping a separator or quote */ - public CSVReader(Reader reader, char separator, - char quotechar, char escape) { + public CSVReader( + Reader reader, char separator, + char quotechar, char escape + ) { this(reader, separator, quotechar, escape, DEFAULT_SKIP_LINES, CSVParser.DEFAULT_STRICT_QUOTES); } @@ -160,10 +162,20 @@ public CSVReader(Reader reader, char separator, char quotechar, char escape, int * @param strictQuotes sets if characters outside the quotes are ignored * @param ignoreLeadingWhiteSpace it true, parser should ignore white space before a quote in a field */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, boolean ignoreLeadingWhiteSpace) { - this(reader, + public CSVReader( + Reader reader, + char separator, + char quotechar, + char escape, + int line, + boolean strictQuotes, + boolean ignoreLeadingWhiteSpace + ) { + this( + reader, line, - new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace)); + new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace) + ); } /** @@ -178,10 +190,14 @@ public CSVReader(Reader reader, char separator, char quotechar, char escape, int * @param ignoreLeadingWhiteSpace if true, parser should ignore white space before a quote in a field * @param keepCR if true the reader will keep carriage returns, otherwise it will discard them. */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, - boolean ignoreLeadingWhiteSpace, boolean keepCR) { - this(reader, line, - new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace), keepCR, DEFAULT_VERIFY_READER); + public CSVReader( + Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, + boolean ignoreLeadingWhiteSpace, boolean keepCR + ) { + this( + reader, line, + new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace), keepCR, DEFAULT_VERIFY_READER + ); } /** diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderBuilder.java similarity index 82% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderBuilder.java index e576f6e0..a93fc5cb 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderBuilder.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,18 +58,19 @@ public class CSVReaderBuilder { private boolean verifyReader = CSVReader.DEFAULT_VERIFY_READER; private CSVReaderNullFieldIndicator nullFieldIndicator = CSVReaderNullFieldIndicator.NEITHER; - /** - * Sets the reader to an underlying CSV source. - * - * @param reader the reader to an underlying CSV source. - */ - public CSVReaderBuilder( - final Reader reader) { - if (reader == null) { - throw new IllegalArgumentException("Reader may not be null"); - } - this.reader = reader; - } + /** + * Sets the reader to an underlying CSV source. + * + * @param reader the reader to an underlying CSV source. + */ + public CSVReaderBuilder( + final Reader reader + ) { + if (reader == null) { + throw new IllegalArgumentException("Reader may not be null"); + } + this.reader = reader; + } /** * Used by unit tests. @@ -99,16 +100,17 @@ protected CSVParser getCsvParser() { } /** - * Sets the line number to skip for start reading. + * Sets the line number to skip for start reading. * * @param skipLines the line number to skip for start reading. * @return the CSVReaderBuilder with skipLines set. - */ + */ public CSVReaderBuilder withSkipLines( - final int skipLines) { - this.skipLines = (skipLines <= 0 ? 0 : skipLines); - return this; - } + final int skipLines + ) { + this.skipLines = (skipLines <= 0 ? 0 : skipLines); + return this; + } /** @@ -116,23 +118,25 @@ public CSVReaderBuilder withSkipLines( * * @param csvParser the parser to use to parse the input. * @return the CSVReaderBuilder with the CSVParser set. - */ + */ public CSVReaderBuilder withCSVParser( - final /*@Nullable*/ CSVParser csvParser) { - this.csvParser = csvParser; - return this; - } + final /*@Nullable*/ CSVParser csvParser + ) { + this.csvParser = csvParser; + return this; + } /** * Creates the CSVReader. + * * @return the CSVReader based on the set criteria. */ public CSVReader build() { - final CSVParser parser = - (csvParser != null ? csvParser : parserBuilder.withFieldAsNull(nullFieldIndicator).build()); - return new CSVReader(reader, skipLines, parser, keepCR, verifyReader); - } + final CSVParser parser = + (csvParser != null ? csvParser : parserBuilder.withFieldAsNull(nullFieldIndicator).build()); + return new CSVReader(reader, skipLines, parser, keepCR, verifyReader); + } /** * Sets if the reader will keep or discard carriage returns. @@ -156,10 +160,10 @@ protected boolean keepCarriageReturn() { /** * Checks to see if the CSVReader should verify the reader state before reads or not. - * + *

* This should be set to false if you are using some form of asynchronous reader (like readers created * by the java.nio.* classes). - * + *

* The default value is true. * * @param verifyReader true if CSVReader should verify reader before each read, false otherwise. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java index 0966ebd6..03825f3b 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVWriter.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVWriter.java index 0afb172d..c7dd0ae7 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/CSVWriter.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -235,7 +235,8 @@ public void writeNext(String[] nextLine) { * @return true if the line contains the quote, escape, separator, newline or return. */ private boolean stringContainsSpecialCharacters(String line) { - return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1 || line.indexOf(separator) != -1 || line.contains(DEFAULT_LINE_END) || line.contains("\r"); + return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1 || line.indexOf(separator) != -1 || line.contains( + DEFAULT_LINE_END) || line.contains("\r"); } /** diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/LineReader.java similarity index 97% rename from modules/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/LineReader.java index d47e5a5c..98664059 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/csv/LineReader.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableConsumer.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableConsumer.java similarity index 93% rename from modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableConsumer.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableConsumer.java index 3cc4248d..521edec2 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableConsumer.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableConsumer.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableFunction.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableFunction.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableFunction.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableFunction.java index 52273e4c..2a876a3f 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableFunction.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableFunction.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableSupplier.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableSupplier.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableSupplier.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableSupplier.java index 952472a3..712c707c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/function/ThrowableSupplier.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/function/ThrowableSupplier.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/BOMInputStream.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/BOMInputStream.java index 84b398f4..5a25f91f 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/BOMInputStream.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/ByteOrderMark.java similarity index 97% rename from modules/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/ByteOrderMark.java index 67c93bbf..46ea933b 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/io/ByteOrderMark.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/IOAuthHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/IOAuthHandler.java similarity index 93% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/IOAuthHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/IOAuthHandler.java index 7dc3d000..8252a1df 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/IOAuthHandler.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/IOAuthHandler.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthConstants.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthConstants.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthConstants.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthConstants.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthTokens.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthTokens.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthTokens.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthTokens.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/OAuthUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/OAuthUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java similarity index 93% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java index 46a04e7d..b39e0f67 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/client/OAuthClientCredentialsHandler.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,9 +53,9 @@ public class OAuthClientCredentialsHandler implements IOAuthHandler { /** * Constructs an OAuthHandler with required parameters. * - * @param clientId the OAuth client ID - * @param secretId the OAuth client secret (nullable for PKCE-only flows) - * @param authUrl the authorization endpoint URL + * @param clientId the OAuth client ID + * @param secretId the OAuth client secret (nullable for PKCE-only flows) + * @param authUrl the authorization endpoint URL */ public OAuthClientCredentialsHandler( @NotNull String clientId, diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/client/OAuthRequestPostBuilder.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/client/OAuthRequestPostBuilder.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/client/OAuthRequestPostBuilder.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/client/OAuthRequestPostBuilder.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/IOAuthCodeResponseHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/IOAuthCodeResponseHandler.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/IOAuthCodeResponseHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/IOAuthCodeResponseHandler.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthCodeHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthCodeHandler.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthCodeHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthCodeHandler.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthCodeResponseHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthCodeResponseHandler.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthCodeResponseHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthCodeResponseHandler.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java similarity index 99% rename from modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java index 4cb26aaa..1ca1cc1c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/oauth/code/OAuthRequestURLBuilder.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/process/ProcessNameUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/process/ProcessNameUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/process/ProcessNameUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/process/ProcessNameUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/HttpTransportInvocationHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/HttpTransportInvocationHandler.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/HttpTransportInvocationHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/HttpTransportInvocationHandler.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestHandlerFactory.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestHandlerFactory.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestHandlerFactory.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestHandlerFactory.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestMapping.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestMapping.java index 669deb6c..6a1abf6f 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestMapping.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestParameter.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestParameter.java index aa9b2ed5..704d4faa 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RequestParameter.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestClient.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestClient.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestClient.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestClient.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolver.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolver.java similarity index 94% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolver.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolver.java index eba77f2b..e1a18c35 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolver.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolver.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java index 1b0b3df8..3f68e128 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestEndpointResolverAdvanced.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestProxy.java similarity index 93% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestProxy.java index 097f5988..9b3b843c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestProxy.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestServer.java similarity index 99% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestServer.java index 6eb84e47..e0bf71b6 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RestServer.java @@ -37,11 +37,7 @@ import java.net.InetSocketAddress; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.*; import java.util.function.Predicate; import java.util.logging.Level; @@ -204,7 +200,8 @@ private static RequestHandler createHandler( return handlerFactory.createHandler(controller.cls, controller.instance, gson, filter, landingPage); } - private static final Type REQUEST_TYPE = new TypeToken>() {}.getType(); + private static final Type REQUEST_TYPE = new TypeToken>() { + }.getType(); public static class RequestHandler implements HttpHandler { diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcClient.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcClient.java similarity index 91% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcClient.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcClient.java index c7f4c44b..0ffc3624 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcClient.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcClient.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ protected static T createProxy( ) { final Object proxy = Proxy.newProxyInstance( cls.getClassLoader(), - new Class[]{cls, RestProxy.class}, + new Class[] {cls, RestProxy.class}, invocationHandler ); diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcConstants.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcConstants.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcConstants.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcConstants.java index cbe7cddd..4cb520bb 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcConstants.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcConstants.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ public JsonElement serialize(LocalDate date, Type typeOfSrc, JsonSerializationCo return new JsonPrimitive(date.format(ISE_DATE_FORMATTER)); // "yyyy-mm-dd" } } + public static class LocalDateTimeAdapter implements JsonSerializer { public JsonElement serialize(LocalDateTime date, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(date.format(ISE_TIMESTAMP_FORMATTER)); // "yyyy-mm-dd" diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcEndpoint.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcEndpoint.java similarity index 94% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcEndpoint.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcEndpoint.java index f2d217b3..5e86dc3e 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcEndpoint.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcEndpoint.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcErrorInfo.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcErrorInfo.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcErrorInfo.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcErrorInfo.java index b1bc03cc..795facad 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcErrorInfo.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcErrorInfo.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcException.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcException.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcException.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcException.java index 8f2b7285..f0be8f6e 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcException.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcException.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcInvocationHandler.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcInvocationHandler.java similarity index 98% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcInvocationHandler.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcInvocationHandler.java index 61f78441..b8515b95 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rest/RpcInvocationHandler.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rest/RpcInvocationHandler.java @@ -18,7 +18,6 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.utils.BeanUtils; @@ -159,7 +158,8 @@ public synchronized Object invoke(Object proxy, Method method, Object[] args) th protected abstract String invokeRemoteMethod( @NotNull Method method, @Nullable RequestMapping mapping, - @NotNull Map values); + @NotNull Map values + ); protected abstract void closeClient(); diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcConstants.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcConstants.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcConstants.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcConstants.java index c70cbd28..b62ffc5c 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcConstants.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcConstants.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcRequest.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcRequest.java similarity index 95% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcRequest.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcRequest.java index 5005c430..8cdb4eee 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcRequest.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcRequest.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcResponse.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcResponse.java similarity index 96% rename from modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcResponse.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcResponse.java index ff5e7473..60cf9c05 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/rpc/RpcResponse.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/rpc/RpcResponse.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/time/ExtendedDateFormat.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/time/ExtendedDateFormat.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/time/ExtendedDateFormat.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/time/ExtendedDateFormat.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/SAXListener.java similarity index 92% rename from modules/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/SAXListener.java index f6faf926..55706dc0 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/SAXListener.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,23 +22,23 @@ import org.xml.sax.Attributes; /** - SAX document listener -*/ + * SAX document listener + */ public interface SAXListener { - void saxStartElement( + void saxStartElement( @NotNull SAXReader reader, @Nullable String namespaceURI, @NotNull String localName, @NotNull Attributes attributes ) throws XMLException; - void saxText( + void saxText( @NotNull SAXReader reader, @NotNull String data ) throws XMLException; - void saxEndElement( + void saxEndElement( @NotNull SAXReader reader, @Nullable String namespaceURI, @NotNull String localName @@ -71,6 +71,7 @@ public void saxEndElement( ) throws XMLException { } } + SAXListener EMPTY_LISTENER = new BaseListener(); } diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/SAXReader.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/SAXReader.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/xml/SAXReader.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/SAXReader.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLBuilder.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLBuilder.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLBuilder.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLBuilder.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLException.java similarity index 71% rename from modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLException.java index 4a7fd190..ececd57d 100644 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java +++ b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLException.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +20,13 @@ /** * XMLException */ -public class XMLException extends Exception -{ - public XMLException(String message) - { - super(message); - } +public class XMLException extends Exception { + public XMLException(String message) { + super(message); + } - public XMLException(String message, Throwable cause) - { - super(message, cause); - } + public XMLException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLUtils.java b/modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLUtils.java similarity index 100% rename from modules/org.jkiss.utils/src/org/jkiss/utils/xml/XMLUtils.java rename to modules/org.jkiss.utils/src/main/java/org/jkiss/utils/xml/XMLUtils.java diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java b/modules/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java deleted file mode 100644 index 0b7abee3..00000000 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java +++ /dev/null @@ -1,807 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * 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.jkiss.utils; - -import java.util.*; - -/** - Map with int key. -*/ -@SuppressWarnings("unchecked") -public class IntKeyMap implements Map { - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified - * by either of the constructors with arguments. - * MUST be a power of two <= 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load fast used when none specified in constructor. - **/ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient IntEntry[] table; - - /** - * The number of key-value mappings contained in this identity hash map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this IntKeyMap has been structurally modified - */ - transient volatile int modCount; - - /** - * Constructs an empty IntKeyMap with the specified initial - * capacity and load factor. - * - * @param initialCapacity The initial capacity. - * @param loadFactor The load factor. - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive. - */ - public IntKeyMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " + - initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " + - loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int)(capacity * loadFactor); - table = new IntEntry[capacity]; - } - - /** - * Constructs an empty IntKeyMap with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity. - * @throws IllegalArgumentException if the initial capacity is negative. - */ - public IntKeyMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty IntKeyMap with the default initial capacity - * (16) and the default load factor (0.75). - */ - public IntKeyMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = DEFAULT_INITIAL_CAPACITY; - table = new IntEntry[DEFAULT_INITIAL_CAPACITY]; - } - - static int hash(long x) { - int h = (int)(x ^ (x >>> 32)); - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length-1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map. - */ - @Override - public int size() { - return size; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - @Override - public boolean isEmpty() - { - return size == 0; - } - - @Override - public boolean containsKey(Object key) - { - return containsKey(((Number)key).intValue()); - } - - /** - * Returns the value to which the specified key is mapped in this identity - * hash map, or null if the map contains no mapping for this key. - * A return value of null does not necessarily indicate - * that the map contains no mapping for the key; it is also possible that - * the map explicitly maps the key to null. The - * containsKey method may be used to distinguish these two cases. - * - * @param key the key whose associated value is to be returned. - * @return the value to which this map maps the specified key, or - * null if the map contains no mapping for this key. - * @see #put(int, Object) - */ - public VALUE get(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (true) { - if (e == null) - return null; - if (e.hash == hash && key == e.key) - return e.value; - e = e.next; - } - } - - /** - * Returns true if this map contains a mapping for the - * specified key. - */ - public boolean containsKey(int key) - { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (e != null) { - if (e.hash == hash && key == e.key) - return true; - e = e.next; - } - return false; - } - - /** - * Returns the entry associated with the specified key in the - * IntKeyMap. Returns null if the IntKeyMap contains no mapping - * for this key. - */ - IntEntry getEntry(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (e != null && !(e.hash == hash && key == e.key)) - e = e.next; - return e; - } - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for this key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the IntKeyMap previously associated - * null with the specified key. - */ - public VALUE put(int key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - for (IntEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - VALUE oldValue = e.value; - e.value = value; - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * This method is used instead of put by constructors and - * pseudoconstructors (clone, readObject). It does not resize the table, - * check for comodification, etc. It calls createEntry rather than - * addEntry. - */ - private void putForCreate(int key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for - * clone or deserialize. It will only happen for construction if the - * input Map is a sorted map whose ordering is inconsistent w/ equals. - */ - for (IntEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - void putAllForCreate(IntKeyMap m) { - for (Iterator i = m.entrySet().iterator(); i.hasNext(); ) { - IntEntry e = (IntEntry) i.next(); - putForCreate(e.key, e.value); - } - } - - /** - * Rehashes the contents of this map into a new IntKeyMap instance - * with a larger capacity. This method is called automatically when the - * number of keys in this map exceeds its capacity and load factor. - * - * @param newCapacity the new capacity, MUST be a power of two. - */ - void resize(int newCapacity) { - // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 - IntEntry[] oldTable = table; - int oldCapacity = oldTable.length; - - // check if needed - if (size < threshold || oldCapacity > newCapacity) - return; - - IntEntry[] newTable = new IntEntry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int)(newCapacity * loadFactor); - } - - /** - * Transfer all entries from current table to newTable. - */ - void transfer(IntEntry[] newTable) { - IntEntry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - IntEntry e = src[j]; - if (e != null) { - src[j] = null; - do { - IntEntry next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map - * These mappings will replace any mappings that - * this map had for any of the keys currently in the specified map. - * - * @param t mappings to be stored in this map. - * @throws NullPointerException if the specified map is null. - */ - public void putAll(IntKeyMap t) { - // Expand enough to hold t's elements without resizing. - int n = t.size(); - if (n == 0) - return; - if (n >= threshold) { - n = (int)(n / loadFactor + 1); - if (n > MAXIMUM_CAPACITY) - n = MAXIMUM_CAPACITY; - int capacity = table.length; - while (capacity < n) - capacity <<= 1; - resize(capacity); - } - - for (Iterator i = t.entrySet().iterator(); i.hasNext(); ) { - IntEntry e = (IntEntry) i.next(); - put(e.key, e.value); - } - } - - /** - * Removes the mapping for this key from this map if present. - * - * @param key key whose mapping is to be removed from the map. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the map previously associated null - * with the specified key. - */ - public VALUE remove(int key) { - IntEntry e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key - * in the IntKeyMap. Returns null if the IntKeyMap contains no mapping - * for this key. - */ - IntEntry removeEntryForKey(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry prev = table[i]; - IntEntry e = prev; - - while (e != null) { - IntEntry next = e.next; - if (e.hash == hash && key == e.key) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - IntEntry removeMapping(Object o) { - if (!(o instanceof IntEntry)) - return null; - - IntEntry entry = (IntEntry)o; - int hash = hash(entry.key); - int i = indexFor(hash, table.length); - IntEntry prev = table[i]; - IntEntry e = prev; - - while (e != null) { - IntEntry next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all mappings from this map. - */ - @Override - public void clear() { - modCount++; - IntEntry tab[] = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns true if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested. - * @return true if this map maps one or more keys to the - * specified value. - */ - @Override - public boolean containsValue(Object value) - { - if (value == null) - return containsNullValue(); - - IntEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (IntEntry e = tab[i] ; e != null ; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - @Override - public VALUE get(Object key) - { - return get(((Number)key).intValue()); - } - - @Override - public VALUE put(Integer key, VALUE value) - { - return put(key.intValue(), value); - } - - @Override - public VALUE remove(Object key) - { - return remove(((Number)key).intValue()); - } - - @Override - public void putAll(Map t) - { - throw new UnsupportedOperationException(); - } - - /** - * Special-case code for containsValue with null argument - **/ - private boolean containsNullValue() - { - IntEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (IntEntry e = tab[i] ; e != null ; e = e.next) - if (e.value == null) - return true; - return false; - } - - public static class IntEntry implements Entry { - final int key; - VALUE value; - final int hash; - IntEntry next; - - /** - * Create new entry. - */ - IntEntry(int h, int k, VALUE v, IntEntry n) { - value = v; - next = n; - key = k; - hash = h; - } - - public int getInt() { - return key; - } - - @Override - public Integer getKey() - { - return key; - } - - @Override - public VALUE getValue() { - return value; - } - - @Override - public VALUE setValue(VALUE newValue) { - VALUE oldValue = value; - value = newValue; - return oldValue; - } - - public boolean equals(Object o) { - if (!(o instanceof IntEntry)) - return false; - IntEntry e = (IntEntry)o; - if (key == e.key) { - VALUE v1 = getValue(); - VALUE v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public int hashCode() { - return hash(key) ^ (value==null ? 0 : value.hashCode()); - } - - public String toString() { - return String.valueOf(key) + "=" + getValue(); - } - - } - - /** - * Add a new entry with the specified key, value and hash code to - * the specified bucket. It is the responsibility of this - * method to resize the table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, int key, VALUE value, int bucketIndex) { - table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries - * as part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of IntKeyMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, int key, VALUE value, int bucketIndex) { - table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); - size++; - } - - private abstract class HashIterator implements Iterator { - IntEntry next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - IntEntry current; // current entry - - HashIterator() { - expectedModCount = modCount; - IntEntry[] t = table; - int i = t.length; - IntEntry n = null; - if (size != 0) { // advance to first entry - while (i > 0 && (n = t[--i]) == null) - ; - } - next = n; - index = i; - } - - @Override - public boolean hasNext() { - return next != null; - } - - IntEntry nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - IntEntry e = next; - if (e == null) - throw new NoSuchElementException(); - - IntEntry n = e.next; - IntEntry[] t = table; - int i = index; - while (n == null && i > 0) - n = t[--i]; - index = i; - next = n; - return current = e; - } - - @Override - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - int k = current.key; - current = null; - IntKeyMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private class ValueIterator extends HashIterator { - @Override - public VALUE next() { - return nextEntry().value; - } - } - - private class KeyIterator extends HashIterator { - @Override - public Integer next() { - return nextEntry().key; - } - public int nextInt() { - return nextEntry().key; - } - } - - private class EntryIterator extends HashIterator> { - @Override - public IntEntry next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator newKeyIterator() - { - return new KeyIterator(); - } - Iterator newValueIterator() - { - return new ValueIterator(); - } - Iterator> newEntryIterator() - { - return new EntryIterator(); - } - - - // Views - - private transient Set> entrySet = null; - transient volatile Set keySet = null; - transient volatile Collection values = null; - - /** - * Returns a set view of the keys contained in this map. The set is - * backed by the map, so changes to the map are reflected in the set, and - * vice-versa. The set supports element removal, which removes the - * corresponding mapping from this map, via the Iterator.remove, - * Set.remove, removeAll, retainAll, and - * clear operations. It does not support the add or - * addAll operations. - * - * @return a set view of the keys contained in this map. - */ - @Override - public Set keySet() { - Set ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private class KeySet extends AbstractSet { - @Override - public Iterator iterator() { - return newKeyIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - if (o instanceof Number) { - return containsKey(((Number)o).intValue()); - } else { - return false; - } - } - @Override - public boolean remove(Object o) { - if (o instanceof Number) { - return IntKeyMap.this.removeEntryForKey(((Number)o).intValue()) != null; - } else { - return false; - } - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - /** - * Returns a collection view of the values contained in this map. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element - * removal, which removes the corresponding mapping from this map, via the - * Iterator.remove, Collection.remove, - * removeAll, retainAll, and clear operations. - * It does not support the add or addAll operations. - * - * @return a collection view of the values contained in this map. - */ - @Override - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private class Values extends AbstractCollection { - @Override - public Iterator iterator() { - return newValueIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - return containsValue(o); - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - @Override - public Set entrySet() - { - Set> es = entrySet; - return (es != null ? es : (entrySet = new EntrySet())); - } - - private class EntrySet extends AbstractSet> { - @Override - public Iterator> iterator() { - return newEntryIterator(); - } - @Override - public boolean contains(Object o) { - if (!(o instanceof IntEntry)) - return false; - IntEntry e = (IntEntry)o; - IntEntry candidate = getEntry(e.key); - return candidate != null && candidate.equals(e); - } - @Override - public boolean remove(Object o) { - return removeMapping(o) != null; - } - @Override - public int size() { - return size; - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - // These methods are used when serializing HashSets - int capacity() { return table.length; } - float loadFactor() { return loadFactor; } -} diff --git a/modules/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java b/modules/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java deleted file mode 100644 index 80473e87..00000000 --- a/modules/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java +++ /dev/null @@ -1,806 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * 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.jkiss.utils; - -import java.util.*; - -/** - Map with long key. -*/ -public class LongKeyMap implements Map { - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified - * by either of the constructors with arguments. - * MUST be a power of two <= 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load fast used when none specified in constructor. - **/ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient LongEntry[] table; - - /** - * The number of key-value mappings contained in this identity hash map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this LongKeyMap has been structurally modified - */ - transient volatile int modCount; - - /** - * Constructs an empty LongKeyMap with the specified initial - * capacity and load factor. - * - * @param initialCapacity The initial capacity. - * @param loadFactor The load factor. - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive. - */ - public LongKeyMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " + - initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " + - loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int)(capacity * loadFactor); - table = new LongEntry[capacity]; - } - - /** - * Constructs an empty LongKeyMap with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity. - * @throws IllegalArgumentException if the initial capacity is negative. - */ - public LongKeyMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty LongKeyMap with the default initial capacity - * (16) and the default load factor (0.75). - */ - public LongKeyMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = DEFAULT_INITIAL_CAPACITY; - table = new LongEntry[DEFAULT_INITIAL_CAPACITY]; - } - - static int hash(long x) { - int h = (int)(x ^ (x >>> 32)); - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length-1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map. - */ - @Override - public int size() { - return size; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - @Override - public boolean isEmpty() - { - return size == 0; - } - - @Override - public boolean containsKey(Object key) - { - return containsKey(((Number)key).longValue()); - } - - /** - * Returns the value to which the specified key is mapped in this identity - * hash map, or null if the map contains no mapping for this key. - * A return value of null does not necessarily indicate - * that the map contains no mapping for the key; it is also possible that - * the map explicitly maps the key to null. The - * containsKey method may be used to distinguish these two cases. - * - * @param key the key whose associated value is to be returned. - * @return the value to which this map maps the specified key, or - * null if the map contains no mapping for this key. - * @see #put(long, Object) - */ - public VALUE get(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (true) { - if (e == null) - return null; - if (e.hash == hash && key == e.key) - return e.value; - e = e.next; - } - } - - /** - * Returns true if this map contains a mapping for the - * specified key. - */ - public boolean containsKey(long key) - { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (e != null) { - if (e.hash == hash && key == e.key) - return true; - e = e.next; - } - return false; - } - - /** - * Returns the entry associated with the specified key in the - * LongKeyMap. Returns null if the LongKeyMap contains no mapping - * for this key. - */ - LongEntry getEntry(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (e != null && !(e.hash == hash && key == e.key)) - e = e.next; - return e; - } - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for this key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the LongKeyMap previously associated - * null with the specified key. - */ - public VALUE put(long key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - for (LongEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - VALUE oldValue = e.value; - e.value = value; - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * This method is used instead of put by constructors and - * pseudoconstructors (clone, readObject). It does not resize the table, - * check for comodification, etc. It calls createEntry rather than - * addEntry. - */ - private void putForCreate(long key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for - * clone or deserialize. It will only happen for construction if the - * input Map is a sorted map whose ordering is inconsistent w/ equals. - */ - for (LongEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - void putAllForCreate(LongKeyMap m) { - for (Iterator> i = m.entrySet().iterator(); i.hasNext(); ) { - LongEntry e = i.next(); - putForCreate(e.key, e.value); - } - } - - /** - * Rehashes the contents of this map into a new LongKeyMap instance - * with a larger capacity. This method is called automatically when the - * number of keys in this map exceeds its capacity and load factor. - * - * @param newCapacity the new capacity, MUST be a power of two. - */ - void resize(int newCapacity) { - // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 - LongEntry[] oldTable = table; - int oldCapacity = oldTable.length; - - // check if needed - if (size < threshold || oldCapacity > newCapacity) - return; - - LongEntry[] newTable = new LongEntry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int)(newCapacity * loadFactor); - } - - /** - * Transfer all entries from current table to newTable. - */ - void transfer(LongEntry[] newTable) { - LongEntry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - LongEntry e = src[j]; - if (e != null) { - src[j] = null; - do { - LongEntry next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map - * These mappings will replace any mappings that - * this map had for any of the keys currently in the specified map. - * - * @param t mappings to be stored in this map. - * @throws NullPointerException if the specified map is null. - */ - public void putAll(LongKeyMap t) { - // Expand enough to hold t's elements without resizing. - int n = t.size(); - if (n == 0) - return; - if (n >= threshold) { - n = (int)(n / loadFactor + 1); - if (n > MAXIMUM_CAPACITY) - n = MAXIMUM_CAPACITY; - int capacity = table.length; - while (capacity < n) - capacity <<= 1; - resize(capacity); - } - - for (Iterator> i = t.entrySet().iterator(); i.hasNext(); ) { - LongEntry e = i.next(); - put(e.key, e.value); - } - } - - /** - * Removes the mapping for this key from this map if present. - * - * @param key key whose mapping is to be removed from the map. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the map previously associated null - * with the specified key. - */ - public VALUE remove(long key) { - LongEntry e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key - * in the LongKeyMap. Returns null if the LongKeyMap contains no mapping - * for this key. - */ - LongEntry removeEntryForKey(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry prev = table[i]; - LongEntry e = prev; - - while (e != null) { - LongEntry next = e.next; - if (e.hash == hash && key == e.key) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - LongEntry removeMapping(Object o) { - if (!(o instanceof LongEntry)) - return null; - - LongEntry entry = (LongEntry)o; - int hash = hash(entry.key); - int i = indexFor(hash, table.length); - LongEntry prev = table[i]; - LongEntry e = prev; - - while (e != null) { - LongEntry next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all mappings from this map. - */ - @Override - public void clear() { - modCount++; - LongEntry tab[] = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns true if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested. - * @return true if this map maps one or more keys to the - * specified value. - */ - @Override - public boolean containsValue(Object value) - { - if (value == null) - return containsNullValue(); - - LongEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (LongEntry e = tab[i] ; e != null ; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - @Override - public VALUE get(Object key) - { - return get(((Number)key).longValue()); - } - - @Override - public VALUE put(Long key, VALUE value) - { - return put(key.longValue(), value); - } - - @Override - public VALUE remove(Object key) - { - return remove(((Number)key).longValue()); - } - - @Override - public void putAll(Map t) - { - throw new UnsupportedOperationException(); - } - - /** - * Special-case code for containsValue with null argument - **/ - private boolean containsNullValue() - { - LongEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (LongEntry e = tab[i] ; e != null ; e = e.next) - if (e.value == null) - return true; - return false; - } - - public static class LongEntry implements Entry { - final long key; - VALUE value; - final int hash; - LongEntry next; - - /** - * Create new entry. - */ - LongEntry(int h, long k, VALUE v, LongEntry n) { - value = v; - next = n; - key = k; - hash = h; - } - - public long getLong() { - return key; - } - - @Override - public Long getKey() - { - return key; - } - - @Override - public VALUE getValue() { - return value; - } - - @Override - public VALUE setValue(VALUE newValue) { - VALUE oldValue = value; - value = newValue; - return oldValue; - } - - public boolean equals(Object o) { - if (!(o instanceof LongEntry)) - return false; - LongEntry e = (LongEntry)o; - if (key == e.key) { - VALUE v1 = getValue(); - VALUE v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public int hashCode() { - return hash(key) ^ (value==null ? 0 : value.hashCode()); - } - - public String toString() { - return String.valueOf(key) + "=" + getValue(); - } - - } - - /** - * Add a new entry with the specified key, value and hash code to - * the specified bucket. It is the responsibility of this - * method to resize the table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, long key, VALUE value, int bucketIndex) { - table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries - * as part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of LongKeyMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, long key, VALUE value, int bucketIndex) { - table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); - size++; - } - - private abstract class HashIterator implements Iterator { - LongEntry next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - LongEntry current; // current entry - - HashIterator() { - expectedModCount = modCount; - LongEntry[] t = table; - int i = t.length; - LongEntry n = null; - if (size != 0) { // advance to first entry - while (i > 0 && (n = t[--i]) == null) - ; - } - next = n; - index = i; - } - - @Override - public boolean hasNext() { - return next != null; - } - - LongEntry nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - LongEntry e = next; - if (e == null) - throw new NoSuchElementException(); - - LongEntry n = e.next; - LongEntry[] t = table; - int i = index; - while (n == null && i > 0) - n = t[--i]; - index = i; - next = n; - return current = e; - } - - @Override - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - long k = current.key; - current = null; - LongKeyMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private class ValueIterator extends HashIterator { - @Override - public VALUE next() { - return nextEntry().value; - } - } - - private class KeyIterator extends HashIterator { - @Override - public Long next() { - return nextEntry().key; - } - public long nextLong() { - return nextEntry().key; - } - } - - private class EntryIterator extends HashIterator> { - @Override - public LongEntry next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator newKeyIterator() - { - return new KeyIterator(); - } - Iterator newValueIterator() - { - return new ValueIterator(); - } - Iterator> newEntryIterator() - { - return new EntryIterator(); - } - - - // Views - - private transient Set> entrySet = null; - transient volatile Set keySet = null; - transient volatile Collection values = null; - - /** - * Returns a set view of the keys contained in this map. The set is - * backed by the map, so changes to the map are reflected in the set, and - * vice-versa. The set supports element removal, which removes the - * corresponding mapping from this map, via the Iterator.remove, - * Set.remove, removeAll, retainAll, and - * clear operations. It does not support the add or - * addAll operations. - * - * @return a set view of the keys contained in this map. - */ - @Override - public Set keySet() { - Set ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private class KeySet extends AbstractSet { - @Override - public Iterator iterator() { - return newKeyIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - if (o instanceof Number) { - return containsKey(((Number)o).longValue()); - } else { - return false; - } - } - @Override - public boolean remove(Object o) { - if (o instanceof Number) { - return LongKeyMap.this.removeEntryForKey(((Number)o).longValue()) != null; - } else { - return false; - } - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - /** - * Returns a collection view of the values contained in this map. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element - * removal, which removes the corresponding mapping from this map, via the - * Iterator.remove, Collection.remove, - * removeAll, retainAll, and clear operations. - * It does not support the add or addAll operations. - * - * @return a collection view of the values contained in this map. - */ - @Override - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private class Values extends AbstractCollection { - @Override - public Iterator iterator() { - return newValueIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - return containsValue(o); - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - @Override - public Set entrySet() - { - Set> es = entrySet; - return (es != null ? es : (entrySet = new EntrySet())); - } - - private class EntrySet extends AbstractSet> { - @Override - public Iterator> iterator() { - return newEntryIterator(); - } - @Override - public boolean contains(Object o) { - if (!(o instanceof LongEntry)) - return false; - LongEntry e = (LongEntry)o; - LongEntry candidate = getEntry(e.key); - return candidate != null && candidate.equals(e); - } - @Override - public boolean remove(Object o) { - return removeMapping(o) != null; - } - @Override - public int size() { - return size; - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - // These methods are used when serializing HashSets - int capacity() { return table.length; } - float loadFactor() { return loadFactor; } -} diff --git a/modules/org.jkiss.utils/src/test/java/org/jkiss/utils/csv/CSVReaderTest.java b/modules/org.jkiss.utils/src/test/java/org/jkiss/utils/csv/CSVReaderTest.java new file mode 100644 index 00000000..0238f2b6 --- /dev/null +++ b/modules/org.jkiss.utils/src/test/java/org/jkiss/utils/csv/CSVReaderTest.java @@ -0,0 +1,215 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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.jkiss.utils.csv; + +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CSVReaderTest { + + private static final String DEFAULT_SEPARATOR = ","; + private static final String DEFAULT_QUOTE = "\""; + private static final String DEFAULT_ESCAPE = "\\"; + + @ParameterizedTest + @ValueSource(strings = {DEFAULT_SEPARATOR, ";"}) + void testReadAllSingleLine(@NotNull String separator) throws Exception { + // given + String input = "a,b,c"; + List expected = rows( + row("a", "b", "c") + ); + + // then + assertReadAll( + expected, + input, + separator, + null, + null + ); + } + + @ParameterizedTest + @ValueSource(strings = {DEFAULT_SEPARATOR, ";"}) + void testReadAllMultiLine(@NotNull String separator) throws Exception { + assertReadAll( + rows( + row("a", "b", "c"), + row("1", "2", "3"), + row("x", "y", "z") + ), + "a,b,c\n1,2,3\nx,y,z", + separator, + null, + null + ); + } + + @ParameterizedTest + @MethodSource("provideSeparators") + void testReadAllMultilineInsideQuotes(@NotNull String separator, @NotNull String quote, @NotNull String escape) throws Exception { + assertReadAll( + rows( + row("a", "hello\nworld", "c"), + row("1", "2", "3") + ), + "a,\"hello\nworld\",c\n1,2,3", + separator, + quote, + escape + ); + } + + @ParameterizedTest + @MethodSource("provideSeparators") + void testReadSeparatorInsideQuotes(@NotNull String separator, @NotNull String quote, @NotNull String escape) throws Exception { + assertReadAll( + rows( + row("a", "hello" + separator + "world", "c"), + row("1", "2", "3") + ), + "a,\"hello" + separator + "world\",c\n1,2,3", + separator, + quote, + escape + ); + } + + @ParameterizedTest + @MethodSource("provideSeparators") + void testReadAllEscapedQuotes(@NotNull String separator, @NotNull String quote, @NotNull String escape) throws Exception { + assertReadAll( + rows( + row("a", "hello " + quote + "world" + quote, "c") + ), + "a,\"hello " + "\\" + "\"world" + "\\" + "\"" + "\"" + ",c", + separator, + quote, + escape + ); + } + + @ParameterizedTest + @MethodSource("provideSeparators") + void testReadAllEscapedEscape(@NotNull String separator, @NotNull String quote, @NotNull String escape) throws Exception { + assertReadAll( + rows( + row("a", "b" + escape + "c", "d") + ), + "a,b\\" + escape + "c,d", + separator, + quote, + escape + ); + } + + private void assertReadAll( + @NotNull List expected, + @NotNull String csvTemplate, + @Nullable String separator, + @Nullable String quoteChar, + @Nullable String escape + ) throws Exception { + + var csv = replaceInCSVToCustom(csvTemplate, separator, quoteChar, escape); + try (CSVReader reader = createReader(csv, separator, quoteChar, escape)) { + List actual = reader.readAll(); + + assertEquals( + expected.size(), + actual.size(), + "Differed rows length\nExpected:" + expected.stream().map(Arrays::toString).collect(Collectors.joining()) + + "\nActual :" + actual.stream().map(Arrays::toString).collect(Collectors.joining()) + ); + for (int i = 0; i < expected.size(); i++) { + assertArrayEquals( + expected.get(i), actual.get(i), "CSV: " + csv + "\nExpected: " + + Arrays.toString(expected.get(i)) + "\nActual : " + Arrays.toString(actual.get(i)) + ); + } + } + } + + private String replaceInCSVToCustom( + @NotNull String csvTemplate, + @Nullable String separator, + @Nullable String quoteChar, + @Nullable String escape + ) { + if (separator != null) { + csvTemplate = csvTemplate.replace(DEFAULT_SEPARATOR, separator); + } + if (quoteChar != null) { + csvTemplate = csvTemplate.replace(DEFAULT_QUOTE, quoteChar); + } + if (escape != null) { + csvTemplate = csvTemplate.replace(DEFAULT_ESCAPE, escape); + } + return csvTemplate; + } + + @NotNull + private CSVReader createReader( + @NotNull String csv, + @Nullable String separator, + @Nullable String quoteChar, + @Nullable String escape + ) { + return new CSVReader( + new StringReader(csv), + Objects.requireNonNullElse(separator, DEFAULT_SEPARATOR).charAt(0), + Objects.requireNonNullElse(quoteChar, DEFAULT_QUOTE).charAt(0), + Objects.requireNonNullElse(escape, DEFAULT_ESCAPE).charAt(0), + 0, + false + ); + } + + @NotNull + private List rows(String[]... rows) { + return List.of(rows); + } + + @NotNull + private String[] row(String... values) { + return values; + } + + private static List provideSeparators() { + return List.of( + //defaults + Arguments.of(DEFAULT_SEPARATOR, DEFAULT_QUOTE, DEFAULT_ESCAPE), + // alternative one char + Arguments.of(";", "'", "~") + ); + } + +} \ No newline at end of file diff --git a/root/pom.xml b/root/pom.xml index e89d6cbb..72e9d9ba 100644 --- a/root/pom.xml +++ b/root/pom.xml @@ -264,6 +264,11 @@ junit-jupiter-api ${junit-jupiter-version} + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter-version} + org.junit.jupiter junit-jupiter-engine