RandomLiteralGenerator.java
/*******************************************************************************
* Copyright (c) 2025 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.lmdb.benchmark;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.function.Supplier;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.XSD;
/**
* A utility class for generating random RDF literals using a variety of data types, including numeric types (integer,
* float, double, etc.), boolean, string, and date/time types.
* <p>
* This class is primarily useful for testing and demonstration purposes where randomized literal values are needed.
*/
public class RandomLiteralGenerator {
/**
* The {@link ValueFactory} used to create RDF literals.
*/
private final ValueFactory vf;
/**
* The {@link Random} instance used to generate random values.
*/
private final Random random;
/**
* A list of suppliers, each of which produces a different type of RDF literal.
*/
private List<Supplier<Literal>> literalSuppliers;
/**
* Constructs a new {@code RandomLiteralGenerator} with the specified {@link ValueFactory} and {@link Random}
* instances.
*
* @param vf the value factory used to create RDF literals
* @param random the random generator used to generate random values
*/
public RandomLiteralGenerator(ValueFactory vf, Random random) {
this.vf = vf;
this.random = random;
init();
}
/**
* Initializes the list of literal suppliers with a variety of data types. Includes decimals, doubles, floats,
* integers, booleans, strings, unsigned values, and date/time literals.
*/
private void init() {
literalSuppliers = Arrays.asList(
// Decimal
() -> vf.createLiteral(BigDecimal.valueOf(random.nextDouble() * 100000 - 50000)),
// Double
() -> vf.createLiteral(random.nextBoolean() ? Double.NaN : random.nextDouble() * 1000),
() -> vf.createLiteral(random.nextBoolean() ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY),
() -> vf.createLiteral((double) random.nextInt(1000)),
// Float
() -> vf.createLiteral(random.nextBoolean() ? Float.NaN : random.nextFloat() * 100),
() -> vf.createLiteral(random.nextBoolean() ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY),
// Integer
() -> vf.createLiteral(BigInteger.valueOf(random.nextInt(1_000_000) - 500_000)),
() -> vf.createLiteral(random.nextInt(1_000_000) - 500_000),
// Long
() -> vf.createLiteral(random.nextLong()),
// Short
() -> vf.createLiteral((short) (random.nextInt(Short.MAX_VALUE - Short.MIN_VALUE) + Short.MIN_VALUE)),
// Byte
() -> vf.createLiteral((byte) (random.nextInt(Byte.MAX_VALUE - Byte.MIN_VALUE) + Byte.MIN_VALUE)),
// Unsigned Int types
() -> vf.createLiteral(String.valueOf(random.nextInt(1 << 16)), XSD.UNSIGNED_SHORT),
() -> vf.createLiteral(String.valueOf(random.nextInt(1 << 8)), XSD.UNSIGNED_BYTE),
() -> vf.createLiteral(String.valueOf(random.nextInt(100000)), XSD.UNSIGNED_INT),
// Positive/Negative Integer
() -> vf.createLiteral(String.valueOf(1 + random.nextInt(1_000_000)), XSD.POSITIVE_INTEGER),
() -> vf.createLiteral("-" + (1 + random.nextInt(1_000_000)), XSD.NEGATIVE_INTEGER),
// Non-negative/Non-positive
() -> vf.createLiteral(String.valueOf(random.nextInt(1_000_000)), XSD.NON_NEGATIVE_INTEGER),
() -> vf.createLiteral("-" + random.nextInt(1_000_000), XSD.NON_POSITIVE_INTEGER),
// String
() -> vf.createLiteral(UUID.randomUUID().toString().substring(0, 8), XSD.STRING),
() -> vf.createLiteral("testString" + random.nextInt(100), XSD.STRING),
// Boolean
() -> vf.createLiteral(random.nextBoolean()),
// Date and DateTime
() -> vf.createLiteral(
LocalDate.of(1970 + random.nextInt(100), 1 + random.nextInt(12), 1 + random.nextInt(28))),
() -> vf.createLiteral(
LocalDateTime.of(1970 + random.nextInt(100), 1 + random.nextInt(12), 1 + random.nextInt(28),
random.nextInt(24), random.nextInt(60), random.nextInt(60)))
);
}
/**
* Generates a random RDF literal.
*
* @return a randomly selected RDF literal
*/
public Literal createRandomLiteral() {
return literalSuppliers.get(random.nextInt(literalSuppliers.size())).get();
}
}