DatasetAnnotation.java
package org.hammer.audio.experimental.acoustic.dataset;
import java.util.Map;
import java.util.Objects;
/**
* Annotation attached to one recording.
*
* @param startSeconds annotation start time in seconds (inclusive)
* @param endSeconds annotation end time in seconds (inclusive)
* @param label annotation label (for example "mosquito_event")
* @param metadata annotation metadata values; never {@code null}
*/
public record DatasetAnnotation(
double startSeconds, double endSeconds, String label, Map<String, String> metadata) {
public DatasetAnnotation {
Objects.requireNonNull(label, "label");
Objects.requireNonNull(metadata, "metadata");
if (!Double.isFinite(startSeconds) || startSeconds < 0.0) {
throw new IllegalArgumentException("startSeconds must be finite and >= 0");
}
if (!Double.isFinite(endSeconds) || endSeconds < startSeconds) {
throw new IllegalArgumentException("endSeconds must be finite and >= startSeconds");
}
if (label.isBlank()) {
throw new IllegalArgumentException("label must not be blank");
}
metadata = validateAndCopyMap(metadata, "metadata");
}
private static Map<String, String> validateAndCopyMap(Map<String, String> values, String field) {
for (Map.Entry<String, String> entry : values.entrySet()) {
String key = Objects.requireNonNull(entry.getKey(), field + " key");
String value = Objects.requireNonNull(entry.getValue(), field + " value");
if (key.isBlank()) {
throw new IllegalArgumentException(field + " keys must not be blank");
}
if (value.isBlank()) {
throw new IllegalArgumentException(field + " values must not be blank");
}
}
return Map.copyOf(values);
}
}