diff --git a/changelog.md b/changelog.md index 2af140fc61..672e093e35 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,8 @@ Codion Change Log ================== ## 0.18.23 +### is.codion.common +- JSpecify annotations applied to common modules. ## is.codion.common.core - ValueObserver.getOrThrow() added. ## is.codion.common.db diff --git a/common/core/build.gradle.kts b/common/core/build.gradle.kts index afdbe2945f..8d7e6340d2 100644 --- a/common/core/build.gradle.kts +++ b/common/core/build.gradle.kts @@ -1,3 +1,7 @@ +dependencies { + api(libs.jspecify) +} + tasks.register("writeVersion") { group = "build" description = "Writes the current framework version to a file available as a resource" diff --git a/common/core/src/main/java/is/codion/common/Configuration.java b/common/core/src/main/java/is/codion/common/Configuration.java index b751658b9c..7b70bfc251 100644 --- a/common/core/src/main/java/is/codion/common/Configuration.java +++ b/common/core/src/main/java/is/codion/common/Configuration.java @@ -175,7 +175,7 @@ public static PropertyValue characterValue(String key, char defaultVa * @return a configuration value builder */ public static PropertyValue stringValue(String key) { - return stringValue(key, null); + return STORE.stringValue(key); } /** @@ -196,7 +196,7 @@ public static PropertyValue stringValue(String key, String defaultValue) * @return a configuration value builder */ public static > PropertyValue enumValue(String key, Class enumClass) { - return enumValue(key, enumClass, null); + return STORE.enumValue(key, enumClass); } /** @@ -242,7 +242,7 @@ public static PropertyValue> listValue(String key, Function PropertyValue value(String key, Function parser) { - return value(key, parser, null); + return STORE.value(key, parser, Objects::toString); } /** diff --git a/common/core/src/main/java/is/codion/common/Nulls.java b/common/core/src/main/java/is/codion/common/Nulls.java index 24763b282d..71a58cfe2a 100644 --- a/common/core/src/main/java/is/codion/common/Nulls.java +++ b/common/core/src/main/java/is/codion/common/Nulls.java @@ -18,6 +18,8 @@ */ package is.codion.common; +import org.jspecify.annotations.Nullable; + import java.util.Arrays; import java.util.Objects; @@ -33,7 +35,7 @@ private Nulls() {} * @param object the object to check * @return true if the object is non null */ - public static boolean nonNull(Object object) { + public static boolean nonNull(@Nullable Object object) { return Objects.nonNull(object); } @@ -41,7 +43,7 @@ public static boolean nonNull(Object object) { * @param objects the objects to check * @return true if none of the given objects are null */ - public static boolean nonNull(Object... objects) { + public static boolean nonNull(@Nullable Object... objects) { if (objects == null) { return false; } diff --git a/common/core/src/main/java/is/codion/common/Serializer.java b/common/core/src/main/java/is/codion/common/Serializer.java index 8aa9d6005b..6633d617e0 100644 --- a/common/core/src/main/java/is/codion/common/Serializer.java +++ b/common/core/src/main/java/is/codion/common/Serializer.java @@ -18,6 +18,8 @@ */ package is.codion.common; +import org.jspecify.annotations.Nullable; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -39,7 +41,7 @@ private Serializer() {} * @return a byte array representing the serialized object, an empty byte array in case of null * @throws IOException in case of an exception */ - public static byte[] serialize(Object object) throws IOException { + public static byte[] serialize(@Nullable Object object) throws IOException { if (object != null) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); new ObjectOutputStream(byteArrayOutputStream).writeObject(object); @@ -54,11 +56,11 @@ public static byte[] serialize(Object object) throws IOException { * Deserializes the given byte array into a T, null or an empty byte array result in a null return value * @param bytes a byte array representing the serialized object * @param the type of the object represented in the byte array - * @return the deserialized object + * @return the deserialized object, null in case of an empty {@code bytes} array * @throws IOException in case of an exception * @throws ClassNotFoundException in case the deserialized class is not found */ - public static T deserialize(byte[] bytes) throws IOException, ClassNotFoundException { + public static @Nullable T deserialize(byte @Nullable[] bytes) throws IOException, ClassNotFoundException { if (bytes != null && bytes.length > 0) { return (T) new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject(); } diff --git a/common/core/src/main/java/is/codion/common/Text.java b/common/core/src/main/java/is/codion/common/Text.java index ac7c46c32b..2db3c15bda 100644 --- a/common/core/src/main/java/is/codion/common/Text.java +++ b/common/core/src/main/java/is/codion/common/Text.java @@ -20,6 +20,8 @@ import is.codion.common.property.PropertyValue; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.text.Collator; @@ -73,7 +75,7 @@ public static List collate(List values) { * @see #DEFAULT_COLLATOR_LANGUAGE */ public static Comparator collator() { - return collator(new Locale(DEFAULT_COLLATOR_LANGUAGE.get())); + return collator(new Locale(DEFAULT_COLLATOR_LANGUAGE.getOrThrow())); } /** @@ -116,7 +118,7 @@ public static String leftPad(String string, int length, char padChar) { * @param commaSeparatedValues a String with comma separated values * @return the trimmed values */ - public static List parseCommaSeparatedValues(String commaSeparatedValues) { + public static List parseCommaSeparatedValues(@Nullable String commaSeparatedValues) { if (nullOrEmpty(commaSeparatedValues)) { return Collections.emptyList(); } @@ -150,7 +152,7 @@ private static String padString(String string, int length, char padChar, boolean * @param string the string to check * @return true if the given string is null or empty, false otherwise */ - public static boolean nullOrEmpty(String string) { + public static boolean nullOrEmpty(@Nullable String string) { return string == null || string.isEmpty(); } @@ -159,7 +161,7 @@ public static boolean nullOrEmpty(String string) { * @param strings the strings to check * @return true if one of the given strings is null or empty or if no arguments are provided, false otherwise */ - public static boolean nullOrEmpty(String... strings) { + public static boolean nullOrEmpty(@Nullable String... strings) { if (strings == null || strings.length == 0) { return true; } @@ -182,7 +184,7 @@ private static final class SpaceAwareComparator implements Comparator, Ser private final Locale locale; - private transient Collator collator; + private transient @Nullable Collator collator; private SpaceAwareComparator(Locale locale) { this.locale = locale; diff --git a/common/core/src/main/java/is/codion/common/event/DefaultEvent.java b/common/core/src/main/java/is/codion/common/event/DefaultEvent.java index 1072e079f7..74948547a3 100644 --- a/common/core/src/main/java/is/codion/common/event/DefaultEvent.java +++ b/common/core/src/main/java/is/codion/common/event/DefaultEvent.java @@ -20,13 +20,15 @@ import is.codion.common.observer.Observer; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; final class DefaultEvent implements Event { private final Object lock = new Object(); - private DefaultObserver observer; + private @Nullable DefaultObserver observer; @Override public void run() { @@ -34,7 +36,7 @@ public void run() { } @Override - public void accept(T data) { + public void accept(@Nullable T data) { if (observer != null) { observer.notifyListeners(data); } diff --git a/common/core/src/main/java/is/codion/common/event/DefaultObserver.java b/common/core/src/main/java/is/codion/common/event/DefaultObserver.java index 839622f66c..40a7d07f21 100644 --- a/common/core/src/main/java/is/codion/common/event/DefaultObserver.java +++ b/common/core/src/main/java/is/codion/common/event/DefaultObserver.java @@ -20,6 +20,8 @@ import is.codion.common.observer.Observer; +import org.jspecify.annotations.Nullable; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -34,10 +36,10 @@ final class DefaultObserver implements Observer { private final Object lock = new Object(); - private Set listeners; - private Set> consumers; - private List> weakListeners; - private List>> weakConsumers; + private @Nullable Set listeners; + private @Nullable Set> consumers; + private @Nullable List> weakListeners; + private @Nullable List>> weakConsumers; @Override public boolean addConsumer(Consumer consumer) { @@ -121,7 +123,7 @@ public boolean removeWeakConsumer(Consumer consumer) { } } - void notifyListeners(T data) { + void notifyListeners(@Nullable T data) { for (Runnable listener : listeners()) { listener.run(); } diff --git a/common/core/src/main/java/is/codion/common/event/Event.java b/common/core/src/main/java/is/codion/common/event/Event.java index 2b476c95b6..30435a9d03 100644 --- a/common/core/src/main/java/is/codion/common/event/Event.java +++ b/common/core/src/main/java/is/codion/common/event/Event.java @@ -20,6 +20,8 @@ import is.codion.common.observer.Observer; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; /** @@ -79,7 +81,7 @@ public interface Event extends Runnable, Consumer, Observer { * @param data data associated with the event */ @Override - void accept(T data); + void accept(@Nullable T data); /** * @return an observer notified each time this event occurs diff --git a/common/core/src/main/java/is/codion/common/event/package-info.java b/common/core/src/main/java/is/codion/common/event/package-info.java new file mode 100644 index 0000000000..d154990599 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/event/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Event related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.event; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/format/DefaultLocaleDateTimePattern.java b/common/core/src/main/java/is/codion/common/format/DefaultLocaleDateTimePattern.java index d6d57fed56..1072003f0e 100644 --- a/common/core/src/main/java/is/codion/common/format/DefaultLocaleDateTimePattern.java +++ b/common/core/src/main/java/is/codion/common/format/DefaultLocaleDateTimePattern.java @@ -18,6 +18,8 @@ */ package is.codion.common.format; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.time.chrono.IsoChronology; @@ -49,7 +51,7 @@ final class DefaultLocaleDateTimePattern implements LocaleDateTimePattern, Seria private final String delimiter; private final boolean fourDigitYear; - private final String timePattern; + private final @Nullable String timePattern; private DefaultLocaleDateTimePattern(DefaultBuilder builder) { this.delimiter = requireNonNull(builder.delimiter, "delimiter must be specified"); @@ -92,7 +94,7 @@ private static String datePattern(Locale locale, String delimiter, boolean fourD } private static String dateTimePattern(Locale locale, String delimiter, boolean fourDigitYear, - String timePattern) { + @Nullable String timePattern) { requireNonNull(locale); String datePattern = DateTimeFormatterBuilder. getLocalizedDateTimePattern(FormatStyle.SHORT, null, IsoChronology.INSTANCE, locale).toLowerCase(locale); @@ -142,7 +144,7 @@ static final class DefaultBuilder implements Builder { private String delimiter = "."; private boolean fourDigitYear = true; - private String timePattern; + private @Nullable String timePattern; @Override public Builder delimiter(String delimiter) { diff --git a/common/core/src/main/java/is/codion/common/format/package-info.java b/common/core/src/main/java/is/codion/common/format/package-info.java new file mode 100644 index 0000000000..148f7b0abe --- /dev/null +++ b/common/core/src/main/java/is/codion/common/format/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Formatting related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.format; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/item/AbstractItem.java b/common/core/src/main/java/is/codion/common/item/AbstractItem.java index db77681025..8e15323593 100644 --- a/common/core/src/main/java/is/codion/common/item/AbstractItem.java +++ b/common/core/src/main/java/is/codion/common/item/AbstractItem.java @@ -18,6 +18,8 @@ */ package is.codion.common.item; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.util.Objects; @@ -27,18 +29,18 @@ abstract class AbstractItem implements Item, Serializable { @Serial private static final long serialVersionUID = 1; - private final T value; + private final @Nullable T value; /** * Creates a new Item. * @param value the value, may be null */ - AbstractItem(T value) { + AbstractItem(@Nullable T value) { this.value = value; } @Override - public final T value() { + public final @Nullable T value() { return value; } diff --git a/common/core/src/main/java/is/codion/common/item/DefaultItem.java b/common/core/src/main/java/is/codion/common/item/DefaultItem.java index be6e50ae7c..d9f79e0387 100644 --- a/common/core/src/main/java/is/codion/common/item/DefaultItem.java +++ b/common/core/src/main/java/is/codion/common/item/DefaultItem.java @@ -18,6 +18,8 @@ */ package is.codion.common.item; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; @@ -32,7 +34,7 @@ final class DefaultItem extends AbstractItem implements Serializable { private final String caption; - DefaultItem(T value, String caption) { + DefaultItem(@Nullable T value, String caption) { super(value); this.caption = requireNonNull(caption, "Item caption may not be null"); } diff --git a/common/core/src/main/java/is/codion/common/item/Item.java b/common/core/src/main/java/is/codion/common/item/Item.java index 47dd6a0457..7f11909f27 100644 --- a/common/core/src/main/java/is/codion/common/item/Item.java +++ b/common/core/src/main/java/is/codion/common/item/Item.java @@ -18,6 +18,8 @@ */ package is.codion.common.item; +import org.jspecify.annotations.Nullable; + /** * A class encapsulating a constant value and a caption representing the value. * {@link Item}s equality is based on their values only. @@ -38,7 +40,7 @@ public interface Item { /** * @return the item value */ - T value(); + @Nullable T value(); /** * Returns an {@link Item}, with the caption as item.toString() or an empty string in case of a null value @@ -46,7 +48,7 @@ public interface Item { * @param the value type * @return an {@link Item} based on the given value */ - static Item item(T value) { + static Item item(@Nullable T value) { if (value == null) { return (Item) DefaultItem.NULL_ITEM; } @@ -62,7 +64,7 @@ static Item item(T value) { * @return an {@link Item} based on the given value and caption * @throws NullPointerException if caption is null */ - static Item item(T value, String caption) { + static Item item(@Nullable T value, String caption) { return new DefaultItem<>(value, caption); } @@ -76,7 +78,7 @@ static Item item(T value, String caption) { * @param the value type * @return an Item based on the given value and resource bundle */ - static Item itemI18n(T value, String resourceBundleName, String resourceBundleKey) { + static Item itemI18n(@Nullable T value, String resourceBundleName, String resourceBundleKey) { return new ItemI18n<>(value, resourceBundleName, resourceBundleKey); } } diff --git a/common/core/src/main/java/is/codion/common/item/ItemI18n.java b/common/core/src/main/java/is/codion/common/item/ItemI18n.java index 80a5f2c79b..028bb33e5a 100644 --- a/common/core/src/main/java/is/codion/common/item/ItemI18n.java +++ b/common/core/src/main/java/is/codion/common/item/ItemI18n.java @@ -18,6 +18,8 @@ */ package is.codion.common.item; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; @@ -32,9 +34,9 @@ final class ItemI18n extends AbstractItem implements Serializable { private final String resourceBundleName; private final String resourceBundleKey; - private transient String caption; + private transient @Nullable String caption; - ItemI18n(T value, String resourceBundleName, String resourceBundleKey) { + ItemI18n(@Nullable T value, String resourceBundleName, String resourceBundleKey) { super(value); getBundle(requireNonNull(resourceBundleName)).getString(requireNonNull(resourceBundleKey)); this.resourceBundleName = resourceBundleName; diff --git a/common/core/src/main/java/is/codion/common/item/package-info.java b/common/core/src/main/java/is/codion/common/item/package-info.java new file mode 100644 index 0000000000..356d8a8892 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/item/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

