Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<!-- Maven Central Publishing -->
<central.autoPublish>false</central.autoPublish>

<!-- Dependency Versions -->
<junit-jupiter.version>5.11.4</junit-jupiter.version>

<!-- Plugin Versions -->
<plugin.central.publishing.version>0.9.0</plugin.central.publishing.version>
<plugin.code-format.version>2.29</plugin.code-format.version>
Expand All @@ -73,9 +76,23 @@
<plugin.maven.gpg.version>3.2.8</plugin.maven.gpg.version>
<plugin.maven.install.version>3.1.4</plugin.maven.install.version>
<plugin.maven.site.version>3.21.0</plugin.maven.site.version>
<plugin.jacoco.version>0.8.14</plugin.jacoco.version>
</properties>

<dependencies>
<!-- Test Dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -199,6 +216,37 @@
</plugins>
</build>
</profile>
<profile>
<id>metrics</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${plugin.jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@
public class ArrayListBuilder<T> {
private final List<T> mList = new ArrayList<>();

/** Creates an empty ArrayListBuilder. */
public ArrayListBuilder() {}

/**
* Creates an ArrayListBuilder initialized with the elements from the given list.
*
* @param initialList list to initialize from
*/
public ArrayListBuilder(List<T> initialList) {
if (initialList != null) {
mList.addAll(initialList);
}
}

/**
* Appends the element to the end of the internal list. Calling add-function on inner ArrayList
* field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
public class HashMapBuilder<K, V> {
private final Map<K, V> mMap = new HashMap<>();

/** Creates an empty HashMapBuilder. */
public HashMapBuilder() {}

/**
* Creates a HashMapBuilder initialized with the mappings from the given map.
*
* @param initialMap map to initialize from
*/
public HashMapBuilder(Map<K, V> initialMap) {
if (initialMap != null) {
mMap.putAll(initialMap);
}
}

/**
* Associates the specified value with the specified key in this map. Using an inner HashMap
* implementation. If the key already exists in the map, the old value is replaced.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,22 @@
public class HashSetBuilder<T> {
private final Set<T> mSet = new HashSet<>();

/** Creates an empty HashSetBuilder. */
public HashSetBuilder() {}

/**
* Creates a HashSetBuilder initialized with the elements from the given set.
*
* @param initialSet set to initialize from
*/
public HashSetBuilder(Set<T> initialSet) {
if (initialSet != null) {
mSet.addAll(initialSet);
}
}

/**
* Adds the specified element to this set if it is not already present. Calling add-function on
* inner HashSet field.
* Appends the element to the internal set. Calling add-function on inner HashSet field.
*
* @param element element to be appended
* @return current instance of ArrayListBuilder for using in stream-notation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,27 @@
* @param <T> the value type
* @param value the underlying value (may be {@code null})
* @param isChanged whether the value was explicitly changed by the builder API
* @param isInitial whether the value is an initial value from an existing instance
*/
public record TrackedValue<T>(T value, boolean isChanged) {
public record TrackedValue<T>(T value, boolean isChanged, boolean isInitial) {

/**
* Executes the provided {@link Consumer} only if this value has been explicitly changed.
* Checks if this value has been set (either as initial value or changed).
*
* @param consumer action to perform with the current {@link #value()} when {@link #isChanged()}
* is {@code true}
* @return true if the value is set (initial or changed), false if unset
*/
public void ifChanged(Consumer<T> consumer) {
if (isChanged) {
public boolean isSet() {
return isChanged || isInitial;
}

/**
* Executes the provided {@link Consumer} only if this value has been set (initial value or
* changed).
*
* @param consumer action to perform with the current {@link #value()}
*/
public void ifSet(Consumer<T> consumer) {
if (isSet()) {
consumer.accept(value);
}
}
Expand All @@ -62,10 +72,11 @@ public void ifChanged(Consumer<T> consumer) {
* Creates a tracked value representing an unset state (no change made).
*
* @param <T> the value type
* @return an instance with {@code value == null} and {@code isChanged == false}
* @return an instance with {@code value == null}, {@code isChanged == false}, and {@code
* isInitial == false}
*/
public static <T> TrackedValue<T> unsetValue() {
return new TrackedValue<>(null, false);
return new TrackedValue<>(null, false, false);
}

/**
Expand All @@ -74,10 +85,11 @@ public static <T> TrackedValue<T> unsetValue() {
*
* @param <T> the value type
* @param value the initial value (may be {@code null})
* @return an instance with the given value and {@code isChanged == false}
* @return an instance with the given value, {@code isChanged == false}, and {@code isInitial ==
* true}
*/
public static <T> TrackedValue<T> initialValue(T value) {
return new TrackedValue<>(value, false);
return new TrackedValue<>(value, false, true);
}

/**
Expand All @@ -88,6 +100,6 @@ public static <T> TrackedValue<T> initialValue(T value) {
* @return an instance with the given value and {@code isChanged == true}
*/
public static <T> TrackedValue<T> changedValue(T value) {
return new TrackedValue<>(value, true);
return new TrackedValue<>(value, true, false);
}
}
Empty file removed core/src/test/java/.gitkeep
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* MIT License
*
* Copyright (c) 2025 Andreas Igel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package org.javahelpers.simple.builders.core.builders;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;

class ArrayListBuilderTest {

@Test
void shouldCreateEmptyBuilder() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>();
List<String> result = builder.build();

assertNotNull(result);
assertTrue(result.isEmpty());
}

@Test
void shouldCreateBuilderWithInitialList() {
List<String> initial = Arrays.asList("item1", "item2", "item3");

ArrayListBuilder<String> builder = new ArrayListBuilder<>(initial);
List<String> result = builder.build();

assertNotNull(result);
assertEquals(3, result.size());
assertEquals("item1", result.get(0));
assertEquals("item2", result.get(1));
assertEquals("item3", result.get(2));
}

@Test
void shouldHandleNullInitialList() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>(null);
List<String> result = builder.build();

assertNotNull(result);
assertTrue(result.isEmpty());
}

@Test
void shouldAllowAddingToInitializedList() {
List<String> initial = Arrays.asList("item1", "item2");

ArrayListBuilder<String> builder = new ArrayListBuilder<>(initial);
builder.add("item3").add("item4");
List<String> result = builder.build();

assertNotNull(result);
assertEquals(4, result.size());
assertEquals("item1", result.get(0));
assertEquals("item2", result.get(1));
assertEquals("item3", result.get(2));
assertEquals("item4", result.get(3));
}

@Test
void shouldAddSingleElement() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>();
builder.add("test");
List<String> result = builder.build();

assertEquals(1, result.size());
assertEquals("test", result.get(0));
}

@Test
void shouldAddMultipleElements() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>();
builder.add("first").add("second").add("third");
List<String> result = builder.build();

assertEquals(3, result.size());
assertEquals("first", result.get(0));
assertEquals("second", result.get(1));
assertEquals("third", result.get(2));
}

@Test
void shouldAddAllFromCollection() {
ArrayListBuilder<Integer> builder = new ArrayListBuilder<>();
builder.addAll(Arrays.asList(1, 2, 3));
List<Integer> result = builder.build();

assertEquals(3, result.size());
assertEquals(1, result.get(0));
assertEquals(2, result.get(1));
assertEquals(3, result.get(2));
}

@Test
void shouldChainAddAndAddAll() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>();
builder.add("first").addAll(Arrays.asList("second", "third")).add("fourth");
List<String> result = builder.build();

assertEquals(4, result.size());
assertEquals("first", result.get(0));
assertEquals("second", result.get(1));
assertEquals("third", result.get(2));
assertEquals("fourth", result.get(3));
}

@Test
void shouldReturnThisForFluentInterface() {
ArrayListBuilder<String> builder = new ArrayListBuilder<>();
ArrayListBuilder<String> result = builder.add("test");

assertEquals(builder, result);
}
}
Loading
Loading