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
15 changes: 13 additions & 2 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import io.spine.dependency.Dependency
*/
@Suppress("unused")
object Ksp : Dependency() {
override val version = "2.3.0"
override val version = "2.3.6"
val dogfoodingVersion = version
override val group = "com.google.devtools.ksp"

Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ package io.spine.dependency.local
*/
@Suppress("ConstPropertyName", "unused")
object Base {
const val version = "2.0.0-SNAPSHOT.385"
const val versionForBuildScript = "2.0.0-SNAPSHOT.385"
const val version = "2.0.0-SNAPSHOT.386"
const val versionForBuildScript = "2.0.0-SNAPSHOT.386"
const val group = Spine.group
private const val prefix = "spine"
const val libModule = "$prefix-base"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ object Compiler : Dependency() {
* The version of the Compiler dependencies.
*/
override val version: String
private const val fallbackVersion = "2.0.0-SNAPSHOT.040"
private const val fallbackVersion = "2.0.0-SNAPSHOT.041"

/**
* The distinct version of the Compiler used by other build tools.
Expand All @@ -81,7 +81,7 @@ object Compiler : Dependency() {
* transitive dependencies, this is the version used to build the project itself.
*/
val dogfoodingVersion: String
private const val fallbackDfVersion = "2.0.0-SNAPSHOT.039"
private const val fallbackDfVersion = "2.0.0-SNAPSHOT.041"

/**
* The artifact for the Compiler Gradle plugin.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ package io.spine.dependency.local
@Suppress("ConstPropertyName", "unused")
object ToolBase {
const val group = Spine.toolsGroup
const val version = "2.0.0-SNAPSHOT.374"
const val dogfoodingVersion = "2.0.0-SNAPSHOT.374"
const val version = "2.0.0-SNAPSHOT.375"
const val dogfoodingVersion = "2.0.0-SNAPSHOT.375"

const val lib = "$group:tool-base:$version"
const val classicCodegen = "$group:classic-codegen:$version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object Validation {
/**
* The version of the Validation library artifacts.
*/
const val version = "2.0.0-SNAPSHOT.405"
const val version = "2.0.0-SNAPSHOT.406"

/**
* The last version of Validation compatible with ProtoData.
Expand Down
324 changes: 158 additions & 166 deletions dependencies.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/_examples
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Add the Validation plugin to the build.
```kotlin
plugins {
module
id("io.spine.validation") version "2.0.0-SNAPSHOT.406"
id("io.spine.validation") version "2.0.0-SNAPSHOT.407"
}
```

Expand Down
151 changes: 151 additions & 0 deletions jvm-runtime/src/main/java/io/spine/validation/ExceptionFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Copyright 2025, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.validation;

import com.google.common.collect.ImmutableList;
import com.google.protobuf.Message;
import com.google.protobuf.ProtocolMessageEnum;
import com.google.protobuf.Value;
import io.spine.annotation.Internal;
import io.spine.base.Error;
import io.spine.protobuf.AnyPacker;
import io.spine.type.MessageClass;

import java.util.Map;

import static java.lang.String.format;

/**
* A helper class for building exceptions used to report invalid {@code Message}s,
* which have fields that violate validation constraint(s).
*
* @param <E>
* the type of {@code Exception} to build
* @param <M>
* the type of the {@code Message}, typically it would be a grouping interface such as
* {@link io.spine.base.EventMessage} or {@link io.spine.base.CommandMessage}
* @param <C>
* the type of the {@linkplain io.spine.type.MessageClass} of {@code |M|}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javadoc for type parameter C contains {@code |M|}, which looks like a formatting artifact and will render incorrectly. Replace it with the intended reference (e.g. {@code M}) so the generated docs are correct.

Suggested change
* the type of the {@linkplain io.spine.type.MessageClass} of {@code |M|}
* the type of the {@linkplain io.spine.type.MessageClass} of {@code M}

Copilot uses AI. Check for mistakes.
* @param <R>
* the type of error code to use for error reporting; must be a Protobuf enum value
*/
@Internal
public abstract class ExceptionFactory<E extends Exception,
M extends Message,
C extends MessageClass<?>,
Comment thread
alexander-yevsyukov marked this conversation as resolved.
R extends ProtocolMessageEnum> {

private final ImmutableList<ConstraintViolation> constraintViolations;
private final M message;

/**
* Creates an {@code ExceptionFactory} instance for a given message and
* constraint violations.
*
* @param message
* an invalid event message
* @param violations
* constraint violations for the event message
Comment on lines +70 to +72
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constructor parameter docs refer to an “event message”, but ExceptionFactory is generic over any invalid Message type (including commands). Please update the wording to avoid misleading API docs.

Suggested change
* an invalid event message
* @param violations
* constraint violations for the event message
* an invalid message
* @param violations
* constraint violations for the message

Copilot uses AI. Check for mistakes.
*/
protected ExceptionFactory(M message, Iterable<ConstraintViolation> violations) {
this.constraintViolations = ImmutableList.copyOf(violations);
this.message = message;
}

/**
* Obtains a {@code MessageClass} for an invalid {@code Message}.
*/
protected abstract C getMessageClass();

/**
* Obtains an error code to use for error reporting.
*/
protected abstract R getErrorCode();

/**
* Obtains an error text to use for error reporting.
*
* <p>This text will also be used as a base for an exception message to generate.
*/
protected abstract String getErrorText();

/**
* Obtains the {@code Message}-specific type attributes for error reporting.
*/
protected abstract Map<String, Value> getMessageTypeAttribute(M message);

/**
* Defines the way to create an instance of exception basing on the source {@code Message},
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The phrase “create an instance of exception basing on…” is grammatically incorrect and makes the Javadoc harder to read. Please reword it (e.g. “based on”).

Suggested change
* Defines the way to create an instance of exception basing on the source {@code Message},
* Defines how to create an exception instance based on the source {@code Message},

Copilot uses AI. Check for mistakes.
* exception text, and a generated {@code Error}.
*/
protected abstract E createException(String exceptionMsg, M message, Error error);

private String formatExceptionMessage() {
return format("%s. Message class: `%s`. %s",
getErrorText(), getMessageClass(), violationsText());
}

private Error createError() {
var validationError = error();
var errorCode = getErrorCode();
var errorType = errorCode.getDescriptorForType()
.getFullName();
var errorText = errorText();

var error = Error.newBuilder()
.setType(errorType)
.setCode(errorCode.getNumber())
.setDetails(AnyPacker.pack(validationError))
.setMessage(errorText)
.putAllAttributes(getMessageTypeAttribute(message));
return error.build();
}

private ValidationError error() {
return ValidationError.newBuilder()
.addAllConstraintViolation(constraintViolations)
.build();
}

private String errorText() {
var errorTextTemplate = getErrorText();
var violationsText = violationsText();
return format("%s %s", errorTextTemplate, violationsText);
}

private String violationsText() {
return ViolationText.ofAll(constraintViolations);
}

/**
* Creates an exception instance for an invalid message which has fields that
* violate validation constraint(s).
*/
public E newException() {
return createException(formatExceptionMessage(), message, createError());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.InlineMe;
import io.spine.base.ErrorWithMessage;
import io.spine.validation.diags.ViolationText;

import java.io.Serial;
import java.util.List;

/**
Expand All @@ -39,6 +39,7 @@
public class ValidationException
extends RuntimeException implements ErrorWithMessage<ValidationError> {

@Serial
private static final long serialVersionUID = 0L;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2025, TeamDev. All rights reserved.
* Copyright 2026, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,13 +24,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.validation.diags;
package io.spine.validation;

import com.google.protobuf.Message;
import io.spine.annotation.Internal;
import io.spine.base.Field;
import io.spine.option.OptionsProto;
import io.spine.validation.ConstraintViolation;

import java.util.Collection;

Expand Down

This file was deleted.

Loading
Loading