See {@link is.codion.common.item.Item}. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.item; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/logging/DefaultMethodLogger.java b/common/core/src/main/java/is/codion/common/logging/DefaultMethodLogger.java index 29420798bd..a01b1a44c9 100644 --- a/common/core/src/main/java/is/codion/common/logging/DefaultMethodLogger.java +++ b/common/core/src/main/java/is/codion/common/logging/DefaultMethodLogger.java @@ -20,6 +20,8 @@ import is.codion.common.Text; +import org.jspecify.annotations.Nullable; + import java.io.PrintWriter; import java.io.Serial; import java.io.Serializable; @@ -71,17 +73,17 @@ public synchronized void enter(String method, Object argument) { } @Override - public Entry exit(String method) { + public @Nullable Entry exit(String method) { return exit(method, null); } @Override - public Entry exit(String method, Exception exception) { + public @Nullable Entry exit(String method, @Nullable Exception exception) { return exit(method, exception, null); } @Override - public synchronized Entry exit(String method, Exception exception, String exitMessage) { + public synchronized @Nullable Entry exit(String method, @Nullable Exception exception, @Nullable String exitMessage) { if (!enabled) { return null; } @@ -141,20 +143,20 @@ private static final class DefaultEntry implements Entry, Serializable { private final LinkedList childEntries = new LinkedList<>(); private final String method; - private final String enterMessage; + private final @Nullable String enterMessage; private final long enterTime; private final long enterTimeNano; - private String exitMessage; + private @Nullable String exitMessage; private long exitTime; private long exitTimeNano; - private String stackTrace; + private @Nullable String stackTrace; /** * Creates a new Entry, using the current time * @param method the method being logged * @param enterMessage the message associated with entering the method */ - private DefaultEntry(String method, String enterMessage) { + private DefaultEntry(String method, @Nullable String enterMessage) { this(method, enterMessage, currentTimeMillis(), nanoTime()); } @@ -165,8 +167,8 @@ private DefaultEntry(String method, String enterMessage) { * @param enterTime the time to associate with entering the method * @param enterTimeNano the nano time to associate with entering the method */ - private DefaultEntry(String method, String enterMessage, long enterTime, long enterTimeNano) { - this.method = method; + private DefaultEntry(String method, @Nullable String enterMessage, long enterTime, long enterTimeNano) { + this.method = requireNonNull(method); this.enterTime = enterTime; this.enterTimeNano = enterTimeNano; this.enterMessage = enterMessage; @@ -183,7 +185,7 @@ public String method() { } @Override - public String enterMessage() { + public @Nullable String enterMessage() { return enterMessage; } @@ -243,7 +245,7 @@ private void setExitTime() { /** * @param exception the exception that occurred during the method call logged by this entry */ - private void setException(Exception exception) { + private void setException(@Nullable Exception exception) { if (exception != null) { stackTrace = stackTrace(exception); } @@ -252,7 +254,7 @@ private void setException(Exception exception) { /** * @param exitMessage the exit message */ - private void setExitMessage(String exitMessage) { + private void setExitMessage(@Nullable String exitMessage) { this.exitMessage = exitMessage; } diff --git a/common/core/src/main/java/is/codion/common/logging/MethodLogger.java b/common/core/src/main/java/is/codion/common/logging/MethodLogger.java index 22e4b6b136..2fe50447b3 100644 --- a/common/core/src/main/java/is/codion/common/logging/MethodLogger.java +++ b/common/core/src/main/java/is/codion/common/logging/MethodLogger.java @@ -18,6 +18,8 @@ */ package is.codion.common.logging; +import org.jspecify.annotations.Nullable; + import java.util.Collection; import java.util.List; @@ -46,14 +48,14 @@ public interface MethodLogger { * @param method the method being exited * @return the Entry */ - Entry exit(String method); + @Nullable Entry exit(String method); /** * @param method the method being exited * @param exception the exception, if any * @return the Entry */ - Entry exit(String method, Exception exception); + @Nullable Entry exit(String method, @Nullable Exception exception); /** * @param method the method being exited @@ -61,7 +63,7 @@ public interface MethodLogger { * @param exitMessage the message to associate with exiting the method * @return the Entry, or null if this logger is not enabled */ - Entry exit(String method, Exception exception, String exitMessage); + @Nullable Entry exit(String method, @Nullable Exception exception, @Nullable String exitMessage); /** * @return true if this logger is enabled @@ -115,7 +117,7 @@ interface Entry { /** * @return the entry message */ - String enterMessage(); + @Nullable String enterMessage(); /** * Returns the duration of the method call this entry represents in nanoseconds, diff --git a/common/core/src/main/java/is/codion/common/logging/package-info.java b/common/core/src/main/java/is/codion/common/logging/package-info.java new file mode 100644 index 0000000000..eda54870da --- /dev/null +++ b/common/core/src/main/java/is/codion/common/logging/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Logging related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.logging; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/observer/Mutable.java b/common/core/src/main/java/is/codion/common/observer/Mutable.java index f6ac7b4110..245eff5a92 100644 --- a/common/core/src/main/java/is/codion/common/observer/Mutable.java +++ b/common/core/src/main/java/is/codion/common/observer/Mutable.java @@ -18,6 +18,8 @@ */ package is.codion.common.observer; +import org.jspecify.annotations.Nullable; + /** * A wrapper for a mutable value, providing a change observer. *

@@ -68,7 +70,7 @@ public interface Mutable extends Observable {
 	 * Sets the value
 	 * @param value the value to set
 	 */
-	void set(T value);
+	void set(@Nullable T value);
 
 	/**
 	 * Clears this {@link Mutable} instance by setting the value to null
diff --git a/common/core/src/main/java/is/codion/common/observer/Observable.java b/common/core/src/main/java/is/codion/common/observer/Observable.java
index 445b8079f5..4495bb7b84 100644
--- a/common/core/src/main/java/is/codion/common/observer/Observable.java
+++ b/common/core/src/main/java/is/codion/common/observer/Observable.java
@@ -18,6 +18,8 @@
  */
 package is.codion.common.observer;
 
+import org.jspecify.annotations.Nullable;
+
 import java.util.Optional;
 import java.util.function.Consumer;
 
@@ -65,7 +67,7 @@ public interface Observable extends Observer {
 	/**
 	 * @return the value
 	 */
-	T get();
+	@Nullable T get();
 
 	/**
 	 * @return an Optional based on the current value
diff --git a/common/core/src/main/java/is/codion/common/observer/package-info.java b/common/core/src/main/java/is/codion/common/observer/package-info.java
new file mode 100644
index 0000000000..6ec87818be
--- /dev/null
+++ b/common/core/src/main/java/is/codion/common/observer/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * This file is part of Codion.
+ *
+ * Codion is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Codion is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codion.  If not, see .
+ *
+ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson.
+ */
+/**
+ * 

{@link is.codion.common.observer.Observer}, {@link is.codion.common.observer.Observable} and {@link is.codion.common.observer.Mutable}. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.observer; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/package-info.java b/common/core/src/main/java/is/codion/common/package-info.java index 701349218e..83091b2ad8 100644 --- a/common/core/src/main/java/is/codion/common/package-info.java +++ b/common/core/src/main/java/is/codion/common/package-info.java @@ -17,9 +17,11 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

Common classes. + *

Package configuration values: *

    *
  • {@link is.codion.common.Text#DEFAULT_COLLATOR_LANGUAGE} *
*/ +@org.jspecify.annotations.NullMarked package is.codion.common; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/property/DefaultPropertyStore.java b/common/core/src/main/java/is/codion/common/property/DefaultPropertyStore.java index 46fe36c0ec..9769af428a 100644 --- a/common/core/src/main/java/is/codion/common/property/DefaultPropertyStore.java +++ b/common/core/src/main/java/is/codion/common/property/DefaultPropertyStore.java @@ -20,6 +20,8 @@ import is.codion.common.value.AbstractValue; +import org.jspecify.annotations.Nullable; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -132,7 +134,7 @@ public PropertyValue characterValue(String propertyName, char default @Override public PropertyValue stringValue(String propertyName) { - return stringValue(propertyName, null); + return value(propertyName, Objects::toString, Objects::toString); } @Override @@ -142,7 +144,9 @@ public PropertyValue stringValue(String propertyName, String defaultValu @Override public > PropertyValue enumValue(String propertyName, Class enumClass) { - return enumValue(propertyName, enumClass, null); + requireNonNull(enumClass); + + return value(propertyName, value -> Enum.valueOf(enumClass, value.toUpperCase()), Objects::toString); } @Override @@ -154,7 +158,7 @@ public > PropertyValue enumValue(String propertyName, Class @Override public PropertyValue> listValue(String propertyName, Function decoder, Function encoder) { - return listValue(propertyName, decoder, encoder, emptyList()); + return value(propertyName, new ListValueDecoder<>(decoder), new ListValueEncoder<>(encoder), emptyList()); } @Override @@ -164,7 +168,13 @@ public PropertyValue> listValue(String propertyName, Function PropertyValue value(String propertyName, Function decoder, Function encoder) { - return value(propertyName, decoder, encoder, null); + if (propertyValues.containsKey(requireNonNull(propertyName))) { + throw new IllegalStateException("A value has already been created for the property '" + propertyName + "'"); + } + DefaultPropertyValue value = new DefaultPropertyValue<>(propertyName, decoder, encoder); + propertyValues.put(propertyName, value); + + return value; } @Override @@ -184,7 +194,7 @@ public Optional> propertyValue(String propertyName) { } @Override - public void setProperty(String propertyName, String value) { + public void setProperty(String propertyName, @Nullable String value) { if (propertyValues.containsKey(requireNonNull(propertyName))) { throw new IllegalArgumentException("Value bound properties can only be modified through their Value instances"); } @@ -273,10 +283,17 @@ private final class DefaultPropertyValue extends AbstractValue implements private final String propertyName; private final Function encoder; - private T value; + private @Nullable T value; + + private DefaultPropertyValue(String propertyName, Function decoder, Function encoder) { + super(null, Notify.WHEN_CHANGED); + this.propertyName = requireNonNull(propertyName); + this.encoder = requireNonNull(encoder); + set(getInitialValue(propertyName, requireNonNull(decoder))); + } private DefaultPropertyValue(String propertyName, Function decoder, Function encoder, T defaultValue) { - super(defaultValue, Notify.WHEN_CHANGED); + super(requireNonNull(defaultValue), Notify.WHEN_CHANGED); this.propertyName = requireNonNull(propertyName); this.encoder = requireNonNull(encoder); set(getInitialValue(propertyName, requireNonNull(decoder))); @@ -307,12 +324,12 @@ public String toString() { } @Override - protected T getValue() { + protected @Nullable T getValue() { return value; } @Override - protected void setValue(T value) { + protected void setValue(@Nullable T value) { this.value = value; if (value == null) { properties.remove(propertyName); @@ -324,7 +341,7 @@ protected void setValue(T value) { } } - private T getInitialValue(String property, Function decoder) { + private @Nullable T getInitialValue(String property, Function decoder) { String initialValue = System.getProperty(property); if (initialValue == null) { initialValue = properties.getProperty(property); @@ -343,7 +360,7 @@ private ListValueDecoder(Function decoder) { } @Override - public List apply(String stringValue) { + public List apply(@Nullable String stringValue) { return stringValue == null ? emptyList() : Arrays.stream(stringValue.split(VALUE_SEPARATOR)) .map(decoder) .collect(toList()); diff --git a/common/core/src/main/java/is/codion/common/property/PropertyStore.java b/common/core/src/main/java/is/codion/common/property/PropertyStore.java index 057df68467..8685b098fc 100644 --- a/common/core/src/main/java/is/codion/common/property/PropertyStore.java +++ b/common/core/src/main/java/is/codion/common/property/PropertyStore.java @@ -20,6 +20,8 @@ import is.codion.common.property.DefaultPropertyStore.DefaultSystemPropertyFormatter; +import org.jspecify.annotations.Nullable; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -249,7 +251,7 @@ public interface PropertyStore { * @param value the value * @throws IllegalArgumentException if the property is value bound */ - void setProperty(String propertyName, String value); + void setProperty(String propertyName, @Nullable String value); /** * Retrieves the value for the given property, null if no value is present diff --git a/common/core/src/main/java/is/codion/common/property/package-info.java b/common/core/src/main/java/is/codion/common/property/package-info.java new file mode 100644 index 0000000000..df4f4cd397 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/property/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Propery related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.property; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/proxy/DefaultProxyBuilder.java b/common/core/src/main/java/is/codion/common/proxy/DefaultProxyBuilder.java index 1e2113392f..09644a4d2e 100644 --- a/common/core/src/main/java/is/codion/common/proxy/DefaultProxyBuilder.java +++ b/common/core/src/main/java/is/codion/common/proxy/DefaultProxyBuilder.java @@ -18,6 +18,8 @@ */ package is.codion.common.proxy; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -38,7 +40,7 @@ final class DefaultProxyBuilder implements ProxyBuilder { private final Map> methodMap = new HashMap<>(); private final Class interfaceToProxy; - private T delegate; + private @Nullable T delegate; DefaultProxyBuilder(Class interfaceToProxy) { if (!requireNonNull(interfaceToProxy).isInterface()) { @@ -119,15 +121,15 @@ private static final class DefaultHandler implements InvocationHandler { private static final String EQUALS = "equals"; private final Map> methodMap; - private final T delegate; + private final @Nullable T delegate; - private DefaultHandler(Map> methodMap, T delegate) { + private DefaultHandler(Map> methodMap, @Nullable T delegate) { this.methodMap = methodMap; this.delegate = delegate; } @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { ProxyMethod proxyMethod = methodMap.get(new MethodKey(method)); if (proxyMethod != null) { return proxyMethod.invoke(new DefaultProxyMethodParameters<>((T) proxy, delegate, args)); @@ -157,10 +159,10 @@ private static boolean isEqualsMethod(Method method) { private static final class DefaultProxyMethodParameters implements ProxyMethod.Parameters { private final T proxy; - private final T delegate; + private final @Nullable T delegate; private final List arguments; - private DefaultProxyMethodParameters(T proxy, T delegate, Object[] arguments) { + private DefaultProxyMethodParameters(T proxy, @Nullable T delegate, @Nullable Object[] arguments) { this.proxy = requireNonNull(proxy); this.delegate = delegate; this.arguments = arguments == null ? emptyList() : unmodifiableList(Arrays.asList(arguments)); diff --git a/common/core/src/main/java/is/codion/common/proxy/ProxyBuilder.java b/common/core/src/main/java/is/codion/common/proxy/ProxyBuilder.java index 50b3ed4198..a949168552 100644 --- a/common/core/src/main/java/is/codion/common/proxy/ProxyBuilder.java +++ b/common/core/src/main/java/is/codion/common/proxy/ProxyBuilder.java @@ -18,6 +18,8 @@ */ package is.codion.common.proxy; +import org.jspecify.annotations.Nullable; + import java.util.List; /** @@ -109,10 +111,10 @@ interface ProxyMethod { /** * Invokes this proxy method. * @param parameters the parameters - * @return the result + * @return the result, may be null * @throws Throwable in case of an exception */ - Object invoke(Parameters parameters) throws Throwable; + @Nullable Object invoke(Parameters parameters) throws Throwable; /** * Parameters available to the invocation handler when calling a proxy method. diff --git a/common/core/src/main/java/is/codion/common/proxy/package-info.java b/common/core/src/main/java/is/codion/common/proxy/package-info.java new file mode 100644 index 0000000000..81905fc653 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/proxy/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Dynamic proxy related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.proxy; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/resource/package-info.java b/common/core/src/main/java/is/codion/common/resource/package-info.java new file mode 100644 index 0000000000..02ae140d87 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/resource/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2024, Björn Darri Sigurðsson. + */ +/** + *

Resource bundle related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.resource; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/scheduler/DefaultTaskScheduler.java b/common/core/src/main/java/is/codion/common/scheduler/DefaultTaskScheduler.java index 2c39816d27..5b733627a4 100644 --- a/common/core/src/main/java/is/codion/common/scheduler/DefaultTaskScheduler.java +++ b/common/core/src/main/java/is/codion/common/scheduler/DefaultTaskScheduler.java @@ -21,6 +21,8 @@ import is.codion.common.value.Value; import is.codion.common.value.Value.Validator; +import org.jspecify.annotations.Nullable; + import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; @@ -39,7 +41,7 @@ final class DefaultTaskScheduler implements TaskScheduler { private final TimeUnit timeUnit; private final ThreadFactory threadFactory; - private ScheduledExecutorService executorService; + private @Nullable ScheduledExecutorService executorService; private DefaultTaskScheduler(DefaultBuilder builder) { this.task = builder.task; @@ -68,7 +70,7 @@ public DefaultTaskScheduler start() { synchronized (lock) { stop(); executorService = Executors.newSingleThreadScheduledExecutor(threadFactory); - executorService.scheduleAtFixedRate(task, initialDelay, interval.get(), timeUnit); + executorService.scheduleAtFixedRate(task, initialDelay, interval.getOrThrow(), timeUnit); return this; } @@ -77,7 +79,7 @@ public DefaultTaskScheduler start() { @Override public void stop() { synchronized (lock) { - if (running()) { + if (running() && executorService != null) { executorService.shutdownNow(); executorService = null; } @@ -105,7 +107,7 @@ static final class DefaultBuilder implements Builder { private int interval; private int initialDelay; - private TimeUnit timeUnit; + private @Nullable TimeUnit timeUnit; private ThreadFactory threadFactory = new DaemonThreadFactory(); DefaultBuilder(Runnable task) { diff --git a/common/core/src/main/java/is/codion/common/scheduler/package-info.java b/common/core/src/main/java/is/codion/common/scheduler/package-info.java new file mode 100644 index 0000000000..4e305caf88 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/scheduler/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

Task scheduling related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.scheduler; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/state/DefaultState.java b/common/core/src/main/java/is/codion/common/state/DefaultState.java index 004706c4fb..665da57f88 100644 --- a/common/core/src/main/java/is/codion/common/state/DefaultState.java +++ b/common/core/src/main/java/is/codion/common/state/DefaultState.java @@ -21,6 +21,8 @@ import is.codion.common.value.Value; import is.codion.common.value.ValueObserver; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; import java.util.function.Function; @@ -28,7 +30,7 @@ final class DefaultState implements State { private final Value value; - private DefaultStateObserver observer; + private @Nullable DefaultStateObserver observer; private DefaultState(Value.Builder valueBuilder) { this.value = valueBuilder.consumer(new Notifier()).build(); @@ -36,18 +38,18 @@ private DefaultState(Value.Builder valueBuilder) { @Override public String toString() { - return Boolean.toString(value.get()); + return Boolean.toString(value.getOrThrow()); } @Override public Boolean get() { synchronized (this.value) { - return this.value.get(); + return this.value.getOrThrow(); } } @Override - public boolean set(Boolean value) { + public boolean set(@Nullable Boolean value) { synchronized (this.value) { return this.value.set(value); } @@ -193,7 +195,7 @@ static final class DefaultBuilder implements Builder { } @Override - public Builder value(Boolean value) { + public Builder value(@Nullable Boolean value) { valueBuilder.value(value); return this; } diff --git a/common/core/src/main/java/is/codion/common/state/DefaultStateCombination.java b/common/core/src/main/java/is/codion/common/state/DefaultStateCombination.java index 720d7880e7..70e549ec6c 100644 --- a/common/core/src/main/java/is/codion/common/state/DefaultStateCombination.java +++ b/common/core/src/main/java/is/codion/common/state/DefaultStateCombination.java @@ -20,6 +20,8 @@ import is.codion.common.Conjunction; +import org.jspecify.annotations.Nullable; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -158,7 +160,7 @@ public boolean removeWeakConsumer(Consumer consumer) { return observer.removeWeakConsumer(consumer); } - private boolean get(Conjunction conjunction, StateObserver exclude, boolean excludeReplacement) { + private boolean get(Conjunction conjunction, @Nullable StateObserver exclude, boolean excludeReplacement) { for (StateCombinationConsumer listener : stateListeners) { StateObserver state = listener.state; boolean value = state.equals(exclude) ? excludeReplacement : state.get(); diff --git a/common/core/src/main/java/is/codion/common/state/DefaultStateGroup.java b/common/core/src/main/java/is/codion/common/state/DefaultStateGroup.java index cceb50c31f..1e81d3d0bd 100644 --- a/common/core/src/main/java/is/codion/common/state/DefaultStateGroup.java +++ b/common/core/src/main/java/is/codion/common/state/DefaultStateGroup.java @@ -20,6 +20,8 @@ import is.codion.common.value.ValueObserver; +import org.jspecify.annotations.Nullable; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -31,7 +33,7 @@ final class DefaultStateGroup implements State.Group { private final List members = new ArrayList<>(); - private State previousState; + private @Nullable State previousState; private boolean disablingStates = false; DefaultStateGroup(State... states) { @@ -98,7 +100,7 @@ else if (members.size() > 1) { previousState = current; } - private State previousState(State current) { + private @Nullable State previousState(State current) { return members.stream() .filter(state -> state != current) .filter(ValueObserver::get) diff --git a/common/core/src/main/java/is/codion/common/state/DefaultStateObserver.java b/common/core/src/main/java/is/codion/common/state/DefaultStateObserver.java index 669b3c4eeb..aa1e5016db 100644 --- a/common/core/src/main/java/is/codion/common/state/DefaultStateObserver.java +++ b/common/core/src/main/java/is/codion/common/state/DefaultStateObserver.java @@ -21,6 +21,8 @@ import is.codion.common.event.Event; import is.codion.common.observer.Observer; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; import static java.util.Objects.requireNonNull; @@ -31,8 +33,8 @@ final class DefaultStateObserver implements StateObserver { private final StateObserver observedState; private final boolean not; - private Event stateChangedEvent; - private DefaultStateObserver notObserver; + private @Nullable Event stateChangedEvent; + private @Nullable DefaultStateObserver notObserver; DefaultStateObserver(StateObserver observedState, boolean not) { this.observedState = requireNonNull(observedState); diff --git a/common/core/src/main/java/is/codion/common/state/State.java b/common/core/src/main/java/is/codion/common/state/State.java index f176026a26..3a3f0ea3cf 100644 --- a/common/core/src/main/java/is/codion/common/state/State.java +++ b/common/core/src/main/java/is/codion/common/state/State.java @@ -21,6 +21,8 @@ import is.codion.common.Conjunction; import is.codion.common.value.Value; +import org.jspecify.annotations.NonNull; + import java.util.Collection; /** @@ -44,6 +46,9 @@ */ public interface State extends StateObserver, Value { + @Override + @NonNull Boolean get(); + /** * Returns a {@link StateObserver} notified each time the state changes * @return a {@link StateObserver} notified each time the state changes diff --git a/common/core/src/main/java/is/codion/common/state/StateObserver.java b/common/core/src/main/java/is/codion/common/state/StateObserver.java index 55511e7779..e93f486d5a 100644 --- a/common/core/src/main/java/is/codion/common/state/StateObserver.java +++ b/common/core/src/main/java/is/codion/common/state/StateObserver.java @@ -20,11 +20,16 @@ import is.codion.common.value.ValueObserver; +import org.jspecify.annotations.NonNull; + /** * Specifies an observer for a {@link State} instance. */ public interface StateObserver extends ValueObserver { + @Override + @NonNull Boolean get(); + /** * @return false */ diff --git a/common/core/src/main/java/is/codion/common/state/package-info.java b/common/core/src/main/java/is/codion/common/state/package-info.java new file mode 100644 index 0000000000..4722eabb7e --- /dev/null +++ b/common/core/src/main/java/is/codion/common/state/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

See {@link is.codion.common.state.State} and {@link is.codion.common.state.StateObserver}. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.state; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/user/DefaultUser.java b/common/core/src/main/java/is/codion/common/user/DefaultUser.java index f4651ed01c..568d56cad3 100644 --- a/common/core/src/main/java/is/codion/common/user/DefaultUser.java +++ b/common/core/src/main/java/is/codion/common/user/DefaultUser.java @@ -18,6 +18,8 @@ */ package is.codion.common.user; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -35,7 +37,7 @@ final class DefaultUser implements User, Serializable { private String username; private char[] password; - DefaultUser(String username, char[] password) { + DefaultUser(String username, char @Nullable[] password) { if (requireNonNull(username).isEmpty()) { throw new IllegalArgumentException("Username must be non-empty"); } @@ -95,7 +97,7 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo this.password = createPassword((char[]) stream.readObject()); } - private static char[] createPassword(char[] password) { + private static char[] createPassword(char @Nullable[] password) { return password == null ? new char[0] : Arrays.copyOf(password, password.length); } } diff --git a/common/core/src/main/java/is/codion/common/user/User.java b/common/core/src/main/java/is/codion/common/user/User.java index 30cd71adaa..9489f82d20 100644 --- a/common/core/src/main/java/is/codion/common/user/User.java +++ b/common/core/src/main/java/is/codion/common/user/User.java @@ -18,6 +18,8 @@ */ package is.codion.common.user; +import org.jspecify.annotations.Nullable; + import static java.util.Objects.requireNonNull; /** @@ -68,7 +70,7 @@ static User user(String username) { * @return a new User * @throws IllegalArgumentException in case username is an empty string */ - static User user(String username, char[] password) { + static User user(String username, char @Nullable[] password) { return new DefaultUser(username, password); } diff --git a/common/core/src/main/java/is/codion/common/user/package-info.java b/common/core/src/main/java/is/codion/common/user/package-info.java new file mode 100644 index 0000000000..b7ee81ea5c --- /dev/null +++ b/common/core/src/main/java/is/codion/common/user/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

See {@link is.codion.common.user.User}. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.user; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/value/AbstractValue.java b/common/core/src/main/java/is/codion/common/value/AbstractValue.java index df5817e136..2c4fdb82a5 100644 --- a/common/core/src/main/java/is/codion/common/value/AbstractValue.java +++ b/common/core/src/main/java/is/codion/common/value/AbstractValue.java @@ -20,6 +20,8 @@ import is.codion.common.event.Event; +import org.jspecify.annotations.Nullable; + import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -46,14 +48,14 @@ */ public abstract class AbstractValue implements Value { - private final T nullValue; - private final Notify notify; + private final @Nullable T nullValue; + private final @Nullable Notify notify; - private Event notifier; - private Set> validators; - private Map, ValueLink> linkedValues; - private Map, ValueObserverLink> linkedObservers; - private ValueObserver observer; + private @Nullable Event notifier; + private @Nullable Set> validators; + private @Nullable Map, ValueLink> linkedValues; + private @Nullable Map, ValueObserverLink> linkedObservers; + private @Nullable ValueObserver observer; /** * Creates a {@link AbstractValue} instance, which does not notify listeners. @@ -66,7 +68,7 @@ protected AbstractValue() { * Creates a {@link AbstractValue} instance, which does not notify listeners. * @param nullValue the value to use instead of null */ - protected AbstractValue(T nullValue) { + protected AbstractValue(@Nullable T nullValue) { this.nullValue = nullValue; this.notify = null; } @@ -76,18 +78,18 @@ protected AbstractValue(T nullValue) { * @param nullValue the value to use instead of null * @param notify specifies when to notify listeners */ - protected AbstractValue(T nullValue, Notify notify) { + protected AbstractValue(@Nullable T nullValue, Notify notify) { this.nullValue = nullValue; this.notify = requireNonNull(notify); } @Override - public final T get() { + public final @Nullable T get() { return getValue(); } @Override - public final boolean set(T value) { + public final boolean set(@Nullable T value) { T newValue = value == null ? nullValue : value; for (Validator validator : validators()) { validator.validate(newValue); @@ -123,7 +125,7 @@ public final boolean nullable() { } @Override - public final void accept(T data) { + public final void accept(@Nullable T data) { set(data); } @@ -134,6 +136,7 @@ public final boolean addListener(Runnable listener) { @Override public final boolean removeListener(Runnable listener) { + requireNonNull(listener); if (notifier != null) { return notifier.removeListener(listener); } @@ -148,6 +151,7 @@ public final boolean addConsumer(Consumer consumer) { @Override public final boolean removeConsumer(Consumer consumer) { + requireNonNull(consumer); if (notifier != null) { return notifier.removeConsumer(consumer); } @@ -162,6 +166,7 @@ public final boolean addWeakListener(Runnable listener) { @Override public final boolean removeWeakListener(Runnable listener) { + requireNonNull(listener); if (notifier != null) { return notifier.removeWeakListener(listener); } @@ -176,6 +181,7 @@ public final boolean addWeakConsumer(Consumer consumer) { @Override public final boolean removeWeakConsumer(Consumer consumer) { + requireNonNull(consumer); if (notifier != null) { return notifier.removeWeakConsumer(consumer); } @@ -250,7 +256,7 @@ public final boolean removeValidator(Validator validator) { } @Override - public final void validate(T value) { + public final void validate(@Nullable T value) { validators().forEach(validator -> validator.validate(value)); } @@ -258,13 +264,13 @@ public final void validate(T value) { * Returns the actual internal value. * @return the value */ - protected abstract T getValue(); + protected abstract @Nullable T getValue(); /** * Sets the actual internal value. * @param value the value */ - protected abstract void setValue(T value); + protected abstract void setValue(@Nullable T value); /** * Notifies listeners that the underlying value has changed or at least that it may have changed diff --git a/common/core/src/main/java/is/codion/common/value/DefaultValue.java b/common/core/src/main/java/is/codion/common/value/DefaultValue.java index 5cf2046b90..32ef8189f9 100644 --- a/common/core/src/main/java/is/codion/common/value/DefaultValue.java +++ b/common/core/src/main/java/is/codion/common/value/DefaultValue.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.Nullable; + import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -28,7 +30,7 @@ class DefaultValue extends AbstractValue { protected final Object lock = new Object(); - private T value; + private @Nullable T value; protected DefaultValue(DefaultBuilder builder) { super(builder.nullValue, builder.notify); @@ -43,12 +45,12 @@ protected DefaultValue(DefaultBuilder builder) { } @Override - protected final T getValue() { + protected final @Nullable T getValue() { return value; } @Override - protected final void setValue(T value) { + protected final void setValue(@Nullable T value) { this.value = value; } @@ -65,7 +67,7 @@ static final class DefaultBuilderFactory implements BuilderFactory { } @Override - public Builder nullable(T value) { + public Builder nullable(@Nullable T value) { return (Builder) new DefaultBuilder<>() .value(value); } @@ -73,7 +75,7 @@ static final class DefaultBuilderFactory implements BuilderFactory { static class DefaultBuilder> implements Builder { - private final T nullValue; + private final @Nullable T nullValue; private final List> validators = new ArrayList<>(); private final List> linkedValues = new ArrayList<>(); private final List> linkedObservers = new ArrayList<>(); @@ -82,7 +84,7 @@ static class DefaultBuilder> implements Builder private final List> consumers = new ArrayList<>(); private final List> weakConsumers = new ArrayList<>(); - private T value; + private @Nullable T value; private Notify notify = Notify.WHEN_CHANGED; DefaultBuilder() { @@ -95,7 +97,7 @@ static class DefaultBuilder> implements Builder } @Override - public final B value(T value) { + public final B value(@Nullable T value) { this.value = value; return self(); } @@ -156,7 +158,7 @@ public Value build() { /** * @return the initial value */ - protected T prepareInitialValue() { + protected @Nullable T prepareInitialValue() { return value == null ? nullValue : value; } diff --git a/common/core/src/main/java/is/codion/common/value/DefaultValueObserver.java b/common/core/src/main/java/is/codion/common/value/DefaultValueObserver.java index e738260e4d..25ab146964 100644 --- a/common/core/src/main/java/is/codion/common/value/DefaultValueObserver.java +++ b/common/core/src/main/java/is/codion/common/value/DefaultValueObserver.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; import static java.util.Objects.requireNonNull; @@ -31,7 +33,7 @@ class DefaultValueObserver implements ValueObserver { } @Override - public final T get() { + public final @Nullable T get() { return value.get(); } diff --git a/common/core/src/main/java/is/codion/common/value/DefaultValues.java b/common/core/src/main/java/is/codion/common/value/DefaultValues.java index 09c839d36e..9e306fda29 100644 --- a/common/core/src/main/java/is/codion/common/value/DefaultValues.java +++ b/common/core/src/main/java/is/codion/common/value/DefaultValues.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.Nullable; + import java.util.Collection; import java.util.Iterator; import java.util.function.Function; @@ -34,7 +36,7 @@ class DefaultValues> extends DefaultValue private final Supplier create; private final Function unmodifiable; - private Value singleValue; + private @Nullable Value singleValue; DefaultValues(DefaultBuilder builder) { super(builder); @@ -44,11 +46,11 @@ class DefaultValues> extends DefaultValue @Override public final Iterator iterator() { - return get().iterator(); + return getOrThrow().iterator(); } @Override - public final boolean set(Collection values) { + public final boolean set(@Nullable Collection values) { synchronized (lock) { C newValues = create.get(); if (values != null) { @@ -60,10 +62,10 @@ public final boolean set(Collection values) { } @Override - public final boolean add(T value) { + public final boolean add(@Nullable T value) { synchronized (lock) { C newValues = create.get(); - newValues.addAll(get()); + newValues.addAll(getOrThrow()); boolean added = newValues.add(value); set(unmodifiable.apply(newValues)); @@ -81,7 +83,7 @@ public final boolean addAll(Collection values) { requireNonNull(values); synchronized (lock) { C newValues = create.get(); - newValues.addAll(get()); + newValues.addAll(getOrThrow()); boolean added = newValues.addAll(values); set(unmodifiable.apply(newValues)); @@ -90,10 +92,10 @@ public final boolean addAll(Collection values) { } @Override - public final boolean remove(T value) { + public final boolean remove(@Nullable T value) { synchronized (lock) { C newValues = create.get(); - newValues.addAll(get()); + newValues.addAll(getOrThrow()); boolean removed = newValues.remove(value); set(unmodifiable.apply(newValues)); @@ -111,7 +113,7 @@ public final boolean removeAll(Collection values) { requireNonNull(values); synchronized (lock) { C newValues = create.get(); - newValues.addAll(get()); + newValues.addAll(getOrThrow()); boolean removed = newValues.removeAll(values); set(unmodifiable.apply(newValues)); @@ -122,7 +124,7 @@ public final boolean removeAll(Collection values) { @Override public final boolean contains(T value) { synchronized (lock) { - return get().contains(value); + return getOrThrow().contains(value); } } @@ -130,14 +132,14 @@ public final boolean contains(T value) { public final boolean containsAll(Collection values) { requireNonNull(values); synchronized (lock) { - return get().containsAll(values); + return getOrThrow().containsAll(values); } } @Override public final boolean empty() { synchronized (lock) { - return get().isEmpty(); + return getOrThrow().isEmpty(); } } @@ -149,7 +151,7 @@ public final boolean notEmpty() { @Override public final int size() { synchronized (lock) { - return get().size(); + return getOrThrow().size(); } } @@ -187,14 +189,14 @@ private SingleValue() { } @Override - protected synchronized T getValue() { - C collection = DefaultValues.this.get(); + protected synchronized @Nullable T getValue() { + C collection = DefaultValues.this.getOrThrow(); return collection.isEmpty() ? null : collection.iterator().next(); } @Override - protected synchronized void setValue(T value) { + protected synchronized void setValue(@Nullable T value) { DefaultValues.this.set(value == null ? emptyList() : singleton(value)); } } diff --git a/common/core/src/main/java/is/codion/common/value/Value.java b/common/core/src/main/java/is/codion/common/value/Value.java index 95f0a2e47f..7324febd81 100755 --- a/common/core/src/main/java/is/codion/common/value/Value.java +++ b/common/core/src/main/java/is/codion/common/value/Value.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.Nullable; + import java.util.function.Consumer; import java.util.function.Function; @@ -80,7 +82,7 @@ enum Notify { * @see #addValidator(Validator) */ @Override - default void accept(T value) { + default void accept(@Nullable T value) { set(value); } @@ -91,7 +93,7 @@ default void accept(T value) { * @throws IllegalArgumentException in case the given value is invalid * @see #addValidator(Validator) */ - boolean set(T value); + boolean set(@Nullable T value); /** * Clears this value, by setting it to null or the null value in case this is a non-null value. @@ -192,7 +194,7 @@ static Value value() { * @param value the initial value * @return a Value for the given type */ - static Value value(T value) { + static Value value(@Nullable T value) { return builder() .nullable(value) .build(); @@ -228,7 +230,7 @@ interface BuilderFactory { * @param the value type * @return a builder for a nullable {@link Value} */ - Builder nullable(T value); + Builder nullable(@Nullable T value); } /** @@ -242,7 +244,7 @@ interface Builder> { * @param value the initial value * @return this builder instance */ - B value(T value); + B value(@Nullable T value); /** * @param notify the notify policy for this value, default {@link Notify#WHEN_CHANGED} @@ -314,6 +316,6 @@ interface Validator { * @param value the value to validate * @throws IllegalArgumentException in case of an invalid value */ - void validate(T value); + void validate(@Nullable T value); } } diff --git a/common/core/src/main/java/is/codion/common/value/ValueLink.java b/common/core/src/main/java/is/codion/common/value/ValueLink.java index 84f01bbddf..8e676e647a 100644 --- a/common/core/src/main/java/is/codion/common/value/ValueLink.java +++ b/common/core/src/main/java/is/codion/common/value/ValueLink.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.Nullable; + import java.util.Set; import java.util.function.Consumer; @@ -107,14 +109,14 @@ private static final class LinkedValidator implements Value.Validator { private final Value linkedValue; - private Value.Validator excluded; + private Value.@Nullable Validator excluded; private LinkedValidator(Value linkedValue) { this.linkedValue = linkedValue; } @Override - public void validate(T value) { + public void validate(@Nullable T value) { if (linkedValue instanceof AbstractValue) { ((AbstractValue) linkedValue).validators() .stream() diff --git a/common/core/src/main/java/is/codion/common/value/ValueObserver.java b/common/core/src/main/java/is/codion/common/value/ValueObserver.java index b38f759bb1..2e752274d1 100644 --- a/common/core/src/main/java/is/codion/common/value/ValueObserver.java +++ b/common/core/src/main/java/is/codion/common/value/ValueObserver.java @@ -20,6 +20,8 @@ import is.codion.common.observer.Observer; +import org.jspecify.annotations.Nullable; + import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; @@ -35,7 +37,7 @@ public interface ValueObserver extends Observer { /** * @return the value */ - T get(); + @Nullable T get(); /** * @return the value @@ -96,7 +98,7 @@ default boolean isNotNull() { * @param value the value * @return true if the underlying value is equal to the given one */ - default boolean isEqualTo(T value) { + default boolean isEqualTo(@Nullable T value) { return Objects.equals(get(), value); } @@ -105,7 +107,7 @@ default boolean isEqualTo(T value) { * @param value the value * @return true if the underlying value is NOT equal to the given one */ - default boolean isNotEqualTo(T value) { + default boolean isNotEqualTo(@Nullable T value) { return !isEqualTo(value); } } diff --git a/common/core/src/main/java/is/codion/common/value/Values.java b/common/core/src/main/java/is/codion/common/value/Values.java index 01adadcd72..ecee5601d5 100644 --- a/common/core/src/main/java/is/codion/common/value/Values.java +++ b/common/core/src/main/java/is/codion/common/value/Values.java @@ -18,6 +18,9 @@ */ package is.codion.common.value; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + import java.util.Collection; import java.util.function.Function; import java.util.function.Supplier; @@ -31,12 +34,15 @@ */ public interface Values> extends Value, ValuesObserver { + @Override + @NonNull C get(); + /** * Sets the values. * @param values the values to set * @return true if this {@link Values} instance changed */ - boolean set(Collection values); + boolean set(@Nullable Collection values); /** * Adds a value to this Values instance. @@ -44,7 +50,7 @@ public interface Values> extends Value, ValuesObse * @return true if the value was added * @see Collection#add(Object) */ - boolean add(T value); + boolean add(@Nullable T value); /** * Adds the given values to this Values instance. @@ -68,7 +74,7 @@ public interface Values> extends Value, ValuesObse * @return true if the value was removed * @see Collection#remove(Object) */ - boolean remove(T value); + boolean remove(@Nullable T value); /** * Removes the given values from this Values instance. diff --git a/common/core/src/main/java/is/codion/common/value/ValuesObserver.java b/common/core/src/main/java/is/codion/common/value/ValuesObserver.java index 7e5ea70113..273204229e 100644 --- a/common/core/src/main/java/is/codion/common/value/ValuesObserver.java +++ b/common/core/src/main/java/is/codion/common/value/ValuesObserver.java @@ -18,6 +18,8 @@ */ package is.codion.common.value; +import org.jspecify.annotations.NonNull; + import java.util.Collection; /** @@ -27,6 +29,9 @@ */ public interface ValuesObserver> extends ValueObserver, Iterable { + @Override + @NonNull C get(); + /** * Returns true if this {@link Values} instance contains the specified element * @param value the element diff --git a/common/core/src/main/java/is/codion/common/value/package-info.java b/common/core/src/main/java/is/codion/common/value/package-info.java new file mode 100644 index 0000000000..656b6659b8 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/value/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

{@link is.codion.common.value.Value} and related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.value; \ No newline at end of file diff --git a/common/core/src/main/java/is/codion/common/version/DefaultVersion.java b/common/core/src/main/java/is/codion/common/version/DefaultVersion.java index ff8a3a91fc..2c3b5eb68d 100644 --- a/common/core/src/main/java/is/codion/common/version/DefaultVersion.java +++ b/common/core/src/main/java/is/codion/common/version/DefaultVersion.java @@ -18,6 +18,8 @@ */ package is.codion.common.version; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.util.Objects; @@ -33,8 +35,8 @@ final class DefaultVersion implements Version, Serializable { private final int major; private final int minor; private final int patch; - private final String metadata; - private final String build; + private final @Nullable String metadata; + private final @Nullable String build; private DefaultVersion(DefaulBuilder builder) { this.major = builder.major; @@ -109,7 +111,7 @@ public int compareTo(Version version) { return result; } - private static int compareMetadata(String metadata, String toCompare) { + private static int compareMetadata(@Nullable String metadata, @Nullable String toCompare) { if (metadata != null && toCompare != null) { return metadata.compareToIgnoreCase(toCompare); } @@ -128,8 +130,8 @@ static final class DefaulBuilder implements Builder { private int major = 0; private int minor = 0; private int patch = 0; - private String metadata; - private String build; + private @Nullable String metadata; + private @Nullable String build; @Override public Builder major(int major) { @@ -159,13 +161,13 @@ public Builder patch(int patch) { } @Override - public Builder metadata(String metadata) { + public Builder metadata(@Nullable String metadata) { this.metadata = metadata; return this; } @Override - public Builder build(String build) { + public Builder build(@Nullable String build) { this.build = build; return this; } diff --git a/common/core/src/main/java/is/codion/common/version/Version.java b/common/core/src/main/java/is/codion/common/version/Version.java index ff3b29ddbd..d10f9cb346 100644 --- a/common/core/src/main/java/is/codion/common/version/Version.java +++ b/common/core/src/main/java/is/codion/common/version/Version.java @@ -18,6 +18,8 @@ */ package is.codion.common.version; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.io.InputStream; import java.util.Optional; @@ -88,13 +90,13 @@ interface Builder { * @param metadata the metadata version component * @return this builder instance */ - Builder metadata(String metadata); + Builder metadata(@Nullable String metadata); /** * @param build the build information version component * @return this builder instance */ - Builder build(String build); + Builder build(@Nullable String build); /** * @return a new {@link Version} instance based on this builder diff --git a/common/core/src/main/java/is/codion/common/version/package-info.java b/common/core/src/main/java/is/codion/common/version/package-info.java new file mode 100644 index 0000000000..890fda8dc8 --- /dev/null +++ b/common/core/src/main/java/is/codion/common/version/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2024, Björn Darri Sigurðsson. + */ +/** + *

See {@link is.codion.common.version.Version}. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.version; \ No newline at end of file diff --git a/common/core/src/main/java/module-info.java b/common/core/src/main/java/module-info.java index 9b686efbaf..5462bbfe76 100644 --- a/common/core/src/main/java/module-info.java +++ b/common/core/src/main/java/module-info.java @@ -17,7 +17,7 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Common classes used throughout, such as: + *

Common classes used throughout. *

    *
  • {@link is.codion.common.observer.Observer} *
  • {@link is.codion.common.observer.Observable} @@ -36,7 +36,9 @@ * @uses is.codion.common.logging.LoggerProxy * @uses is.codion.common.resource.Resources */ +@org.jspecify.annotations.NullMarked module is.codion.common.core { + requires transitive org.jspecify; exports is.codion.common; exports is.codion.common.event; exports is.codion.common.format; diff --git a/common/core/src/test/java/is/codion/common/NullsTest.java b/common/core/src/test/java/is/codion/common/NullsTest.java index d76d76d660..836879cec7 100644 --- a/common/core/src/test/java/is/codion/common/NullsTest.java +++ b/common/core/src/test/java/is/codion/common/NullsTest.java @@ -30,7 +30,7 @@ void nonNull() { assertTrue(Nulls.nonNull()); assertTrue(Nulls.nonNull(new Object[0])); assertTrue(Nulls.nonNull(1)); - assertFalse(Nulls.nonNull(null)); + assertFalse(Nulls.nonNull((Object[]) null)); assertFalse(Nulls.nonNull(1, null)); assertFalse(Nulls.nonNull(null, 1)); } diff --git a/common/db/src/main/java/is/codion/common/db/connection/DatabaseConnection.java b/common/db/src/main/java/is/codion/common/db/connection/DatabaseConnection.java index b3eb22d0a5..b7e0c5846a 100644 --- a/common/db/src/main/java/is/codion/common/db/connection/DatabaseConnection.java +++ b/common/db/src/main/java/is/codion/common/db/connection/DatabaseConnection.java @@ -23,6 +23,8 @@ import is.codion.common.logging.MethodLogger; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; + import java.sql.Connection; import java.sql.SQLException; @@ -67,7 +69,7 @@ public interface DatabaseConnection extends AutoCloseable { * until a non-null connection is set. * @param connection the JDBC connection */ - void setConnection(Connection connection); + void setConnection(@Nullable Connection connection); /** * Starts a transaction on this connection, to end the transaction use {@link #commitTransaction()} or {@link #rollbackTransaction()}. @@ -130,12 +132,12 @@ public interface DatabaseConnection extends AutoCloseable { /** * @param methodLogger the MethodLogger to use, null to disable method logging */ - void setMethodLogger(MethodLogger methodLogger); + void setMethodLogger(@Nullable MethodLogger methodLogger); /** * @return the MethodLogger being used, possibly null */ - MethodLogger getMethodLogger(); + @Nullable MethodLogger getMethodLogger(); /** * Constructs a new DatabaseConnection instance, based on the given Database and User diff --git a/common/db/src/main/java/is/codion/common/db/connection/DefaultDatabaseConnection.java b/common/db/src/main/java/is/codion/common/db/connection/DefaultDatabaseConnection.java index 302d11420c..0288cb3508 100644 --- a/common/db/src/main/java/is/codion/common/db/connection/DefaultDatabaseConnection.java +++ b/common/db/src/main/java/is/codion/common/db/connection/DefaultDatabaseConnection.java @@ -23,6 +23,8 @@ import is.codion.common.logging.MethodLogger; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; + import java.sql.Connection; import java.sql.SQLException; import java.util.Map; @@ -41,10 +43,10 @@ final class DefaultDatabaseConnection implements DatabaseConnection { private final User user; private final Database database; - private Connection connection; + private @Nullable Connection connection; private boolean transactionOpen = false; - private MethodLogger methodLogger; + private @Nullable MethodLogger methodLogger; /** * Constructs a new DefaultDatabaseConnection instance, initialized and ready for use. @@ -83,12 +85,12 @@ public User user() { } @Override - public void setMethodLogger(MethodLogger methodLogger) { + public void setMethodLogger(@Nullable MethodLogger methodLogger) { this.methodLogger = methodLogger; } @Override - public MethodLogger getMethodLogger() { + public @Nullable MethodLogger getMethodLogger() { return methodLogger; } @@ -123,15 +125,13 @@ public boolean valid() { } @Override - public void setConnection(Connection connection) { + public void setConnection(@Nullable Connection connection) { this.connection = connection; } @Override public Connection getConnection() { - verifyOpenConnection(); - - return connection; + return verifyOpenConnection(); } @Override @@ -144,7 +144,7 @@ public void startTransaction() { if (transactionOpen) { throw new IllegalStateException("Transaction already open"); } - verifyOpenConnection(); + connection = verifyOpenConnection(); logEntry("startTransaction"); transactionOpen = true; logExit("startTransaction", null); @@ -155,7 +155,7 @@ public void rollbackTransaction() throws SQLException { if (!transactionOpen) { throw new IllegalStateException("Transaction is not open"); } - verifyOpenConnection(); + connection = verifyOpenConnection(); logEntry("rollbackTransaction"); SQLException exception = null; try { @@ -176,7 +176,7 @@ public void commitTransaction() throws SQLException { if (!transactionOpen) { throw new IllegalStateException("Transaction is not open"); } - verifyOpenConnection(); + connection = verifyOpenConnection(); logEntry("commitTransaction"); SQLException exception = null; try { @@ -202,7 +202,7 @@ public void commit() throws SQLException { if (transactionOpen) { throw new IllegalStateException("Can not perform a commit during an open transaction, use 'commitTransaction()'"); } - verifyOpenConnection(); + connection = verifyOpenConnection(); logEntry("commit"); SQLException exception = null; try { @@ -223,7 +223,7 @@ public void rollback() throws SQLException { if (transactionOpen) { throw new IllegalStateException("Can not perform a rollback during an open transaction, use 'rollbackTransaction()'"); } - verifyOpenConnection(); + connection = verifyOpenConnection(); logEntry("rollback"); SQLException exception = null; try { @@ -244,7 +244,7 @@ private void logEntry(String method) { } } - private MethodLogger.Entry logExit(String method, Exception exception) { + private MethodLogger.@Nullable Entry logExit(String method, @Nullable Exception exception) { if (methodLogger != null && methodLogger.isEnabled()) { return methodLogger.exit(method, exception); } @@ -252,10 +252,12 @@ private MethodLogger.Entry logExit(String method, Exception exception) { return null; } - private void verifyOpenConnection() { + private Connection verifyOpenConnection() { if (!connected()) { throw new IllegalStateException("Connection is closed"); } + + return connection; } /** diff --git a/common/db/src/main/java/is/codion/common/db/connection/package-info.java b/common/db/src/main/java/is/codion/common/db/connection/package-info.java new file mode 100644 index 0000000000..9772fac181 --- /dev/null +++ b/common/db/src/main/java/is/codion/common/db/connection/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    JDBC connection related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.db.connection; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/database/AbstractDatabase.java b/common/db/src/main/java/is/codion/common/db/database/AbstractDatabase.java index dd755ca20f..e0c97183bf 100644 --- a/common/db/src/main/java/is/codion/common/db/database/AbstractDatabase.java +++ b/common/db/src/main/java/is/codion/common/db/database/AbstractDatabase.java @@ -27,6 +27,8 @@ import is.codion.common.db.pool.ConnectionPoolWrapper; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.sql.Connection; @@ -66,11 +68,11 @@ public abstract class AbstractDatabase implements Database { DriverManager.setLoginTimeout(Database.LOGIN_TIMEOUT.getOrThrow()); } - private static Database instance; + private static @Nullable Database instance; private final Map connectionPools = new HashMap<>(); - private final int validityCheckTimeout = CONNECTION_VALIDITY_CHECK_TIMEOUT.get(); - private final Integer transactionIsolation = TRANSACTION_ISOLATION.get(); + private final int validityCheckTimeout = CONNECTION_VALIDITY_CHECK_TIMEOUT.getOrThrow(); + private final @Nullable Integer transactionIsolation = TRANSACTION_ISOLATION.get(); private final DefaultQueryCounter queryCounter = new DefaultQueryCounter(); private final String url; @@ -198,7 +200,7 @@ public String sequenceQuery(String sequenceName) { } @Override - public String errorMessage(SQLException exception, Operation operation) { + public @Nullable String errorMessage(SQLException exception, Operation operation) { requireNonNull(exception); requireNonNull(operation); @@ -249,7 +251,7 @@ else if (isTimeoutException(exception)) { static Database instance() { try { synchronized (AbstractDatabase.class) { - String databaseUrl = DATABASE_URL.get(); + String databaseUrl = DATABASE_URL.getOrThrow(); if (AbstractDatabase.instance == null || !AbstractDatabase.instance.url().equals(databaseUrl)) { Database previousInstance = AbstractDatabase.instance; //replace the instance @@ -279,7 +281,7 @@ static Database instance() { * @param offset the offset, may be null * @return a limit/offset clause */ - protected static String createLimitOffsetClause(Integer limit, Integer offset) { + protected static String createLimitOffsetClause(@Nullable Integer limit, @Nullable Integer offset) { StringBuilder builder = new StringBuilder(); if (limit != null) { builder.append(LIMIT).append(limit); @@ -299,7 +301,7 @@ protected static String createLimitOffsetClause(Integer limit, Integer offset) { * @param offset the offset, may be null * @return a limit/offset clause */ - protected static String createOffsetFetchNextClause(Integer limit, Integer offset) { + protected static String createOffsetFetchNextClause(@Nullable Integer limit, @Nullable Integer offset) { StringBuilder builder = new StringBuilder(); if (offset != null) { builder.append(OFFSET).append(offset).append(ROWS); @@ -347,7 +349,7 @@ private static final class DefaultQueryCounter implements QueryCounter { private final AtomicInteger deletesPerSecondCounter = new AtomicInteger(); private final AtomicInteger otherPerSecondCounter = new AtomicInteger(); - private final boolean enabled = COUNT_QUERIES.get(); + private final boolean enabled = COUNT_QUERIES.getOrThrow(); @Override public void select() { diff --git a/common/db/src/main/java/is/codion/common/db/database/Database.java b/common/db/src/main/java/is/codion/common/db/database/Database.java index 78b3b73ebe..25f744b153 100644 --- a/common/db/src/main/java/is/codion/common/db/database/Database.java +++ b/common/db/src/main/java/is/codion/common/db/database/Database.java @@ -26,6 +26,8 @@ import is.codion.common.property.PropertyValue; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.Collection; @@ -161,12 +163,12 @@ enum Operation { /** * Returns a limit/offset clause variation for this database, based on the given limit and offset values. - * If both are null an empty string should be returned. + * If both are null an empty string is returned. * @param limit the limit * @param offset the offset * @return a limit/offset clause */ - String limitOffsetClause(Integer limit, Integer offset); + String limitOffsetClause(@Nullable Integer limit, @Nullable Integer offset); /** * Returns true if this database requires that subqueries by aliased. @@ -189,7 +191,7 @@ enum Operation { * @return the message assigned to the given exception * @throws NullPointerException in case {@code exception} or {@code operation} is null */ - String errorMessage(SQLException exception, Operation operation); + @Nullable String errorMessage(SQLException exception, Operation operation); /** * Maps the given SQLException to a DatabaseException. @@ -262,7 +264,7 @@ enum Operation { /** * @param username the username - * @return the connection pool for the given user, null if none exists + * @return the connection pool for the given user * @throws IllegalArgumentException in case no connection pool exists for the given user */ ConnectionPoolWrapper connectionPool(String username); diff --git a/common/db/src/main/java/is/codion/common/db/database/package-info.java b/common/db/src/main/java/is/codion/common/db/database/package-info.java index 0a768ca31e..5a1ec6b005 100644 --- a/common/db/src/main/java/is/codion/common/db/database/package-info.java +++ b/common/db/src/main/java/is/codion/common/db/database/package-info.java @@ -17,7 +17,8 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    Database related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.db.database.Database#DATABASE_URL} *
    • {@link is.codion.common.db.database.Database#DATABASE_INIT_SCRIPTS} @@ -28,4 +29,5 @@ *
    • {@link is.codion.common.db.database.Database#CONNECTION_VALIDITY_CHECK_TIMEOUT} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.db.database; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/exception/AuthenticationException.java b/common/db/src/main/java/is/codion/common/db/exception/AuthenticationException.java index 19d0a421c2..991d23f67c 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/AuthenticationException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/AuthenticationException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + /** * An exception indication an authentication failure */ @@ -26,7 +28,7 @@ public final class AuthenticationException extends DatabaseException { /** * @param message the error message */ - public AuthenticationException(String message) { + public AuthenticationException(@Nullable String message) { super(message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/DatabaseException.java b/common/db/src/main/java/is/codion/common/db/exception/DatabaseException.java index ffeed5df76..49cc702ec8 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/DatabaseException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/DatabaseException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.sql.SQLException; import java.util.Optional; @@ -34,7 +36,7 @@ public class DatabaseException extends RuntimeException { * The sql statement being run when this exception occurred, if any, transient * so that it's not available client side if running in a server/client environment */ - private final transient String statement; + private final transient @Nullable String statement; /** * The underlying error code, if any, transient so that it's not @@ -46,13 +48,13 @@ public class DatabaseException extends RuntimeException { * The underlying sql state, if any, transient so that it's not * available client side if running in a server/client environment */ - private final transient String sqlState; + private final transient @Nullable String sqlState; /** * Constructs a new DatabaseException instance * @param message the exception message */ - public DatabaseException(String message) { + public DatabaseException(@Nullable String message) { this(message, null); } @@ -61,7 +63,7 @@ public DatabaseException(String message) { * @param message the exception message * @param statement the sql statement which caused the exception */ - public DatabaseException(String message, String statement) { + public DatabaseException(@Nullable String message, @Nullable String statement) { super(message); this.statement = statement; this.errorCode = -1; @@ -81,7 +83,7 @@ public DatabaseException(SQLException cause) { * @param cause the root cause, the stack trace is copied and used * @param message the exception message */ - public DatabaseException(SQLException cause, String message) { + public DatabaseException(SQLException cause, @Nullable String message) { this(cause, message, null); } @@ -91,7 +93,7 @@ public DatabaseException(SQLException cause, String message) { * @param message the exception message * @param statement the sql statement which caused the exception */ - public DatabaseException(SQLException cause, String message, String statement) { + public DatabaseException(@Nullable SQLException cause, @Nullable String message, @Nullable String statement) { super(message); this.statement = statement; if (cause != null) { diff --git a/common/db/src/main/java/is/codion/common/db/exception/DeleteException.java b/common/db/src/main/java/is/codion/common/db/exception/DeleteException.java index c04660d697..d2fe836a14 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/DeleteException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/DeleteException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + /** * An exception indicating a failed delete operation */ @@ -27,7 +29,7 @@ public final class DeleteException extends DatabaseException { * Instantiates a new {@link DeleteException} * @param message the message */ - public DeleteException(String message) { + public DeleteException(@Nullable String message) { super(message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/MultipleRecordsFoundException.java b/common/db/src/main/java/is/codion/common/db/exception/MultipleRecordsFoundException.java index 32e287d655..710c81978d 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/MultipleRecordsFoundException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/MultipleRecordsFoundException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + /** * Exception used when one record was expected but many were found. */ @@ -27,7 +29,7 @@ public class MultipleRecordsFoundException extends DatabaseException { * Instantiates a new MultipleRecordsFoundException * @param message the exception message */ - public MultipleRecordsFoundException(String message) { + public MultipleRecordsFoundException(@Nullable String message) { super(message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/QueryTimeoutException.java b/common/db/src/main/java/is/codion/common/db/exception/QueryTimeoutException.java index f9ba208839..cc40f82499 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/QueryTimeoutException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/QueryTimeoutException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; /** @@ -30,7 +32,7 @@ public final class QueryTimeoutException extends DatabaseException { * @param cause the underlying cause * @param message the error message */ - public QueryTimeoutException(SQLException cause, String message) { + public QueryTimeoutException(SQLException cause, @Nullable String message) { super(cause, message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/RecordModifiedException.java b/common/db/src/main/java/is/codion/common/db/exception/RecordModifiedException.java index e0b0566648..a5c7ff1550 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/RecordModifiedException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/RecordModifiedException.java @@ -18,13 +18,17 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + +import static java.util.Objects.requireNonNull; + /** * An exception indicating that the row in question has been modified or deleted since it was loaded. */ public final class RecordModifiedException extends UpdateException { private final Object row; - private final Object modifiedRow; + private final @Nullable Object modifiedRow; /** * Instantiates a new RecordModifiedException @@ -32,9 +36,9 @@ public final class RecordModifiedException extends UpdateException { * @param modifiedRow the current (modified) version of the row, null if it has been deleted * @param message a message describing the modification */ - public RecordModifiedException(Object row, Object modifiedRow, String message) { + public RecordModifiedException(Object row, @Nullable Object modifiedRow, @Nullable String message) { super(message); - this.row = row; + this.row = requireNonNull(row); this.modifiedRow = modifiedRow; } @@ -48,7 +52,7 @@ public Object row() { /** * @return the current (modified) version of the row, null if it has been deleted */ - public Object modifiedRow() { + public @Nullable Object modifiedRow() { return modifiedRow; } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/ReferentialIntegrityException.java b/common/db/src/main/java/is/codion/common/db/exception/ReferentialIntegrityException.java index 2874cafa11..8cdb9e32ec 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/ReferentialIntegrityException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/ReferentialIntegrityException.java @@ -20,6 +20,8 @@ import is.codion.common.db.database.Database.Operation; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import static java.util.Objects.requireNonNull; @@ -37,7 +39,7 @@ public final class ReferentialIntegrityException extends DatabaseException { * @param message the error message * @param operation the operation causing this exception */ - public ReferentialIntegrityException(SQLException cause, String message, Operation operation) { + public ReferentialIntegrityException(SQLException cause, @Nullable String message, Operation operation) { super(cause, message); this.operation = requireNonNull(operation); } diff --git a/common/db/src/main/java/is/codion/common/db/exception/UniqueConstraintException.java b/common/db/src/main/java/is/codion/common/db/exception/UniqueConstraintException.java index 8a1cec177d..6b23141c44 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/UniqueConstraintException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/UniqueConstraintException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; /** @@ -30,7 +32,7 @@ public final class UniqueConstraintException extends DatabaseException { * @param cause the underlying cause * @param message the error message */ - public UniqueConstraintException(SQLException cause, String message) { + public UniqueConstraintException(SQLException cause, @Nullable String message) { super(cause, message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/UpdateException.java b/common/db/src/main/java/is/codion/common/db/exception/UpdateException.java index 5461d78759..5c6e22b14c 100644 --- a/common/db/src/main/java/is/codion/common/db/exception/UpdateException.java +++ b/common/db/src/main/java/is/codion/common/db/exception/UpdateException.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.exception; +import org.jspecify.annotations.Nullable; + /** * An exception indicating a failed update operation */ @@ -27,7 +29,7 @@ public class UpdateException extends DatabaseException { * Instantiates a new {@link UpdateException} * @param message the message */ - public UpdateException(String message) { + public UpdateException(@Nullable String message) { super(message); } } diff --git a/common/db/src/main/java/is/codion/common/db/exception/package-info.java b/common/db/src/main/java/is/codion/common/db/exception/package-info.java new file mode 100644 index 0000000000..0795584d9f --- /dev/null +++ b/common/db/src/main/java/is/codion/common/db/exception/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    Database related Exceptions. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.db.exception; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/operation/DatabaseFunction.java b/common/db/src/main/java/is/codion/common/db/operation/DatabaseFunction.java index 7bad0c4b9f..8299e0c519 100644 --- a/common/db/src/main/java/is/codion/common/db/operation/DatabaseFunction.java +++ b/common/db/src/main/java/is/codion/common/db/operation/DatabaseFunction.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.operation; +import org.jspecify.annotations.Nullable; + /** * A database function * @param the connection type required by this function @@ -32,5 +34,5 @@ public interface DatabaseFunction { * @param argument the function argument, if any * @return the function return argument */ - R execute(C connection, T argument); + @Nullable R execute(C connection, @Nullable T argument); } diff --git a/common/db/src/main/java/is/codion/common/db/operation/DatabaseProcedure.java b/common/db/src/main/java/is/codion/common/db/operation/DatabaseProcedure.java index b46294ee6a..edec9fbf1c 100644 --- a/common/db/src/main/java/is/codion/common/db/operation/DatabaseProcedure.java +++ b/common/db/src/main/java/is/codion/common/db/operation/DatabaseProcedure.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.operation; +import org.jspecify.annotations.Nullable; + /** * A database procedure * @param the connection type required by this procedure @@ -30,5 +32,5 @@ public interface DatabaseProcedure { * @param connection the connection to use * @param argument the procedure argument, if any */ - void execute(C connection, T argument); + void execute(C connection, @Nullable T argument); } diff --git a/common/db/src/main/java/is/codion/common/db/operation/package-info.java b/common/db/src/main/java/is/codion/common/db/operation/package-info.java new file mode 100644 index 0000000000..cbf8cb4e39 --- /dev/null +++ b/common/db/src/main/java/is/codion/common/db/operation/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    Database operations and functions. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.db.operation; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/pool/AbstractConnectionPoolWrapper.java b/common/db/src/main/java/is/codion/common/db/pool/AbstractConnectionPoolWrapper.java index b29777db85..7edd5a5272 100755 --- a/common/db/src/main/java/is/codion/common/db/pool/AbstractConnectionPoolWrapper.java +++ b/common/db/src/main/java/is/codion/common/db/pool/AbstractConnectionPoolWrapper.java @@ -25,6 +25,8 @@ import is.codion.common.proxy.ProxyBuilder.ProxyMethod; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; + import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; @@ -198,7 +200,7 @@ public Object invoke(Parameters parameters) throws Throwable { private final class Close implements ProxyMethod { @Override - public Object invoke(Parameters parameters) throws Throwable { + public @Nullable Object invoke(Parameters parameters) throws Throwable { Connection connection = parameters.delegate(); if (!connection.isClosed()) { counter.incrementConnectionsDestroyedCounter(); diff --git a/common/db/src/main/java/is/codion/common/db/pool/package-info.java b/common/db/src/main/java/is/codion/common/db/pool/package-info.java index a6f4af25a1..feed9aaee6 100644 --- a/common/db/src/main/java/is/codion/common/db/pool/package-info.java +++ b/common/db/src/main/java/is/codion/common/db/pool/package-info.java @@ -17,11 +17,13 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    Connection pool related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.db.pool.ConnectionPoolWrapper#DEFAULT_MAXIMUM_POOL_SIZE} *
    • {@link is.codion.common.db.pool.ConnectionPoolWrapper#DEFAULT_MINIMUM_POOL_SIZE} *
    • {@link is.codion.common.db.pool.ConnectionPoolWrapper#DEFAULT_IDLE_TIMEOUT} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.db.pool; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/report/AbstractReport.java b/common/db/src/main/java/is/codion/common/db/report/AbstractReport.java index c8e9d1fd55..eb42e4b8a5 100644 --- a/common/db/src/main/java/is/codion/common/db/report/AbstractReport.java +++ b/common/db/src/main/java/is/codion/common/db/report/AbstractReport.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.report; +import org.jspecify.annotations.Nullable; + import static java.util.Objects.requireNonNull; /** @@ -35,7 +37,7 @@ public abstract class AbstractReport implements Report { private final boolean cacheReport; - private T cachedReport; + private @Nullable T cachedReport; /** * Instantiates a new AbstractReport. diff --git a/common/db/src/main/java/is/codion/common/db/report/package-info.java b/common/db/src/main/java/is/codion/common/db/report/package-info.java index 49fbe4efd5..205906a8b6 100644 --- a/common/db/src/main/java/is/codion/common/db/report/package-info.java +++ b/common/db/src/main/java/is/codion/common/db/report/package-info.java @@ -17,10 +17,12 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    Report related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.db.report.Report#REPORT_PATH} *
    • {@link is.codion.common.db.report.Report#CACHE_REPORTS} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.db.report; \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/result/DefaultIterator.java b/common/db/src/main/java/is/codion/common/db/result/DefaultIterator.java index 35d57393fe..904f52d72f 100644 --- a/common/db/src/main/java/is/codion/common/db/result/DefaultIterator.java +++ b/common/db/src/main/java/is/codion/common/db/result/DefaultIterator.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.result; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.Iterator; import java.util.NoSuchElementException; @@ -43,7 +45,7 @@ public boolean hasNext() { } @Override - public T next() { + public @Nullable T next() { if (!hasNext()) { throw new NoSuchElementException(); } diff --git a/common/db/src/main/java/is/codion/common/db/result/ResultIterator.java b/common/db/src/main/java/is/codion/common/db/result/ResultIterator.java index 8e1c785b01..0a9dda109c 100644 --- a/common/db/src/main/java/is/codion/common/db/result/ResultIterator.java +++ b/common/db/src/main/java/is/codion/common/db/result/ResultIterator.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.result; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.Iterator; @@ -40,7 +42,7 @@ public interface ResultIterator extends AutoCloseable, Iterable { * @throws SQLException in case of an exception * @throws java.util.NoSuchElementException in case no more rows are available */ - T next() throws SQLException; + @Nullable T next() throws SQLException; /** * Closes the underlying result set and other resources held by this iterator diff --git a/common/db/src/main/java/is/codion/common/db/result/ResultPacker.java b/common/db/src/main/java/is/codion/common/db/result/ResultPacker.java index 4c531f0965..da387ca7b6 100644 --- a/common/db/src/main/java/is/codion/common/db/result/ResultPacker.java +++ b/common/db/src/main/java/is/codion/common/db/result/ResultPacker.java @@ -18,6 +18,8 @@ */ package is.codion.common.db.result; +import org.jspecify.annotations.Nullable; + import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -59,5 +61,5 @@ default List pack(ResultSet resultSet) throws SQLException { * @return the instance fetched from the ResultSet * @throws SQLException in case of failure */ - T get(ResultSet resultSet) throws SQLException; + @Nullable T get(ResultSet resultSet) throws SQLException; } \ No newline at end of file diff --git a/common/db/src/main/java/is/codion/common/db/result/package-info.java b/common/db/src/main/java/is/codion/common/db/result/package-info.java new file mode 100644 index 0000000000..44d07024f8 --- /dev/null +++ b/common/db/src/main/java/is/codion/common/db/result/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    ResultSet handling related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.db.result; \ No newline at end of file diff --git a/common/db/src/main/java/module-info.java b/common/db/src/main/java/module-info.java index d731ebe78c..66f958eb51 100644 --- a/common/db/src/main/java/module-info.java +++ b/common/db/src/main/java/module-info.java @@ -17,7 +17,7 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Core classes concerned with JDBC connectivity, such as: + *

    Core classes concerned with JDBC connectivity. *

      *
    • {@link is.codion.common.db.database.Database} *
    • {@link is.codion.common.db.database.DatabaseFactory} @@ -29,7 +29,9 @@ * @uses is.codion.common.db.database.DatabaseFactory * @uses is.codion.common.db.pool.ConnectionPoolFactory */ +@org.jspecify.annotations.NullMarked module is.codion.common.db { + requires transitive org.jspecify; requires transitive java.sql; requires transitive is.codion.common.core; diff --git a/common/db/src/test/java/is/codion/common/db/database/AbstractDatabaseTest.java b/common/db/src/test/java/is/codion/common/db/database/AbstractDatabaseTest.java index fa541e54c3..368cbc2438 100644 --- a/common/db/src/test/java/is/codion/common/db/database/AbstractDatabaseTest.java +++ b/common/db/src/test/java/is/codion/common/db/database/AbstractDatabaseTest.java @@ -109,7 +109,7 @@ public String name() { @Override public String autoIncrementQuery(String idSource) { - return null; + return ""; } @Override diff --git a/common/db/src/test/java/is/codion/common/db/database/DatabaseTest.java b/common/db/src/test/java/is/codion/common/db/database/DatabaseTest.java index 75985c20a2..024843c373 100644 --- a/common/db/src/test/java/is/codion/common/db/database/DatabaseTest.java +++ b/common/db/src/test/java/is/codion/common/db/database/DatabaseTest.java @@ -20,6 +20,7 @@ import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import java.sql.Connection; @@ -59,7 +60,7 @@ public String selectForUpdateClause() { } @Override - public String limitOffsetClause(Integer limit, Integer offset) { + public String limitOffsetClause(@Nullable Integer limit, @Nullable Integer offset) { return createLimitOffsetClause(limit, offset); } diff --git a/common/i18n/src/main/java/is/codion/common/i18n/package-info.java b/common/i18n/src/main/java/is/codion/common/i18n/package-info.java new file mode 100644 index 0000000000..6bdc56761f --- /dev/null +++ b/common/i18n/src/main/java/is/codion/common/i18n/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

      i18n related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.i18n; \ No newline at end of file diff --git a/common/i18n/src/main/java/module-info.java b/common/i18n/src/main/java/module-info.java index 0bdda449ad..5dc6389413 100644 --- a/common/i18n/src/main/java/module-info.java +++ b/common/i18n/src/main/java/module-info.java @@ -22,7 +22,9 @@ *

    • {@link is.codion.common.i18n.Messages} *
    */ +@org.jspecify.annotations.NullMarked module is.codion.common.i18n { + requires transitive org.jspecify; requires is.codion.common.core; exports is.codion.common.i18n; diff --git a/common/model/src/main/java/is/codion/common/model/FilterModel.java b/common/model/src/main/java/is/codion/common/model/FilterModel.java index b46c14635d..006c3c9561 100644 --- a/common/model/src/main/java/is/codion/common/model/FilterModel.java +++ b/common/model/src/main/java/is/codion/common/model/FilterModel.java @@ -29,6 +29,8 @@ import is.codion.common.state.StateObserver; import is.codion.common.value.Value; +import org.jspecify.annotations.Nullable; + import java.util.Collection; import java.util.List; import java.util.function.Consumer; @@ -299,7 +301,7 @@ abstract class AbstractRefresher implements Refresher { private final Event refreshFailedEvent = Event.event(); private final State refreshingState = State.state(); private final Supplier> supplier; - private final State async = State.state(ASYNC_REFRESH.get()); + private final State async = State.state(ASYNC_REFRESH.getOrThrow()); /** * @param supplier supplies the items when refreshing @@ -389,13 +391,13 @@ protected final void notifyFailure(Exception exception) { * Performes an async refresh * @param onRefresh if specified will be called after a successful refresh */ - protected abstract void refreshAsync(Consumer> onRefresh); + protected abstract void refreshAsync(@Nullable Consumer> onRefresh); /** * Performs a sync refresh * @param onRefresh if specified will be called after a successful refresh */ - protected abstract void refreshSync(Consumer> onRefresh); + protected abstract void refreshSync(@Nullable Consumer> onRefresh); /** * Processes the refresh result, by replacing the current model items by the result items. diff --git a/common/model/src/main/java/is/codion/common/model/UserPreferences.java b/common/model/src/main/java/is/codion/common/model/UserPreferences.java index 3c730b46bb..e441f40891 100644 --- a/common/model/src/main/java/is/codion/common/model/UserPreferences.java +++ b/common/model/src/main/java/is/codion/common/model/UserPreferences.java @@ -18,6 +18,8 @@ */ package is.codion.common.model; +import org.jspecify.annotations.Nullable; + import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; @@ -28,7 +30,7 @@ */ public final class UserPreferences { - private static Preferences preferences; + private static @Nullable Preferences preferences; private UserPreferences() {} diff --git a/common/model/src/main/java/is/codion/common/model/condition/ConditionModel.java b/common/model/src/main/java/is/codion/common/model/condition/ConditionModel.java index 85049a3f24..8ecb069b03 100644 --- a/common/model/src/main/java/is/codion/common/model/condition/ConditionModel.java +++ b/common/model/src/main/java/is/codion/common/model/condition/ConditionModel.java @@ -26,6 +26,8 @@ import is.codion.common.value.Value; import is.codion.common.value.ValueSet; +import org.jspecify.annotations.Nullable; + import java.text.Format; import java.util.List; import java.util.Optional; @@ -166,7 +168,7 @@ public String description() { * @param value the value * @return true if the given value is accepted by this models condition */ - boolean accepts(Comparable value); + boolean accepts(@Nullable Comparable value); /** * @return an observer notified each time the condition changes @@ -235,13 +237,13 @@ interface Builder { * @param format the format to use when presenting the values, numbers for example * @return this builder instance */ - Builder format(Format format); + Builder format(@Nullable Format format); /** * @param dateTimePattern the date/time format pattern to use in case of a date/time value * @return this builder instance */ - Builder dateTimePattern(String dateTimePattern); + Builder dateTimePattern(@Nullable String dateTimePattern); /** * @param wildcard the wildcards to use diff --git a/common/model/src/main/java/is/codion/common/model/condition/DefaultConditionModel.java b/common/model/src/main/java/is/codion/common/model/condition/DefaultConditionModel.java index 5587e761ee..3893f65320 100644 --- a/common/model/src/main/java/is/codion/common/model/condition/DefaultConditionModel.java +++ b/common/model/src/main/java/is/codion/common/model/condition/DefaultConditionModel.java @@ -29,6 +29,8 @@ import is.codion.common.value.ValueObserver; import is.codion.common.value.ValueSet; +import org.jspecify.annotations.Nullable; + import java.text.Format; import java.util.List; import java.util.Optional; @@ -62,8 +64,8 @@ final class DefaultConditionModel implements ConditionModel { .build(); private final Class valueClass; - private final Format format; - private final String dateTimePattern; + private final @Nullable Format format; + private final @Nullable String dateTimePattern; private final List operators; private DefaultConditionModel(DefaultBuilder builder) { @@ -162,7 +164,7 @@ public void clear() { } @Override - public boolean accepts(Comparable value) { + public boolean accepts(@Nullable Comparable value) { return valueAccepted(value); } @@ -171,11 +173,11 @@ public Observer changed() { return conditionChanged.observer(); } - private boolean valueAccepted(Comparable comparable) { + private boolean valueAccepted(@Nullable Comparable comparable) { if (!caseSensitive.get()) { comparable = stringOrCharacterToLowerCase(comparable); } - switch (operator.get()) { + switch (operator.getOrThrow()) { case EQUAL: return isEqual(comparable); case NOT_EQUAL: @@ -205,7 +207,7 @@ private boolean valueAccepted(Comparable comparable) { } } - private boolean isEqual(Comparable comparable) { + private boolean isEqual(@Nullable Comparable comparable) { T equalOperand = operands.equal().get(); if (!caseSensitive.get()) { equalOperand = stringOrCharacterToLowerCase(equalOperand); @@ -223,7 +225,7 @@ private boolean isEqual(Comparable comparable) { return comparable.compareTo(equalOperand) == 0; } - private boolean isNotEqual(Comparable comparable) { + private boolean isNotEqual(@Nullable Comparable comparable) { T equalOperand = operands.equal().get(); if (!caseSensitive.get()) { equalOperand = stringOrCharacterToLowerCase(equalOperand); @@ -261,31 +263,31 @@ private boolean isEqualWildcard(String value) { .collect(joining(REGEX_WILDCARD, "", equalOperand.endsWith(WILDCARD_CHARACTER) ? REGEX_WILDCARD : "")), value); } - private boolean isLessThan(Comparable comparable) { + private boolean isLessThan(@Nullable Comparable comparable) { T upperBound = operands.upperBound.get(); return upperBound == null || comparable != null && comparable.compareTo(upperBound) < 0; } - private boolean isLessThanOrEqual(Comparable comparable) { + private boolean isLessThanOrEqual(@Nullable Comparable comparable) { T upperBound = operands.upperBound.get(); return upperBound == null || comparable != null && comparable.compareTo(upperBound) <= 0; } - private boolean isGreaterThan(Comparable comparable) { + private boolean isGreaterThan(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); return lowerBound == null || comparable != null && comparable.compareTo(lowerBound) > 0; } - private boolean isGreaterThanOrEqual(Comparable comparable) { + private boolean isGreaterThanOrEqual(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); return lowerBound == null || comparable != null && comparable.compareTo(lowerBound) >= 0; } - private boolean isBetweenExclusive(Comparable comparable) { + private boolean isBetweenExclusive(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); T upperBound = operands.upperBound.get(); if (lowerBound == null && upperBound == null) { @@ -310,7 +312,7 @@ private boolean isBetweenExclusive(Comparable comparable) { return lowerCompareResult > 0 && upperCompareResult < 0; } - private boolean isBetween(Comparable comparable) { + private boolean isBetween(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); T upperBound = operands.upperBound.get(); if (lowerBound == null && upperBound == null) { @@ -335,7 +337,7 @@ private boolean isBetween(Comparable comparable) { return lowerCompareResult >= 0 && upperCompareResult <= 0; } - private boolean isNotBetweenExclusive(Comparable comparable) { + private boolean isNotBetweenExclusive(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); T upperBound = operands.upperBound.get(); if (lowerBound == null && upperBound == null) { @@ -360,7 +362,7 @@ private boolean isNotBetweenExclusive(Comparable comparable) { return lowerCompareResult < 0 || upperCompareResult > 0; } - private boolean isNotBetween(Comparable comparable) { + private boolean isNotBetween(@Nullable Comparable comparable) { T lowerBound = operands.lowerBound.get(); T upperBound = operands.upperBound.get(); if (lowerBound == null && upperBound == null) { @@ -385,11 +387,11 @@ private boolean isNotBetween(Comparable comparable) { return lowerCompareResult <= 0 || upperCompareResult >= 0; } - private boolean isIn(Comparable comparable) { + private boolean isIn(@Nullable Comparable comparable) { return operands.in.get().contains(comparable); } - private boolean isNotIn(Comparable comparable) { + private boolean isNotIn(@Nullable Comparable comparable) { return !isIn(comparable); } @@ -399,13 +401,13 @@ private void checkLock() { } } - private void validateOperator(Operator operator) { + private void validateOperator(@Nullable Operator operator) { if (operators != null && !operators.contains(requireNonNull(operator))) { throw new IllegalArgumentException("Operator " + operator + " not available"); } } - private static T stringOrCharacterToLowerCase(T value) { + private static @Nullable T stringOrCharacterToLowerCase(@Nullable T value) { if (value instanceof String) { return (T) ((String) value).toLowerCase(); } @@ -416,7 +418,7 @@ private static T stringOrCharacterToLowerCase(T value) { return value; } - private static Comparable stringOrCharacterToLowerCase(Comparable comparable) { + private static @Nullable Comparable stringOrCharacterToLowerCase(@Nullable Comparable comparable) { if (comparable instanceof String) { return (Comparable) ((String) comparable).toLowerCase(); } @@ -432,7 +434,7 @@ private final class AutoEnableListener implements Runnable { @Override public void run() { if (autoEnable.get()) { - switch (operator.get()) { + switch (operator.getOrThrow()) { case EQUAL: case NOT_EQUAL: enabled.set(operands.equal.isNotNull()); @@ -513,7 +515,7 @@ private static final class EqualOperand extends AbstractValue { private final Value wildcard; private final ValueObserver operatorObserver; - private T value; + private @Nullable T value; private EqualOperand(Wildcard wildcard, ValueObserver operatorObserver) { super(null, Notify.WHEN_SET); @@ -524,7 +526,7 @@ private EqualOperand(Wildcard wildcard, ValueObserver operatorObserver } @Override - protected T getValue() { + protected @Nullable T getValue() { return addWildcard(value); } @@ -533,11 +535,11 @@ protected void setValue(T value) { this.value = value; } - private T addWildcard(T operand) { + private @Nullable T addWildcard(@Nullable T operand) { if (!(operand instanceof String)) { return operand; } - switch (operatorObserver.get()) { + switch (operatorObserver.getOrThrow()) { //wildcard only used for EQUAL and NOT_EQUAL case EQUAL: case NOT_EQUAL: @@ -549,7 +551,7 @@ private T addWildcard(T operand) { private String addWildcard(String operand) { String operandWithWildcards = operand; - switch (wildcard.get()) { + switch (wildcard.getOrThrow()) { case PREFIX: operandWithWildcards = addWildcardPrefix(operandWithWildcards); break; @@ -593,15 +595,15 @@ static final class DefaultBuilder implements Builder { private List operators; private Operator operator = Operator.EQUAL; - private Format format; - private String dateTimePattern = LocaleDateTimePattern.builder() + private @Nullable Format format; + private @Nullable String dateTimePattern = LocaleDateTimePattern.builder() .delimiterDash() .yearFourDigits() .hoursMinutesSeconds() .build() .dateTimePattern(); - private Wildcard wildcard = WILDCARD.get(); - private boolean caseSensitive = CASE_SENSITIVE.get(); + private Wildcard wildcard = WILDCARD.getOrThrow(); + private boolean caseSensitive = CASE_SENSITIVE.getOrThrow(); private boolean autoEnable = true; DefaultBuilder(Class valueClass) { @@ -627,13 +629,13 @@ public Builder operator(Operator operator) { } @Override - public Builder format(Format format) { + public Builder format(@Nullable Format format) { this.format = format; return this; } @Override - public Builder dateTimePattern(String dateTimePattern) { + public Builder dateTimePattern(@Nullable String dateTimePattern) { this.dateTimePattern = dateTimePattern; return this; } diff --git a/common/model/src/main/java/is/codion/common/model/condition/package-info.java b/common/model/src/main/java/is/codion/common/model/condition/package-info.java index c56edb33dc..83cc2a9036 100644 --- a/common/model/src/main/java/is/codion/common/model/condition/package-info.java +++ b/common/model/src/main/java/is/codion/common/model/condition/package-info.java @@ -17,10 +17,12 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    Condition related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.model.condition.ConditionModel#WILDCARD} *
    • {@link is.codion.common.model.condition.ConditionModel#CASE_SENSITIVE} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.model.condition; \ No newline at end of file diff --git a/common/model/src/main/java/is/codion/common/model/package-info.java b/common/model/src/main/java/is/codion/common/model/package-info.java new file mode 100644 index 0000000000..e9181a4bcd --- /dev/null +++ b/common/model/src/main/java/is/codion/common/model/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    Application model related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.model; \ No newline at end of file diff --git a/common/model/src/main/java/is/codion/common/model/selection/package-info.java b/common/model/src/main/java/is/codion/common/model/selection/package-info.java new file mode 100644 index 0000000000..4c9973cf61 --- /dev/null +++ b/common/model/src/main/java/is/codion/common/model/selection/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    Selection related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.model.selection; \ No newline at end of file diff --git a/common/model/src/main/java/is/codion/common/model/summary/ColumnSummary.java b/common/model/src/main/java/is/codion/common/model/summary/ColumnSummary.java index e33d46b173..4dc0a0529c 100644 --- a/common/model/src/main/java/is/codion/common/model/summary/ColumnSummary.java +++ b/common/model/src/main/java/is/codion/common/model/summary/ColumnSummary.java @@ -26,6 +26,7 @@ import java.util.OptionalDouble; import static is.codion.common.resource.MessageBundle.messageBundle; +import static java.util.Objects.requireNonNull; import static java.util.ResourceBundle.getBundle; /** @@ -57,7 +58,7 @@ public String toString() { @Override public String summary(SummaryValues summaryValues) { - Collection values = summaryValues.values(); + Collection values = requireNonNull(summaryValues).values(); if (!values.isEmpty()) { return addSubsetIndicator(summaryValues.format(values.stream() .filter(Objects::nonNull) @@ -78,7 +79,7 @@ public String toString() { @Override public String summary(SummaryValues summaryValues) { - Collection values = summaryValues.values(); + Collection values = requireNonNull(summaryValues).values(); if (!values.isEmpty()) { OptionalDouble average = values.stream() .mapToDouble(value -> value == null ? 0d : value.doubleValue()) @@ -102,7 +103,7 @@ public String toString() { @Override public String summary(SummaryValues summaryValues) { - Collection values = summaryValues.values(); + Collection values = requireNonNull(summaryValues).values(); if (!values.isEmpty()) { OptionalDouble min = values.stream() .filter(Objects::nonNull) @@ -127,7 +128,7 @@ public String toString() { @Override public String summary(SummaryValues summaryValues) { - Collection values = summaryValues.values(); + Collection values = requireNonNull(summaryValues).values(); if (!values.isEmpty()) { OptionalDouble max = values.stream() .filter(Objects::nonNull) @@ -152,7 +153,7 @@ public String toString() { @Override public String summary(SummaryValues summaryValues) { - Collection values = summaryValues.values(); + Collection values = requireNonNull(summaryValues).values(); if (!values.isEmpty()) { OptionalDouble min = values.stream() .filter(Objects::nonNull) diff --git a/common/model/src/main/java/is/codion/common/model/summary/DefaultSummaryModel.java b/common/model/src/main/java/is/codion/common/model/summary/DefaultSummaryModel.java index 9703a4602b..b61b18ad32 100644 --- a/common/model/src/main/java/is/codion/common/model/summary/DefaultSummaryModel.java +++ b/common/model/src/main/java/is/codion/common/model/summary/DefaultSummaryModel.java @@ -73,6 +73,6 @@ public ValueObserver summaryText() { } private void updateSummary() { - summaryText.set(summary().get().summary(summaryValues)); + summaryText.set(summary().getOrThrow().summary(summaryValues)); } } diff --git a/common/model/src/main/java/is/codion/common/model/summary/DefaultTableSummaryModel.java b/common/model/src/main/java/is/codion/common/model/summary/DefaultTableSummaryModel.java index 1676e7de53..c2adff0667 100644 --- a/common/model/src/main/java/is/codion/common/model/summary/DefaultTableSummaryModel.java +++ b/common/model/src/main/java/is/codion/common/model/summary/DefaultTableSummaryModel.java @@ -39,7 +39,7 @@ final class DefaultTableSummaryModel implements TableSummaryModel { @Override public Optional summaryModel(C identifier) { - return Optional.ofNullable(summaryModels.computeIfAbsent(identifier, k -> + return Optional.ofNullable(summaryModels.computeIfAbsent(requireNonNull(identifier), k -> createSummaryModel(k, NumberFormat.getInstance()).orElse(null))); } diff --git a/common/model/src/main/java/is/codion/common/model/summary/package-info.java b/common/model/src/main/java/is/codion/common/model/summary/package-info.java new file mode 100644 index 0000000000..77204e92a7 --- /dev/null +++ b/common/model/src/main/java/is/codion/common/model/summary/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    Summary related classes. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.model.summary; \ No newline at end of file diff --git a/common/model/src/main/java/module-info.java b/common/model/src/main/java/module-info.java index 9c11a3cb6a..b9e0d0f5a2 100644 --- a/common/model/src/main/java/module-info.java +++ b/common/model/src/main/java/module-info.java @@ -17,7 +17,7 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Shared model classes, such as: + *

    Shared model classes. *

      *
    • {@link is.codion.common.model.UserPreferences} *
    • {@link is.codion.common.model.CancelException} @@ -30,7 +30,9 @@ *
    • {@link is.codion.common.model.summary.TableSummaryModel} *
    */ +@org.jspecify.annotations.NullMarked module is.codion.common.model { + requires transitive org.jspecify; requires java.prefs; requires transitive is.codion.common.core; diff --git a/common/rmi/src/main/java/is/codion/common/rmi/client/Clients.java b/common/rmi/src/main/java/is/codion/common/rmi/client/Clients.java index d80d90989f..cb6c427346 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/client/Clients.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/client/Clients.java @@ -32,8 +32,6 @@ import java.nio.file.Files; import java.security.KeyStore; -import static is.codion.common.Text.nullOrEmpty; - /** * Utility methods for remote clients */ @@ -95,7 +93,7 @@ private Clients() {} */ public static void resolveTrustStore() { String trustStorePath = TRUSTSTORE.get(); - if (nullOrEmpty(trustStorePath)) { + if (trustStorePath == null || trustStorePath.isEmpty()) { LOG.warn("No truststore specified via {}", TRUSTSTORE.propertyName()); return; } diff --git a/common/rmi/src/main/java/is/codion/common/rmi/client/ConnectionRequest.java b/common/rmi/src/main/java/is/codion/common/rmi/client/ConnectionRequest.java index 6f59bdf0cd..719ac0aced 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/client/ConnectionRequest.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/client/ConnectionRequest.java @@ -21,6 +21,8 @@ import is.codion.common.user.User; import is.codion.common.version.Version; +import org.jspecify.annotations.Nullable; + import java.time.ZoneId; import java.util.Locale; import java.util.Map; @@ -111,7 +113,7 @@ interface Builder { * @param clientVersion the client version * @return this Builder instance */ - Builder clientVersion(Version clientVersion); + Builder clientVersion(@Nullable Version clientVersion); /** * @param key the key diff --git a/common/rmi/src/main/java/is/codion/common/rmi/client/DefaultConnectionRequest.java b/common/rmi/src/main/java/is/codion/common/rmi/client/DefaultConnectionRequest.java index 98b458eb1d..d017ba0ded 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/client/DefaultConnectionRequest.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/client/DefaultConnectionRequest.java @@ -21,6 +21,8 @@ import is.codion.common.user.User; import is.codion.common.version.Version; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import java.time.ZoneId; @@ -44,9 +46,9 @@ final class DefaultConnectionRequest implements ConnectionRequest, Serializable private final String clientType; private final Locale clientLocale = Locale.getDefault(); private final ZoneId clientTimeZone = ZoneId.systemDefault(); - private final Version clientVersion; + private final @Nullable Version clientVersion; private final Version frameworkVersion = Version.version(); - private final Map parameters; + private final @Nullable Map parameters; private DefaultConnectionRequest(DefaultBuilder builder) { this.user = requireNonNull(builder.user, "user must be specified"); @@ -127,11 +129,11 @@ public String toString() { static final class DefaultBuilder implements Builder { - private User user; - private UUID clientId; - private String clientType; - private Version clientVersion; - private Map parameters; + private @Nullable User user; + private @Nullable UUID clientId; + private @Nullable String clientType; + private @Nullable Version clientVersion; + private @Nullable Map parameters; DefaultBuilder() {} @@ -154,13 +156,14 @@ public Builder clientType(String clientType) { } @Override - public Builder clientVersion(Version clientVersion) { + public Builder clientVersion(@Nullable Version clientVersion) { this.clientVersion = clientVersion; return this; } @Override public Builder parameter(String key, Object value) { + requireNonNull(key); if (parameters == null) { parameters = new HashMap<>(); } diff --git a/common/rmi/src/main/java/is/codion/common/rmi/client/package-info.java b/common/rmi/src/main/java/is/codion/common/rmi/client/package-info.java index b19bac978e..662b07fffe 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/client/package-info.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/client/package-info.java @@ -17,11 +17,13 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    RMI client related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.rmi.client.Clients#SERVER_HOSTNAME} *
    • {@link is.codion.common.rmi.client.Clients#TRUSTSTORE} *
    • {@link is.codion.common.rmi.client.Clients#TRUSTSTORE_PASSWORD} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.rmi.client; \ No newline at end of file diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/AbstractServer.java b/common/rmi/src/main/java/is/codion/common/rmi/server/AbstractServer.java index 6a0d1538b0..e464651812 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/AbstractServer.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/AbstractServer.java @@ -26,6 +26,7 @@ import is.codion.common.scheduler.TaskScheduler; import is.codion.common.user.User; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -77,8 +78,8 @@ public abstract class AbstractServer ex private volatile int connectionLimit = -1; private volatile boolean shuttingDown = false; - private Registry registry; - private A admin; + private @Nullable Registry registry; + private @Nullable A admin; /** * Instantiates a new AbstractServer @@ -155,7 +156,7 @@ public final void setConnectionLimit(int connectionLimit) { * @return the maintenance check interval in ms */ public final int getMaintenanceInterval() { - return connectionMaintenanceScheduler.interval().get(); + return connectionMaintenanceScheduler.interval().getOrThrow(); } /** @@ -296,6 +297,7 @@ final Collection clients(User user) { * @throws IllegalStateException in case an admin instance has already been set */ protected final void setAdmin(A admin) { + requireNonNull(admin); if (this.admin != null) { throw new IllegalStateException("Admin has already been set for this server"); } @@ -502,7 +504,7 @@ private static void stopAuxiliaryServer(AuxiliaryServer server) { } } - private static void unexportSilently(Remote... remotes) { + private static void unexportSilently(@Nullable Remote... remotes) { for (Remote remote : remotes) { if (remote != null) { try { @@ -515,7 +517,7 @@ private static void unexportSilently(Remote... remotes) { } } - private static String clientHost(String requestParameterHost) { + private static String clientHost(@Nullable String requestParameterHost) { if (requestParameterHost == null) { try { return getClientHost(); diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerConfiguration.java b/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerConfiguration.java index d69df9233d..f5aff05b66 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerConfiguration.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerConfiguration.java @@ -20,6 +20,7 @@ import is.codion.common.version.Version; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,9 +55,9 @@ final class DefaultServerConfiguration implements ServerConfiguration { private final int adminPort; private final boolean sslEnabled; private final Supplier serverNameSupplier; - private final RMIClientSocketFactory rmiClientSocketFactory; - private final RMIServerSocketFactory rmiServerSocketFactory; - private final String objectInputFilterFactoryClassName; + private final @Nullable RMIClientSocketFactory rmiClientSocketFactory; + private final @Nullable RMIServerSocketFactory rmiServerSocketFactory; + private final @Nullable String objectInputFilterFactoryClassName; private final int connectionMaintenanceInterval; private final int connectionLimit; @@ -146,9 +147,9 @@ static final class DefaultBuilder implements Builder { private int serverAdminPort; private boolean sslEnabled = true; private Supplier serverName = new DefaultServerName(); - private RMIClientSocketFactory rmiClientSocketFactory = new SslRMIClientSocketFactory(); - private RMIServerSocketFactory rmiServerSocketFactory = new SslRMIServerSocketFactory(); - private String objectInputFilterFactoryClassName; + private @Nullable RMIClientSocketFactory rmiClientSocketFactory = new SslRMIClientSocketFactory(); + private @Nullable RMIServerSocketFactory rmiServerSocketFactory = new SslRMIServerSocketFactory(); + private @Nullable String objectInputFilterFactoryClassName = OBJECT_INPUT_FILTER_FACTORY_CLASS_NAME.get(); private Integer connectionMaintenanceInterval = DEFAULT_CONNECTION_MAINTENANCE_INTERVAL; private int connectionLimit = -1; @@ -199,7 +200,7 @@ public DefaultBuilder sslEnabled(boolean sslEnabled) { } @Override - public DefaultBuilder objectInputFilterFactoryClassName(String objectInputFilterFactoryClassName) { + public DefaultBuilder objectInputFilterFactoryClassName(@Nullable String objectInputFilterFactoryClassName) { this.objectInputFilterFactoryClassName = objectInputFilterFactoryClassName; return this; } @@ -266,7 +267,7 @@ private static final class DefaultServerName implements Supplier { @Override public String get() { - String serverNamePrefix = SERVER_NAME_PREFIX.get(); + String serverNamePrefix = SERVER_NAME_PREFIX.getOrThrow(); if (serverNamePrefix.isEmpty()) { throw new IllegalArgumentException("serverNamePrefix must not be empty"); } diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerLocator.java b/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerLocator.java index 9b36295f66..f3aae74474 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerLocator.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/DefaultServerLocator.java @@ -18,6 +18,7 @@ */ package is.codion.common.rmi.server; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -108,8 +109,8 @@ private static void addIfReachable(Str } } - private static Server getIfReachable(Server server, - int requestedServerPort) throws RemoteException { + private static @Nullable Server getIfReachable(Server server, + int requestedServerPort) throws RemoteException { ServerInformation serverInformation = server.serverInformation(); if (requestedServerPort != -1 && serverInformation.serverPort() != requestedServerPort) { LOG.warn("Server \"{}\" is serving on port {}, requested port was {}", @@ -126,10 +127,10 @@ private static Server getIfReach static final class DefaultBuilder implements Server.Locator.Builder { - private String hostName = ServerConfiguration.RMI_SERVER_HOSTNAME.get(); - private String namePrefix = ServerConfiguration.SERVER_NAME_PREFIX.get(); - private int registryPort = ServerConfiguration.REGISTRY_PORT.get(); - private int port = ServerConfiguration.SERVER_PORT.get(); + private String hostName = ServerConfiguration.RMI_SERVER_HOSTNAME.getOrThrow(); + private String namePrefix = ServerConfiguration.SERVER_NAME_PREFIX.getOrThrow(); + private int registryPort = ServerConfiguration.REGISTRY_PORT.getOrThrow(); + private int port = ServerConfiguration.SERVER_PORT.getOrThrow(); @Override public Builder hostName(String hostName) { diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/ServerConfiguration.java b/common/rmi/src/main/java/is/codion/common/rmi/server/ServerConfiguration.java index 693856fc48..80f29e124a 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/ServerConfiguration.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/ServerConfiguration.java @@ -22,6 +22,8 @@ import is.codion.common.Text; import is.codion.common.property.PropertyValue; +import org.jspecify.annotations.Nullable; + import java.rmi.registry.Registry; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; @@ -296,7 +298,7 @@ interface Builder> { * @param objectInputFilterFactoryClassName the object input filter factory class name * @return this builder instance */ - B objectInputFilterFactoryClassName(String objectInputFilterFactoryClassName); + B objectInputFilterFactoryClassName(@Nullable String objectInputFilterFactoryClassName); /** * @param connectionMaintenanceInterval the interval between server connection maintenance runs, in milliseconds. @@ -342,10 +344,9 @@ static > Builder builder(int serverPort, int registryPor */ static > Builder builderFromSystemProperties() { return (Builder) builder(SERVER_PORT.getOrThrow(), REGISTRY_PORT.getOrThrow()) - .auxiliaryServerFactoryClassNames(Text.parseCommaSeparatedValues(AUXILIARY_SERVER_FACTORY_CLASS_NAMES.get())) - .adminPort(ADMIN_PORT.get()) - .sslEnabled(SSL_ENABLED.get()) - .connectionMaintenanceInterval(CONNECTION_MAINTENANCE_INTERVAL.get()) - .objectInputFilterFactoryClassName(OBJECT_INPUT_FILTER_FACTORY_CLASS_NAME.get()); + .auxiliaryServerFactoryClassNames(Text.parseCommaSeparatedValues(AUXILIARY_SERVER_FACTORY_CLASS_NAMES.getOrThrow())) + .adminPort(ADMIN_PORT.getOrThrow()) + .sslEnabled(SSL_ENABLED.getOrThrow()) + .connectionMaintenanceInterval(CONNECTION_MAINTENANCE_INTERVAL.getOrThrow()); } } diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/WhitelistInputFilterFactory.java b/common/rmi/src/main/java/is/codion/common/rmi/server/WhitelistInputFilterFactory.java index dabc03f840..95a960adb0 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/WhitelistInputFilterFactory.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/WhitelistInputFilterFactory.java @@ -42,7 +42,7 @@ public final class WhitelistInputFilterFactory implements ObjectInputFilterFacto @Override public ObjectInputFilter createObjectInputFilter() { String whitelist = SERIALIZATION_FILTER_WHITELIST.getOrThrow(); - if (SERIALIZATION_FILTER_DRYRUN.get()) { + if (SERIALIZATION_FILTER_DRYRUN.getOrThrow()) { return SerializationWhitelist.whitelistDryRun(whitelist); } diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/exception/package-info.java b/common/rmi/src/main/java/is/codion/common/rmi/server/exception/package-info.java new file mode 100644 index 0000000000..b71046461c --- /dev/null +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/exception/package-info.java @@ -0,0 +1,23 @@ +/* + * This file is part of Codion. + * + * Codion is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Codion is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Codion. If not, see . + * + * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. + */ +/** + *

    RMI server related exceptions. + */ +@org.jspecify.annotations.NullMarked +package is.codion.common.rmi.server.exception; \ No newline at end of file diff --git a/common/rmi/src/main/java/is/codion/common/rmi/server/package-info.java b/common/rmi/src/main/java/is/codion/common/rmi/server/package-info.java index 8649ea5af7..3bd99022ec 100644 --- a/common/rmi/src/main/java/is/codion/common/rmi/server/package-info.java +++ b/common/rmi/src/main/java/is/codion/common/rmi/server/package-info.java @@ -17,7 +17,8 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * Package configuration values: + *

    RMI server related classes. + *

    Package configuration values: *

      *
    • {@link is.codion.common.rmi.server.ServerConfiguration#RMI_SERVER_HOSTNAME} *
    • {@link is.codion.common.rmi.server.ServerConfiguration#SERVER_NAME_PREFIX} @@ -35,4 +36,5 @@ *
    • {@link is.codion.common.rmi.server.WhitelistInputFilterFactory#SERIALIZATION_FILTER_DRYRUN} *
    */ +@org.jspecify.annotations.NullMarked package is.codion.common.rmi.server; \ No newline at end of file diff --git a/common/rmi/src/main/java/module-info.java b/common/rmi/src/main/java/module-info.java index 9520f9e61b..b25a14be2d 100644 --- a/common/rmi/src/main/java/module-info.java +++ b/common/rmi/src/main/java/module-info.java @@ -17,7 +17,7 @@ * Copyright (c) 2023 - 2024, Björn Darri Sigurðsson. */ /** - * RMI client/server classes, such as: + *

    RMI client/server classes. *

      *
    • {@link is.codion.common.rmi.client.ConnectionRequest} *
    • {@link is.codion.common.rmi.server.Server} @@ -31,7 +31,9 @@ * @uses is.codion.common.rmi.server.ObjectInputFilterFactory * @provides is.codion.common.rmi.server.ObjectInputFilterFactory */ +@org.jspecify.annotations.NullMarked module is.codion.common.rmi { + requires transitive org.jspecify; requires org.slf4j; requires jdk.management; requires nl.altindag.ssl; diff --git a/framework/server/src/main/java/is/codion/framework/server/DefaultEntityServerConfiguration.java b/framework/server/src/main/java/is/codion/framework/server/DefaultEntityServerConfiguration.java index 81e7ecdd75..8197f02a65 100644 --- a/framework/server/src/main/java/is/codion/framework/server/DefaultEntityServerConfiguration.java +++ b/framework/server/src/main/java/is/codion/framework/server/DefaultEntityServerConfiguration.java @@ -170,17 +170,14 @@ public Map clientTypeIdleConnectionTimeouts() { static EntityServerConfiguration.Builder builderFromSystemProperties() { Builder builder = new DefaultBuilder(SERVER_PORT.getOrThrow(), REGISTRY_PORT.getOrThrow()) .auxiliaryServerFactoryClassNames(Text.parseCommaSeparatedValues(AUXILIARY_SERVER_FACTORY_CLASS_NAMES.get())) - .sslEnabled(SSL_ENABLED.get()) - .objectInputFilterFactoryClassName(OBJECT_INPUT_FILTER_FACTORY_CLASS_NAME.get()) + .sslEnabled(SSL_ENABLED.getOrThrow()) .adminPort(ADMIN_PORT.getOrThrow()) - .connectionLimit(CONNECTION_LIMIT.get()) + .connectionLimit(CONNECTION_LIMIT.getOrThrow()) .database(Database.instance()) .domainClassNames(Text.parseCommaSeparatedValues(DOMAIN_MODEL_CLASSES.get())) .connectionPoolUsers(Text.parseCommaSeparatedValues(CONNECTION_POOL_USERS.get()).stream() .map(User::parse) - .collect(toList())) - .clientLogging(CLIENT_LOGGING.get()) - .idleConnectionTimeout(IDLE_CONNECTION_TIMEOUT.get()); + .collect(toList())); Map clientTypeIdleConnectionTimeoutMap = new HashMap<>(); for (String clientTimeout : Text.parseCommaSeparatedValues(CLIENT_CONNECTION_TIMEOUT.get())) { String[] split = clientTimeout.split(":"); @@ -209,8 +206,8 @@ static final class DefaultBuilder implements Builder { private Database database; private User adminUser; - private boolean clientLogging = CLIENT_LOGGING.get(); - private int idleConnectionTimeout = IDLE_CONNECTION_TIMEOUT.get(); + private boolean clientLogging = CLIENT_LOGGING.getOrThrow(); + private int idleConnectionTimeout = IDLE_CONNECTION_TIMEOUT.getOrThrow(); private String connectionPoolFactory; private final Collection domainClassNames = new HashSet<>(); private final Collection connectionPoolUsers = new HashSet<>(); @@ -223,7 +220,7 @@ static final class DefaultBuilder implements Builder { throw new IllegalStateException("Database must be set before initializing server name"); } - String serverNamePrefix = SERVER_NAME_PREFIX.get(); + String serverNamePrefix = SERVER_NAME_PREFIX.getOrThrow(); if (serverNamePrefix.isEmpty()) { throw new IllegalArgumentException("serverNamePrefix must not be empty"); } diff --git a/settings.gradle b/settings.gradle index 2124d54bec..e5150e2702 100644 --- a/settings.gradle +++ b/settings.gradle @@ -201,6 +201,7 @@ dependencyResolutionManagement { version("tomcat", "11.0.2") version("jasperreports", "7.0.1") + version("jspecify", "1.0.0") library("slf4j-api", "org.slf4j", "slf4j-api").versionRef("slf4j.api") library("logback-core", "ch.qos.logback", "logback-core").versionRef("logback") @@ -231,6 +232,8 @@ dependencyResolutionManagement { library("log4j-core", "org.apache.logging.log4j", "log4j-core").versionRef("log4j") library("tomcat-jdbc", "org.apache.tomcat", "tomcat-jdbc").versionRef("tomcat") + library("jspecify", "org.jspecify", "jspecify").versionRef("jspecify") + library("jasperreports", "net.sf.jasperreports", "jasperreports").versionRef("jasperreports") library("jasperreports-jdt", "net.sf.jasperreports", "jasperreports-jdt").versionRef("jasperreports") }