You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vv...@apache.org on 2022/06/20 11:23:21 UTC
[ignite-3] branch main updated: IGNITE-17148 Support for abstract configuration (#878)
This is an automated email from the ASF dual-hosted git repository.
vveider pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 9c90a8652 IGNITE-17148 Support for abstract configuration (#878)
9c90a8652 is described below
commit 9c90a865246a49b2d6006375d6c0ed09df52e472
Author: Kirill Tkalenko <tk...@yandex.ru>
AuthorDate: Mon Jun 20 14:23:16 2022 +0300
IGNITE-17148 Support for abstract configuration (#878)
---
.../processor/AbstractProcessorTest.java | 8 +-
...Test.java => ItConfigurationProcessorTest.java} | 204 ++++++++-
.../AbstractConfigConfigurationSchema.java} | 25 +-
...ConfigWithInjectedNameConfigurationSchema.java} | 19 +-
...ctConfigWithInternalIdConfigurationSchema.java} | 20 +-
.../AbstractRootConfigConfigurationSchema.java} | 20 +-
.../SimpleConfigConfigurationSchema.java} | 13 +-
.../SimpleConfigRootConfigurationSchema.java} | 17 +-
...yAbstractConfigurationConfigurationSchema.java} | 16 +-
...amesWithAbstractConfigConfigurationSchema.java} | 15 +-
...NameWithAbstractConfigConfigurationSchema.java} | 20 +-
...alIdWithAbstractConfigConfigurationSchema.java} | 21 +-
...yAbstractConfigurationConfigurationSchema.java} | 18 +-
...amesWithAbstractConfigConfigurationSchema.java} | 19 +-
...edNameInAbstractConfigConfigurationSchema.java} | 19 +-
...rnalIdInAbstractConfigConfigurationSchema.java} | 19 +-
...ConfigMustContainsNameConfigurationSchema.java} | 22 +-
...ibleSchemaAnnotations0ConfigurationSchema.java} | 18 +-
...ibleSchemaAnnotations1ConfigurationSchema.java} | 18 +-
...ibleSchemaAnnotations2ConfigurationSchema.java} | 18 +-
...ibleSchemaAnnotations3ConfigurationSchema.java} | 18 +-
...ibleSchemaAnnotations4ConfigurationSchema.java} | 18 +-
.../MustNotBeSuperClassConfigurationSchema.java} | 17 +-
...otContainPolymorphicIdConfigurationSchema.java} | 19 +-
.../StaticConstantsConfigurationSchema.java | 4 +-
...{Processor.java => ConfigurationProcessor.java} | 463 ++++++++++++++-------
...n.java => ConfigurationProcessorException.java} | 19 +-
...Utils.java => ConfigurationProcessorUtils.java} | 59 ++-
.../services/javax.annotation.processing.Processor | 2 +-
...t.java => ConfigurationProcessorUtilsTest.java} | 8 +-
...ConfigValue.java => AbstractConfiguration.java} | 21 +-
.../ignite/configuration/annotation/Config.java | 2 +-
.../configuration/annotation/ConfigValue.java | 2 +-
.../configuration/annotation/InjectedName.java | 4 +-
modules/configuration/README.md | 44 +-
.../asm/ConfigurationAsmGenerator.java | 40 +-
.../internal/configuration/tree/InnerNode.java | 8 +
.../configuration/util/ConfigurationUtil.java | 1 -
.../configuration/validation/ValidationUtil.java | 2 +-
.../asm/ConfigurationAsmGeneratorTest.java | 99 ++++-
.../ignite/internal/util/CollectionUtils.java | 62 ++-
.../ignite/internal/util/CollectionUtilsTest.java | 90 +++-
42 files changed, 1088 insertions(+), 463 deletions(-)
diff --git a/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/AbstractProcessorTest.java b/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/AbstractProcessorTest.java
index 856b13c81..c7a5987be 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/AbstractProcessorTest.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/AbstractProcessorTest.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.configuration.processor;
import static com.google.testing.compile.Compiler.javac;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getChangeName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getViewName;
import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
@@ -47,7 +49,7 @@ public class AbstractProcessorTest {
List<JavaFileObject> fileObjects = fileNames.stream().map(JavaFileObjects::forResource).collect(Collectors.toList());
- return javac().withProcessors(new Processor()).compile(fileObjects);
+ return javac().withProcessors(new ConfigurationProcessor()).compile(fileObjects);
}
/**
@@ -68,8 +70,8 @@ public class AbstractProcessorTest {
* @return ConfigSet.
*/
protected static ConfigSet getConfigSet(ClassName clazz, final Map<ClassName, JavaFileObject> generatedClasses) {
- final ClassName viewName = Utils.getViewName(clazz);
- final ClassName changeName = Utils.getChangeName(clazz);
+ final ClassName viewName = getViewName(clazz);
+ final ClassName changeName = getChangeName(clazz);
final JavaFileObject viewClass = generatedClasses.get(viewName);
final JavaFileObject changeClass = generatedClasses.get(changeName);
diff --git a/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItProcessorTest.java b/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItConfigurationProcessorTest.java
similarity index 65%
rename from modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItProcessorTest.java
rename to modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItConfigurationProcessorTest.java
index 7d10716c5..11e696531 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItProcessorTest.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/java/org/apache/ignite/internal/configuration/processor/ItConfigurationProcessorTest.java
@@ -18,8 +18,12 @@
package org.apache.ignite.internal.configuration.processor;
import static com.google.testing.compile.CompilationSubject.assertThat;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getChangeName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getConfigurationInterfaceName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getViewName;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.matchesRegex;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -29,6 +33,7 @@ import com.google.testing.compile.Compilation;
import com.squareup.javapoet.ClassName;
import java.util.Arrays;
import java.util.List;
+import java.util.regex.Pattern;
import org.apache.ignite.configuration.annotation.InjectedName;
import org.apache.ignite.configuration.annotation.InternalId;
import org.apache.ignite.configuration.annotation.Name;
@@ -41,7 +46,7 @@ import org.opentest4j.AssertionFailedError;
/**
* Test for basic code generation scenarios.
*/
-public class ItProcessorTest extends AbstractProcessorTest {
+public class ItConfigurationProcessorTest extends AbstractProcessorTest {
/**
* The simplest test for code generation.
*/
@@ -255,9 +260,9 @@ public class ItProcessorTest extends AbstractProcessorTest {
assertThat(compilation).succeededWithoutWarnings();
var generatedClasses = List.of(
- Utils.getViewName(schema).toString(),
- Utils.getChangeName(schema).toString(),
- Utils.getConfigurationInterfaceName(schema).toString()
+ getViewName(schema).toString(),
+ getChangeName(schema).toString(),
+ getConfigurationInterfaceName(schema).toString()
);
for (String generatedClass : generatedClasses) {
@@ -427,11 +432,186 @@ public class ItProcessorTest extends AbstractProcessorTest {
assertTrue(batchCompile.getBySchema(cls).allGenerated());
}
+ @Test
+ void testFailValidationForAbstractConfiguration() {
+ String packageName = "org.apache.ignite.internal.configuration.processor.abstractconfig.validation";
+
+ // Let's check the incompatible configuration schema annotations.
+
+ Pattern incompatibleAnotationsPattern = Pattern.compile(
+ ".*ConfigurationProcessorException: Class with @.* is not allowed with @.*"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "IncompatibleSchemaAnnotations0ConfigurationSchema"),
+ incompatibleAnotationsPattern
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "IncompatibleSchemaAnnotations1ConfigurationSchema"),
+ incompatibleAnotationsPattern
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "IncompatibleSchemaAnnotations2ConfigurationSchema"),
+ incompatibleAnotationsPattern
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "IncompatibleSchemaAnnotations3ConfigurationSchema"),
+ incompatibleAnotationsPattern
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "IncompatibleSchemaAnnotations4ConfigurationSchema"),
+ incompatibleAnotationsPattern
+ );
+
+ // Let's check other validations for abstract configuration.
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "MustNotBeSuperClassConfigurationSchema"),
+ "Class with @AbstractConfiguration should not have a superclass"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "MustNotContainPolymorphicIdConfigurationSchema"),
+ "Class with @AbstractConfiguration cannot have a field with @PolymorphicId"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "FieldWithInjectedNameFromAbstractConfigMustContainsNameConfigurationSchema"),
+ "Missing @Name for field"
+ );
+
+ // Let's check the validation of the abstract configuration descendants.
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigRootCanExtendOnlyAbstractConfigurationConfigurationSchema"),
+ "Superclass must have @AbstractConfiguration"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigCanExtendOnlyAbstractConfigurationConfigurationSchema"),
+ "Superclass must have @AbstractConfiguration"
+ );
+
+ // Let's check the search for a conflict of field names.
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigRootConflictFieldNamesWithAbstractConfigConfigurationSchema"),
+ "Duplicate field names are not allowed"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigConflictFieldNamesWithAbstractConfigConfigurationSchema"),
+ "Duplicate field names are not allowed"
+ );
+
+ // Let's check @InjectedName for descendants of abstract configuration.
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigRootMustNotContainInjectedNameInAbstractConfigConfigurationSchema"),
+ "Field with @InjectedName in superclass are not allowed"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigMustNotContainInjectedNameWithAbstractConfigConfigurationSchema"),
+ "Field with @InjectedName is already present in the superclass"
+ );
+
+ // Let's check @InternalId for descendants of abstract configuration.
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigRootMustNotContainInternalIdInAbstractConfigConfigurationSchema"),
+ "Field with @InternalId in superclass are not allowed"
+ );
+
+ assertThrowsEx(
+ IllegalStateException.class,
+ () -> batchCompile(packageName, "ConfigMustNotContainInternalIdWithAbstractConfigConfigurationSchema"),
+ "Field with @InternalId is already present in the superclass"
+ );
+ }
+
+ @Test
+ void testSuccessfulCodeGenerationAbstractConfigurationAndItsDescendants() {
+ String packageName = "org.apache.ignite.internal.configuration.processor.abstractconfig";
+
+ ClassName abstractConfigSchema = ClassName.get(packageName, "AbstractConfigConfigurationSchema");
+ ClassName abstractRootConfigSchema = ClassName.get(packageName, "AbstractRootConfigConfigurationSchema");
+
+ ClassName configSchema = ClassName.get(packageName, "SimpleConfigConfigurationSchema");
+ ClassName configRootSchema = ClassName.get(packageName, "SimpleConfigRootConfigurationSchema");
+
+ BatchCompilation batchCompile = batchCompile(abstractConfigSchema, abstractRootConfigSchema, configSchema, configRootSchema);
+
+ assertThat(batchCompile.getCompilationStatus()).succeededWithoutWarnings();
+
+ assertEquals(4 * 3, batchCompile.generated().size());
+
+ assertTrue(batchCompile.getBySchema(abstractConfigSchema).allGenerated());
+ assertTrue(batchCompile.getBySchema(abstractRootConfigSchema).allGenerated());
+ assertTrue(batchCompile.getBySchema(configSchema).allGenerated());
+ assertTrue(batchCompile.getBySchema(configRootSchema).allGenerated());
+
+ StringSubject configViewInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getViewName(configSchema).toString())
+ .contentsAsUtf8String();
+
+ StringSubject configRootViewInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getViewName(configRootSchema).toString())
+ .contentsAsUtf8String();
+
+ configViewInterfaceContent.contains("extends " + getViewName(abstractConfigSchema).simpleName());
+ configRootViewInterfaceContent.contains("extends " + getViewName(abstractRootConfigSchema).simpleName());
+
+ StringSubject configChangeInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getChangeName(configSchema).toString())
+ .contentsAsUtf8String();
+
+ StringSubject configRootChangeInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getChangeName(configRootSchema).toString())
+ .contentsAsUtf8String();
+
+ configChangeInterfaceContent.contains("extends " + getViewName(configSchema).simpleName()
+ + ", " + getChangeName(abstractConfigSchema).simpleName());
+
+ configRootChangeInterfaceContent.contains("extends " + getViewName(configRootSchema).simpleName()
+ + ", " + getChangeName(abstractRootConfigSchema).simpleName());
+
+ StringSubject configConfigurationInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getConfigurationInterfaceName(configSchema).toString())
+ .contentsAsUtf8String();
+
+ StringSubject configRootConfigurationInterfaceContent = assertThat(batchCompile.getCompilationStatus())
+ .generatedSourceFile(getConfigurationInterfaceName(configRootSchema).toString())
+ .contentsAsUtf8String();
+
+ configConfigurationInterfaceContent.contains("extends " + getConfigurationInterfaceName(abstractConfigSchema).simpleName());
+ configRootConfigurationInterfaceContent.contains("extends " + getConfigurationInterfaceName(abstractRootConfigSchema).simpleName());
+ }
+
/**
* Compile set of classes.
*
* @param packageName Package names.
- * @param classNames Simple class names.
+ * @param classNames Simple class names.
* @return Result of batch compilation.
*/
private static BatchCompilation batchCompile(String packageName, String... classNames) {
@@ -457,4 +637,18 @@ public class ItProcessorTest extends AbstractProcessorTest {
assertThat(t.getMessage(), containsString(expSubStr));
}
}
+
+ /**
+ * Extends {@link Assertions#assertThrows(Class, Executable)} to validate an error message against a pattern.
+ *
+ * @param expErrCls Expected error class.
+ * @param exec Supplier.
+ * @param pattern Error message pattern.
+ * @throws AssertionFailedError If failed.
+ */
+ private void assertThrowsEx(Class<? extends Throwable> expErrCls, Executable exec, Pattern pattern) {
+ Throwable t = assertThrows(expErrCls, exec);
+
+ assertThat(t.getMessage().replaceAll("[\\r\\n]", " "), matchesRegex(pattern));
+ }
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigConfigurationSchema.java
similarity index 61%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigConfigurationSchema.java
index 0c05a86fe..1fdfdb483 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigConfigurationSchema.java
@@ -15,21 +15,28 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
-import org.apache.ignite.configuration.annotation.Config;
+import java.util.UUID;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.InjectedName;
+import org.apache.ignite.configuration.annotation.InternalId;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * An example of an abstract configuration.
*/
-@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
+@AbstractConfiguration
+public class AbstractConfigConfigurationSchema {
+ @InjectedName
+ public String name;
- public static final String STRING_CONSTANT = "foobar";
+ @InternalId
+ public UUID id;
@Value
- public String str;
+ public String strVal;
+
+ @Value
+ public int intVal;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInjectedNameConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInjectedNameConfigurationSchema.java
index 4282aa6ef..b758b9bf2 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInjectedNameConfigurationSchema.java
@@ -15,17 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.InjectedName;
/**
- * Annotation processing exception.
+ * An example of an abstract configuration with field that contain {@link InjectedName}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+public class AbstractConfigWithInjectedNameConfigurationSchema {
+ @InjectedName
+ public String name;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInternalIdConfigurationSchema.java
similarity index 64%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInternalIdConfigurationSchema.java
index 4282aa6ef..ccdb48db6 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractConfigWithInternalIdConfigurationSchema.java
@@ -15,17 +15,17 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
+
+import java.util.UUID;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.InternalId;
/**
- * Annotation processing exception.
+ * An example of an abstract configuration with field that contain {@link InternalId}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+public class AbstractConfigWithInternalIdConfigurationSchema {
+ @InternalId
+ public UUID id;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractRootConfigConfigurationSchema.java
similarity index 67%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractRootConfigConfigurationSchema.java
index 4282aa6ef..9de85840a 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/AbstractRootConfigConfigurationSchema.java
@@ -15,17 +15,19 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.Value;
/**
- * Annotation processing exception.
+ * An example of an abstract root configuration.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
+@AbstractConfiguration
+public class AbstractRootConfigConfigurationSchema {
+ @Value
+ public String strVal;
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+ @Value
+ public int intVal;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigConfigurationSchema.java
similarity index 70%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigConfigurationSchema.java
index 0c05a86fe..0ea614c8d 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigConfigurationSchema.java
@@ -15,21 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * An example of a simple configuration that extends {@link AbstractConfigConfigurationSchema}.
*/
@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
+public class SimpleConfigConfigurationSchema extends AbstractConfigConfigurationSchema {
@Value
- public String str;
+ public long longVal;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigRootConfigurationSchema.java
similarity index 66%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigRootConfigurationSchema.java
index 0c05a86fe..e735bbf7d 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/SimpleConfigRootConfigurationSchema.java
@@ -15,21 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig;
-import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * An example of a simple configuration that extends {@link AbstractConfigConfigurationSchema}.
*/
-@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
+@ConfigurationRoot(rootName = "test")
+public class SimpleConfigRootConfigurationSchema extends AbstractRootConfigConfigurationSchema {
@Value
- public String str;
+ public long longVal;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigCanExtendOnlyAbstractConfigurationConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigCanExtendOnlyAbstractConfigurationConfigurationSchema.java
index 0c05a86fe..b6133667e 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigCanExtendOnlyAbstractConfigurationConfigurationSchema.java
@@ -15,21 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+import java.util.ArrayList;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
-import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Checks that {@link Config} can only extend schema with {@link AbstractConfiguration}.
*/
@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
- @Value
- public String str;
+public class ConfigCanExtendOnlyAbstractConfigurationConfigurationSchema extends ArrayList {
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigConflictFieldNamesWithAbstractConfigConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigConflictFieldNamesWithAbstractConfigConfigurationSchema.java
index 0c05a86fe..4b0c98a35 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigConflictFieldNamesWithAbstractConfigConfigurationSchema.java
@@ -15,21 +15,18 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigConfigurationSchema;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Checks if the {@link Config} conflicts in field names with {@link AbstractConfiguration}.
*/
@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
+public class ConfigConflictFieldNamesWithAbstractConfigConfigurationSchema extends AbstractConfigConfigurationSchema {
@Value
- public String str;
+ public String name;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInjectedNameWithAbstractConfigConfigurationSchema.java
similarity index 57%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInjectedNameWithAbstractConfigConfigurationSchema.java
index 0c05a86fe..a786713ab 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInjectedNameWithAbstractConfigConfigurationSchema.java
@@ -15,21 +15,19 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
-import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
+import org.apache.ignite.configuration.annotation.InjectedName;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigConfigurationSchema;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Checks that {@link Config} must not contain a field with {@link InjectedName} if {@link AbstractConfiguration} already has a field with
+ * {@link InjectedName}.
*/
@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
- @Value
- public String str;
+public class ConfigMustNotContainInjectedNameWithAbstractConfigConfigurationSchema extends AbstractConfigConfigurationSchema {
+ @InjectedName
+ public String name0;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInternalIdWithAbstractConfigConfigurationSchema.java
similarity index 56%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInternalIdWithAbstractConfigConfigurationSchema.java
index 0c05a86fe..0543c50af 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigMustNotContainInternalIdWithAbstractConfigConfigurationSchema.java
@@ -15,21 +15,20 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+import java.util.UUID;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
-import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
+import org.apache.ignite.configuration.annotation.InternalId;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigConfigurationSchema;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Checks that {@link Config} must not contain a field with {@link InternalId} if {@link AbstractConfiguration} already has a field with
+ * {@link InternalId}.
*/
@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
- @Value
- public String str;
+public class ConfigMustNotContainInternalIdWithAbstractConfigConfigurationSchema extends AbstractConfigConfigurationSchema {
+ @InternalId
+ public UUID id0;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootCanExtendOnlyAbstractConfigurationConfigurationSchema.java
similarity index 62%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootCanExtendOnlyAbstractConfigurationConfigurationSchema.java
index 4282aa6ef..13d8f6cb0 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootCanExtendOnlyAbstractConfigurationConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import java.util.ArrayList;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
/**
- * Annotation processing exception.
+ * Checks that {@link ConfigurationRoot} can only extend schema with {@link AbstractConfiguration}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@ConfigurationRoot(rootName = "test")
+public class ConfigRootCanExtendOnlyAbstractConfigurationConfigurationSchema extends ArrayList {
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootConflictFieldNamesWithAbstractConfigConfigurationSchema.java
similarity index 58%
copy from modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootConflictFieldNamesWithAbstractConfigConfigurationSchema.java
index 0c05a86fe..075a71f22 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootConflictFieldNamesWithAbstractConfigConfigurationSchema.java
@@ -15,21 +15,18 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor.internal;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
-import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigConfigurationSchema;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Checks if the {@link ConfigurationRoot} conflicts in field names with {@link AbstractConfiguration}.
*/
-@Config
-public class StaticConstantsConfigurationSchema {
- public static final int INT_CONSTANT = 0;
-
- public static final String STRING_CONSTANT = "foobar";
-
+@ConfigurationRoot(rootName = "test")
+public class ConfigRootConflictFieldNamesWithAbstractConfigConfigurationSchema extends AbstractConfigConfigurationSchema {
@Value
- public String str;
+ public String name;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInjectedNameInAbstractConfigConfigurationSchema.java
similarity index 53%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInjectedNameInAbstractConfigConfigurationSchema.java
index 4282aa6ef..a0702e049 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInjectedNameInAbstractConfigConfigurationSchema.java
@@ -15,17 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
+import org.apache.ignite.configuration.annotation.InjectedName;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigWithInjectedNameConfigurationSchema;
/**
- * Annotation processing exception.
+ * Checks that {@link ConfigurationRoot} should not extend {@link AbstractConfiguration} which has {@link InjectedName}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@ConfigurationRoot(rootName = "test")
+public class ConfigRootMustNotContainInjectedNameInAbstractConfigConfigurationSchema extends AbstractConfigWithInjectedNameConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInternalIdInAbstractConfigConfigurationSchema.java
similarity index 53%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInternalIdInAbstractConfigConfigurationSchema.java
index 4282aa6ef..7d6294ebf 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/ConfigRootMustNotContainInternalIdInAbstractConfigConfigurationSchema.java
@@ -15,17 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
+import org.apache.ignite.configuration.annotation.InternalId;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.AbstractConfigWithInternalIdConfigurationSchema;
/**
- * Annotation processing exception.
+ * Checks that {@link ConfigurationRoot} should not extend {@link AbstractConfiguration} which has {@link InternalId}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@ConfigurationRoot(rootName = "test")
+public class ConfigRootMustNotContainInternalIdInAbstractConfigConfigurationSchema extends AbstractConfigWithInternalIdConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/FieldWithInjectedNameFromAbstractConfigMustContainsNameConfigurationSchema.java
similarity index 51%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/FieldWithInjectedNameFromAbstractConfigMustContainsNameConfigurationSchema.java
index 4282aa6ef..2f03fcae1 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/FieldWithInjectedNameFromAbstractConfigMustContainsNameConfigurationSchema.java
@@ -15,17 +15,19 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.ConfigValue;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
+import org.apache.ignite.configuration.annotation.InjectedName;
+import org.apache.ignite.configuration.annotation.Name;
+import org.apache.ignite.internal.configuration.processor.abstractconfig.SimpleConfigConfigurationSchema;
/**
- * Annotation processing exception.
+ * Field whose configuration schema (extends abstract configuration) contains {@link InjectedName} must contain {@link Name}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@ConfigurationRoot(rootName = "test")
+public class FieldWithInjectedNameFromAbstractConfigMustContainsNameConfigurationSchema {
+ @ConfigValue
+ public SimpleConfigConfigurationSchema config;
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations0ConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations0ConfigurationSchema.java
index 4282aa6ef..4912c7325 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations0ConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.InternalConfiguration;
/**
- * Annotation processing exception.
+ * Checks for incompatibility {@link AbstractConfiguration} and {@link InternalConfiguration}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+@InternalConfiguration
+public class IncompatibleSchemaAnnotations0ConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations1ConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations1ConfigurationSchema.java
index 4282aa6ef..6ddaa07fd 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations1ConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.PolymorphicConfig;
/**
- * Annotation processing exception.
+ * Checks for incompatibility {@link AbstractConfiguration} and {@link PolymorphicConfig}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+@PolymorphicConfig
+public class IncompatibleSchemaAnnotations1ConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations2ConfigurationSchema.java
similarity index 64%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations2ConfigurationSchema.java
index 4282aa6ef..a1234a2f7 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations2ConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
/**
- * Annotation processing exception.
+ * Checks for incompatibility {@link AbstractConfiguration} and {@link PolymorphicConfigInstance}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+@PolymorphicConfigInstance("test")
+public class IncompatibleSchemaAnnotations2ConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations3ConfigurationSchema.java
similarity index 67%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations3ConfigurationSchema.java
index 4282aa6ef..a0a9a5a92 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations3ConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.Config;
/**
- * Annotation processing exception.
+ * Checks for incompatibility {@link AbstractConfiguration} and {@link Config}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+@Config
+public class IncompatibleSchemaAnnotations3ConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations4ConfigurationSchema.java
similarity index 64%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations4ConfigurationSchema.java
index 4282aa6ef..51217e841 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/IncompatibleSchemaAnnotations4ConfigurationSchema.java
@@ -15,17 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
/**
- * Annotation processing exception.
+ * Checks for incompatibility {@link AbstractConfiguration} and {@link ConfigurationRoot}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+@ConfigurationRoot(rootName = "test")
+public class IncompatibleSchemaAnnotations4ConfigurationSchema {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotBeSuperClassConfigurationSchema.java
similarity index 68%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotBeSuperClassConfigurationSchema.java
index 4282aa6ef..54e039abe 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotBeSuperClassConfigurationSchema.java
@@ -15,17 +15,14 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import java.util.ArrayList;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
/**
- * Annotation processing exception.
+ * Checks that the config schema with {@link AbstractConfiguration} will not extend other classes.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+public class MustNotBeSuperClassConfigurationSchema extends ArrayList {
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotContainPolymorphicIdConfigurationSchema.java
similarity index 65%
copy from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
copy to modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotContainPolymorphicIdConfigurationSchema.java
index 4282aa6ef..66f161248 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/abstractconfig/validation/MustNotContainPolymorphicIdConfigurationSchema.java
@@ -15,17 +15,16 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.configuration.processor;
+package org.apache.ignite.internal.configuration.processor.abstractconfig.validation;
+
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
+import org.apache.ignite.configuration.annotation.PolymorphicId;
/**
- * Annotation processing exception.
+ * Checks that there should not be a field with {@link PolymorphicId}.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
- super(message);
- }
-
- public ProcessorException(String message, Throwable cause) {
- super(message, cause);
- }
+@AbstractConfiguration
+public class MustNotContainPolymorphicIdConfigurationSchema {
+ @PolymorphicId
+ public String type;
}
diff --git a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
index 0c05a86fe..76ae2b2dc 100644
--- a/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/integrationTest/resources/org/apache/ignite/internal/configuration/processor/internal/StaticConstantsConfigurationSchema.java
@@ -19,10 +19,10 @@ package org.apache.ignite.internal.configuration.processor.internal;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.processor.ItProcessorTest;
+import org.apache.ignite.internal.configuration.processor.ItConfigurationProcessorTest;
/**
- * Test class for {@link ItProcessorTest#testStaticConstants()}.
+ * Test class for {@link ItConfigurationProcessorTest#testStaticConstants()}.
*/
@Config
public class StaticConstantsConfigurationSchema {
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Processor.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
similarity index 67%
rename from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Processor.java
rename to modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
index 7b4bd9cac..f9107e629 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Processor.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
@@ -23,9 +23,16 @@ import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
-import static org.apache.ignite.internal.configuration.processor.Utils.joinSimpleName;
-import static org.apache.ignite.internal.configuration.processor.Utils.simpleName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.collectFieldsWithAnnotation;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.findFirstPresentAnnotation;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getChangeName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getConfigurationInterfaceName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.getViewName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.joinSimpleName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.simpleName;
import static org.apache.ignite.internal.util.ArrayUtils.nullOrEmpty;
+import static org.apache.ignite.internal.util.CollectionUtils.concat;
+import static org.apache.ignite.internal.util.CollectionUtils.difference;
import static org.apache.ignite.internal.util.CollectionUtils.viewReadOnly;
import com.squareup.javapoet.ClassName;
@@ -42,7 +49,7 @@ import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
-import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
@@ -56,7 +63,6 @@ import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
@@ -66,6 +72,7 @@ import org.apache.ignite.configuration.NamedListChange;
import org.apache.ignite.configuration.NamedListView;
import org.apache.ignite.configuration.PolymorphicChange;
import org.apache.ignite.configuration.RootKey;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.ConfigValue;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
@@ -82,7 +89,8 @@ import org.jetbrains.annotations.Nullable;
/**
* Annotation processor that produces configuration classes.
*/
-public class Processor extends AbstractProcessor {
+// TODO: IGNITE-17166 Split into classes/methods for regular/internal/polymorphic/abstract configuration
+public class ConfigurationProcessor extends AbstractProcessor {
/** Java file padding. */
private static final String INDENT = " ";
@@ -143,7 +151,7 @@ public class Processor extends AbstractProcessor {
// Find all the fields of the schema.
List<VariableElement> fields = fields(clazz);
- validate(clazz, fields);
+ validateConfigurationSchemaClass(clazz, fields);
// Get package name of the schema class
String packageName = elementUtils.getPackageOf(clazz).getQualifiedName().toString();
@@ -151,14 +159,14 @@ public class Processor extends AbstractProcessor {
ClassName schemaClassName = ClassName.get(packageName, clazz.getSimpleName().toString());
// Get name for generated configuration interface.
- ClassName configInterface = Utils.getConfigurationInterfaceName(schemaClassName);
+ ClassName configInterface = getConfigurationInterfaceName(schemaClassName);
TypeSpec.Builder configurationInterfaceBuilder = TypeSpec.interfaceBuilder(configInterface)
.addModifiers(PUBLIC);
for (VariableElement field : fields) {
if (!field.getModifiers().contains(PUBLIC)) {
- throw new ProcessorException("Field " + clazz.getQualifiedName() + "." + field + " must be public");
+ throw new ConfigurationProcessorException("Field " + clazz.getQualifiedName() + "." + field + " must be public");
}
final String fieldName = field.getSimpleName().toString();
@@ -180,7 +188,7 @@ public class Processor extends AbstractProcessor {
if (valueAnnotation != null) {
// Must be a primitive or an array of the primitives (including java.lang.String)
if (!isPrimitiveOrArray(field.asType())) {
- throw new ProcessorException(
+ throw new ConfigurationProcessorException(
"@Value " + clazz.getQualifiedName() + "." + field.getSimpleName() + " field must"
+ " have one of the following types: boolean, int, long, double, String or an array of "
+ "aforementioned type."
@@ -191,7 +199,7 @@ public class Processor extends AbstractProcessor {
PolymorphicId polymorphicId = field.getAnnotation(PolymorphicId.class);
if (polymorphicId != null) {
if (!isClass(field.asType(), String.class)) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
FIELD_MUST_BE_SPECIFIC_CLASS_ERROR_FORMAT,
simpleName(PolymorphicId.class),
clazz.getQualifiedName(),
@@ -203,7 +211,7 @@ public class Processor extends AbstractProcessor {
if (field.getAnnotation(InternalId.class) != null) {
if (!isClass(field.asType(), UUID.class)) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
FIELD_MUST_BE_SPECIFIC_CLASS_ERROR_FORMAT,
simpleName(InternalId.class),
clazz.getQualifiedName(),
@@ -256,7 +264,7 @@ public class Processor extends AbstractProcessor {
ClassName schemaClassName,
TypeElement realSchemaClass
) {
- ClassName viewClassName = Utils.getViewName(schemaClassName);
+ ClassName viewClassName = getViewName(schemaClassName);
ParameterizedTypeName fieldTypeName = ParameterizedTypeName.get(ROOT_KEY_CLASSNAME, configInterface, viewClassName);
@@ -275,8 +283,8 @@ public class Processor extends AbstractProcessor {
* Create getters for configuration class.
*
* @param configurationInterfaceBuilder Interface builder.
- * @param fieldName Field name.
- * @param interfaceGetMethodType Return type.
+ * @param fieldName Field name.
+ * @param interfaceGetMethodType Return type.
*/
private static void createGetters(
TypeSpec.Builder configurationInterfaceBuilder,
@@ -304,15 +312,15 @@ public class Processor extends AbstractProcessor {
ConfigValue confAnnotation = field.getAnnotation(ConfigValue.class);
if (confAnnotation != null) {
- interfaceGetMethodType = Utils.getConfigurationInterfaceName((ClassName) baseType);
+ interfaceGetMethodType = getConfigurationInterfaceName((ClassName) baseType);
}
NamedConfigValue namedConfigAnnotation = field.getAnnotation(NamedConfigValue.class);
if (namedConfigAnnotation != null) {
- ClassName interfaceGetType = Utils.getConfigurationInterfaceName((ClassName) baseType);
+ ClassName interfaceGetType = getConfigurationInterfaceName((ClassName) baseType);
- TypeName viewClassType = Utils.getViewName((ClassName) baseType);
- TypeName changeClassType = Utils.getChangeName((ClassName) baseType);
+ TypeName viewClassType = getViewName((ClassName) baseType);
+ TypeName changeClassType = getChangeName((ClassName) baseType);
interfaceGetMethodType = ParameterizedTypeName.get(
ClassName.get(NamedConfigurationTree.class),
@@ -348,13 +356,13 @@ public class Processor extends AbstractProcessor {
/**
* Create VIEW and CHANGE classes and methods.
*
- * @param fields Collection of configuration fields.
- * @param schemaClassName Class name of schema.
+ * @param fields Collection of configuration fields.
+ * @param schemaClassName Class name of schema.
* @param configurationInterfaceBuilder Configuration interface builder.
- * @param extendBaseSchema {@code true} if extending base schema interfaces.
- * @param realSchemaClass Class descriptor.
- * @param isPolymorphicConfig Is a polymorphic configuration.
- * @param isPolymorphicInstanceConfig Is an instance of polymorphic configuration.
+ * @param extendBaseSchema {@code true} if extending base schema interfaces.
+ * @param realSchemaClass Class descriptor.
+ * @param isPolymorphicConfig Is a polymorphic configuration.
+ * @param isPolymorphicInstanceConfig Is an instance of polymorphic configuration.
*/
private void createPojoBindings(
Collection<VariableElement> fields,
@@ -365,23 +373,54 @@ public class Processor extends AbstractProcessor {
boolean isPolymorphicConfig,
boolean isPolymorphicInstanceConfig
) {
- ClassName viewClsName = Utils.getViewName(schemaClassName);
- ClassName changeClsName = Utils.getChangeName(schemaClassName);
+ ClassName viewClsName = getViewName(schemaClassName);
+ ClassName changeClsName = getChangeName(schemaClassName);
TypeName configInterfaceType;
@Nullable TypeName viewBaseSchemaInterfaceType;
@Nullable TypeName changeBaseSchemaInterfaceType;
- if (extendBaseSchema) {
- DeclaredType superClassType = (DeclaredType) realSchemaClass.getSuperclass();
- ClassName superClassSchemaClassName = ClassName.get((TypeElement) superClassType.asElement());
+ TypeElement superClass = superClass(realSchemaClass);
- configInterfaceType = Utils.getConfigurationInterfaceName(superClassSchemaClassName);
- viewBaseSchemaInterfaceType = Utils.getViewName(superClassSchemaClassName);
- changeBaseSchemaInterfaceType = Utils.getChangeName(superClassSchemaClassName);
+ boolean isSuperClassAbstractConfiguration = !isClass(superClass.asType(), Object.class)
+ && superClass.getAnnotation(AbstractConfiguration.class) != null;
+
+ if (extendBaseSchema || isSuperClassAbstractConfiguration) {
+ ClassName superClassSchemaClassName = ClassName.get(superClass);
+
+ viewBaseSchemaInterfaceType = getViewName(superClassSchemaClassName);
+ changeBaseSchemaInterfaceType = getChangeName(superClassSchemaClassName);
+
+ if (isSuperClassAbstractConfiguration) {
+ // Example: ExtendedTableConfig extends TableConfig<ExtendedTableView, ExtendedTableChange>
+ configInterfaceType = ParameterizedTypeName.get(
+ getConfigurationInterfaceName(superClassSchemaClassName),
+ viewClsName,
+ changeClsName
+ );
+ } else {
+ // Example: ExtendedTableConfig extends TableConfig
+ configInterfaceType = getConfigurationInterfaceName(superClassSchemaClassName);
+ }
} else {
ClassName confTreeInterface = ClassName.get("org.apache.ignite.configuration", "ConfigurationTree");
- configInterfaceType = ParameterizedTypeName.get(confTreeInterface, viewClsName, changeClsName);
+
+ if (realSchemaClass.getAnnotation(AbstractConfiguration.class) != null) {
+ // Example: TableConfig<VIEWT extends TableView, CHANGET extends TableChange> extends ConfigurationTree<VIEWT, CHANGET>
+ configurationInterfaceBuilder.addTypeVariables(List.of(
+ TypeVariableName.get("VIEWT", viewClsName),
+ TypeVariableName.get("CHANGET", changeClsName)
+ ));
+
+ configInterfaceType = ParameterizedTypeName.get(
+ confTreeInterface,
+ TypeVariableName.get("VIEWT"),
+ TypeVariableName.get("CHANGET")
+ );
+ } else {
+ // Example: TableConfig extends ConfigurationTree<TableView, TableChange>
+ configInterfaceType = ParameterizedTypeName.get(confTreeInterface, viewClsName, changeClsName);
+ }
viewBaseSchemaInterfaceType = null;
changeBaseSchemaInterfaceType = null;
@@ -427,10 +466,10 @@ public class Processor extends AbstractProcessor {
boolean namedListField = field.getAnnotation(NamedConfigValue.class) != null;
TypeName viewFieldType =
- leafField ? schemaFieldTypeName : Utils.getViewName((ClassName) schemaFieldTypeName);
+ leafField ? schemaFieldTypeName : getViewName((ClassName) schemaFieldTypeName);
TypeName changeFieldType =
- leafField ? schemaFieldTypeName : Utils.getChangeName((ClassName) schemaFieldTypeName);
+ leafField ? schemaFieldTypeName : getChangeName((ClassName) schemaFieldTypeName);
if (namedListField) {
changeFieldType = ParameterizedTypeName.get(
@@ -518,7 +557,7 @@ public class Processor extends AbstractProcessor {
.build()
.writeTo(processingEnv.getFiler());
} catch (Throwable throwable) {
- throw new ProcessorException("Failed to generate class " + packageName + "." + cls.name, throwable);
+ throw new ConfigurationProcessorException("Failed to generate class " + packageName + "." + cls.name, throwable);
}
}
@@ -566,15 +605,13 @@ public class Processor extends AbstractProcessor {
/**
* Validate the class.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param fields Class fields.
- * @throws ProcessorException If the class validation fails.
+ * @throws ConfigurationProcessorException If the class validation fails.
*/
- private void validate(TypeElement clazz, List<VariableElement> fields) {
- String simpleName = clazz.getSimpleName().toString();
-
- if (!simpleName.endsWith(CONFIGURATION_SCHEMA_POSTFIX)) {
- throw new ProcessorException(
+ private void validateConfigurationSchemaClass(TypeElement clazz, List<VariableElement> fields) {
+ if (!clazz.getSimpleName().toString().endsWith(CONFIGURATION_SCHEMA_POSTFIX)) {
+ throw new ConfigurationProcessorException(
String.format("%s must end with '%s'", clazz.getQualifiedName(), CONFIGURATION_SCHEMA_POSTFIX));
}
@@ -584,10 +621,12 @@ public class Processor extends AbstractProcessor {
validatePolymorphicConfig(clazz, fields);
} else if (clazz.getAnnotation(PolymorphicConfigInstance.class) != null) {
validatePolymorphicConfigInstance(clazz, fields);
+ } else if (clazz.getAnnotation(AbstractConfiguration.class) != null) {
+ validateAbstractConfiguration(clazz, fields);
} else if (clazz.getAnnotation(ConfigurationRoot.class) != null) {
- checkNotContainsPolymorphicIdField(clazz, ConfigurationRoot.class, fields);
+ validateConfigurationRoot(clazz, fields);
} else if (clazz.getAnnotation(Config.class) != null) {
- checkNotContainsPolymorphicIdField(clazz, Config.class, fields);
+ validateConfig(clazz, fields);
}
validateInjectedNameFields(clazz, fields);
@@ -598,14 +637,14 @@ public class Processor extends AbstractProcessor {
/**
* Checks configuration schema with {@link InternalConfiguration}.
*
- * @param clazz type element under validation
- * @param fields non-static fields of the class under validation
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
*/
private void validateInternalConfiguration(TypeElement clazz, List<VariableElement> fields) {
checkIncompatibleClassAnnotations(
clazz,
InternalConfiguration.class,
- Config.class, PolymorphicConfig.class, PolymorphicConfigInstance.class
+ incompatibleSchemaClassAnnotations(InternalConfiguration.class, ConfigurationRoot.class)
);
checkNotContainsPolymorphicIdField(clazz, InternalConfiguration.class, fields);
@@ -618,7 +657,7 @@ public class Processor extends AbstractProcessor {
TypeElement superClazz = superClass(clazz);
if (superClazz.getAnnotation(InternalConfiguration.class) != null) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Superclass must not have %s: %s",
simpleName(InternalConfiguration.class),
clazz.getQualifiedName()
@@ -634,22 +673,22 @@ public class Processor extends AbstractProcessor {
/**
* Checks configuration schema with {@link PolymorphicConfig}.
*
- * @param clazz type element under validation
- * @param fields non-static fields of the class under validation
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
*/
private void validatePolymorphicConfig(TypeElement clazz, List<VariableElement> fields) {
checkIncompatibleClassAnnotations(
clazz,
PolymorphicConfig.class,
- ConfigurationRoot.class, Config.class, PolymorphicConfigInstance.class
+ incompatibleSchemaClassAnnotations(PolymorphicConfig.class)
);
checkNotExistSuperClass(clazz, PolymorphicConfig.class);
- List<VariableElement> typeIdFields = collectAnnotatedFields(fields, PolymorphicId.class);
+ List<VariableElement> typeIdFields = collectFieldsWithAnnotation(fields, PolymorphicId.class);
if (typeIdFields.size() != 1 || fields.indexOf(typeIdFields.get(0)) != 0) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Class with %s must contain one field with %s and it should be the first in the schema: %s",
simpleName(PolymorphicConfig.class),
simpleName(PolymorphicId.class),
@@ -661,14 +700,14 @@ public class Processor extends AbstractProcessor {
/**
* Checks configuration schema with {@link PolymorphicConfigInstance}.
*
- * @param clazz type element under validation
- * @param fields non-static fields of the class under validation
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
*/
private void validatePolymorphicConfigInstance(TypeElement clazz, List<VariableElement> fields) {
checkIncompatibleClassAnnotations(
clazz,
PolymorphicConfigInstance.class,
- ConfigurationRoot.class, Config.class
+ incompatibleSchemaClassAnnotations(PolymorphicConfigInstance.class)
);
checkNotContainsPolymorphicIdField(clazz, PolymorphicConfigInstance.class, fields);
@@ -676,7 +715,7 @@ public class Processor extends AbstractProcessor {
String id = clazz.getAnnotation(PolymorphicConfigInstance.class).value();
if (id == null || id.isBlank()) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
EMPTY_FIELD_ERROR_FORMAT,
simpleName(PolymorphicConfigInstance.class) + ".id()",
clazz.getQualifiedName()
@@ -705,9 +744,7 @@ public class Processor extends AbstractProcessor {
}
/**
- * Returns annotation types supported by this processor.
- *
- * @return Annotation types supported by this processor.
+ * Returns immutable set of annotation types supported by this processor.
*/
private Set<Class<? extends Annotation>> supportedAnnotationTypes() {
return Set.of(
@@ -715,7 +752,8 @@ public class Processor extends AbstractProcessor {
ConfigurationRoot.class,
InternalConfiguration.class,
PolymorphicConfig.class,
- PolymorphicConfigInstance.class
+ PolymorphicConfigInstance.class,
+ AbstractConfiguration.class
);
}
@@ -723,28 +761,11 @@ public class Processor extends AbstractProcessor {
* Getting a superclass.
*
* @param clazz Class type.
- * @return Superclass type.
*/
private TypeElement superClass(TypeElement clazz) {
return processingEnv.getElementUtils().getTypeElement(clazz.getSuperclass().toString());
}
- /**
- * Returns the first annotation found for the class.
- *
- * @param clazz Class type.
- * @param annotationClasses Annotation classes that will be searched for the class.
- * @return First annotation found.
- */
- @SafeVarargs
- @Nullable
- private static Annotation findFirst(
- TypeElement clazz,
- Class<? extends Annotation>... annotationClasses
- ) {
- return Stream.of(annotationClasses).map(clazz::getAnnotation).filter(Objects::nonNull).findFirst().orElse(null);
- }
-
/**
* Search for duplicate class fields by name.
*
@@ -773,9 +794,9 @@ public class Processor extends AbstractProcessor {
/**
* Checking a class field with annotations {@link ConfigValue} or {@link NamedConfigValue}.
*
- * @param field Class field.
+ * @param field Class field.
* @param annotationClass Field annotation: {@link ConfigValue} or {@link NamedConfigValue}.
- * @throws ProcessorException If the check is not successful.
+ * @throws ConfigurationProcessorException If the check is not successful.
*/
private void checkConfigField(
VariableElement field,
@@ -788,7 +809,7 @@ public class Processor extends AbstractProcessor {
if (fieldTypeElement.getAnnotation(Config.class) == null
&& fieldTypeElement.getAnnotation(PolymorphicConfig.class) == null) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Class for %s field must be defined as %s: %s.%s",
simpleName(annotationClass),
joinSimpleName(" or ", Config.class, PolymorphicConfig.class),
@@ -810,27 +831,13 @@ public class Processor extends AbstractProcessor {
return classType.equals(type);
}
- /**
- * Collect fields with annotation.
- *
- * @param fields Fields.
- * @param annotationClass Annotation class.
- * @return Fields with annotation.
- */
- private static List<VariableElement> collectAnnotatedFields(
- Collection<VariableElement> fields,
- Class<? extends Annotation> annotationClass
- ) {
- return fields.stream().filter(f -> f.getAnnotation(annotationClass) != null).collect(toList());
- }
-
/**
* Checks for an incompatible class annotation with {@code clazzAnnotation}.
*
- * @param clazz Class type.
- * @param clazzAnnotation Class annotation.
+ * @param clazz Class type.
+ * @param clazzAnnotation Class annotation.
* @param incompatibleAnnotations Incompatible class annotations with {@code clazzAnnotation}.
- * @throws ProcessorException If there is an incompatible class annotation with {@code clazzAnnotation}.
+ * @throws ConfigurationProcessorException If there is an incompatible class annotation with {@code clazzAnnotation}.
*/
@SafeVarargs
private void checkIncompatibleClassAnnotations(
@@ -841,12 +848,12 @@ public class Processor extends AbstractProcessor {
assert clazz.getAnnotation(clazzAnnotation) != null : clazz.getQualifiedName();
assert !nullOrEmpty(incompatibleAnnotations);
- Annotation incompatible = findFirst(clazz, incompatibleAnnotations);
+ Optional<? extends Annotation> incompatible = findFirstPresentAnnotation(clazz, incompatibleAnnotations);
- if (incompatible != null) {
- throw new ProcessorException(String.format(
+ if (incompatible.isPresent()) {
+ throw new ConfigurationProcessorException(String.format(
"Class with %s is not allowed with %s: %s",
- simpleName(incompatible.getClass()),
+ simpleName(incompatible.get().annotationType()),
simpleName(clazzAnnotation),
clazz.getQualifiedName()
));
@@ -856,15 +863,15 @@ public class Processor extends AbstractProcessor {
/**
* Checks that the class has a superclass.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param clazzAnnotation Class annotation.
- * @throws ProcessorException If the class doesn't have a superclass.
+ * @throws ConfigurationProcessorException If the class doesn't have a superclass.
*/
private void checkExistSuperClass(TypeElement clazz, Class<? extends Annotation> clazzAnnotation) {
assert clazz.getAnnotation(clazzAnnotation) != null : clazz.getQualifiedName();
if (isClass(clazz.getSuperclass(), Object.class)) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Class with %s should not have a superclass: %s",
simpleName(clazzAnnotation),
clazz.getQualifiedName()
@@ -875,15 +882,15 @@ public class Processor extends AbstractProcessor {
/**
* Checks that the class should not have a superclass.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param clazzAnnotation Class annotation.
- * @throws ProcessorException If the class have a superclass.
+ * @throws ConfigurationProcessorException If the class have a superclass.
*/
private void checkNotExistSuperClass(TypeElement clazz, Class<? extends Annotation> clazzAnnotation) {
assert clazz.getAnnotation(clazzAnnotation) != null : clazz.getQualifiedName();
if (!isClass(clazz.getSuperclass(), Object.class)) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Class with %s should not have a superclass: %s",
simpleName(clazzAnnotation),
clazz.getQualifiedName()
@@ -894,10 +901,10 @@ public class Processor extends AbstractProcessor {
/**
* Checks that the class does not have a field with {@link PolymorphicId}.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param clazzAnnotation Class annotation.
- * @param clazzfields Class fields.
- * @throws ProcessorException If the class has a field with {@link PolymorphicId}.
+ * @param clazzfields Class fields.
+ * @throws ConfigurationProcessorException If the class has a field with {@link PolymorphicId}.
*/
private void checkNotContainsPolymorphicIdField(
TypeElement clazz,
@@ -906,8 +913,8 @@ public class Processor extends AbstractProcessor {
) {
assert clazz.getAnnotation(clazzAnnotation) != null : clazz.getQualifiedName();
- if (!collectAnnotatedFields(clazzfields, PolymorphicId.class).isEmpty()) {
- throw new ProcessorException(String.format(
+ if (!collectFieldsWithAnnotation(clazzfields, PolymorphicId.class).isEmpty()) {
+ throw new ConfigurationProcessorException(String.format(
"Class with %s cannot have a field with %s: %s",
simpleName(clazzAnnotation),
simpleName(PolymorphicId.class),
@@ -919,11 +926,11 @@ public class Processor extends AbstractProcessor {
/**
* Checks that there is no conflict of field names between classes.
*
- * @param clazz0 First class type.
- * @param clazz1 Second class type.
+ * @param clazz0 First class type.
+ * @param clazz1 Second class type.
* @param clazzFields0 First class fields.
* @param clazzFields1 Second class fields.
- * @throws ProcessorException If there is a conflict of field names between classes.
+ * @throws ConfigurationProcessorException If there is a conflict of field names between classes.
*/
private void checkNoConflictFieldNames(
TypeElement clazz0,
@@ -934,7 +941,7 @@ public class Processor extends AbstractProcessor {
Collection<Name> duplicateFieldNames = findDuplicates(clazzFields0, clazzFields1);
if (!duplicateFieldNames.isEmpty()) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Duplicate field names are not allowed [class=%s, superClass=%s, fields=%s]",
clazz0.getQualifiedName(),
clazz1.getQualifiedName(),
@@ -946,10 +953,10 @@ public class Processor extends AbstractProcessor {
/**
* Checks if the superclass has at least one annotation from {@code superClazzAnnotations}.
*
- * @param clazz Class type.
- * @param superClazz Superclass type.
+ * @param clazz Class type.
+ * @param superClazz Superclass type.
* @param superClazzAnnotations Superclass annotations.
- * @throws ProcessorException If the superclass has none of the annotations from {@code superClazzAnnotations}.
+ * @throws ConfigurationProcessorException If the superclass has none of the annotations from {@code superClazzAnnotations}.
*/
@SafeVarargs
private void checkSuperclassContainAnyAnnotation(
@@ -958,7 +965,7 @@ public class Processor extends AbstractProcessor {
Class<? extends Annotation>... superClazzAnnotations
) {
if (Stream.of(superClazzAnnotations).allMatch(a -> superClazz.getAnnotation(a) == null)) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
SUPERCLASS_MISSING_ANNOTATION_ERROR_FORMAT,
joinSimpleName(" or ", superClazzAnnotations),
clazz.getQualifiedName()
@@ -969,66 +976,66 @@ public class Processor extends AbstractProcessor {
/**
* Validation of class fields with {@link InjectedName} if present.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param fields Class fields.
- * @throws ProcessorException If the class validation fails.
+ * @throws ConfigurationProcessorException If the class validation fails.
*/
private void validateInjectedNameFields(TypeElement clazz, List<VariableElement> fields) {
- List<VariableElement> injectedNameFields = collectAnnotatedFields(fields, InjectedName.class);
+ List<VariableElement> injectedNameFields = collectFieldsWithAnnotation(fields, InjectedName.class);
if (injectedNameFields.isEmpty()) {
return;
}
if (injectedNameFields.size() > 1) {
- throw new ProcessorException(String.format(
- "%s contains more than one field with %s",
- clazz.getQualifiedName(),
- simpleName(InjectedName.class)
+ throw new ConfigurationProcessorException(String.format(
+ "%s contains more than one field with %s",
+ clazz.getQualifiedName(),
+ simpleName(InjectedName.class)
));
}
VariableElement injectedNameField = injectedNameFields.get(0);
if (!isClass(injectedNameField.asType(), String.class)) {
- throw new ProcessorException(String.format(
- FIELD_MUST_BE_SPECIFIC_CLASS_ERROR_FORMAT,
- simpleName(InjectedName.class),
- clazz.getQualifiedName(),
- injectedNameField.getSimpleName(),
- String.class.getSimpleName()
+ throw new ConfigurationProcessorException(String.format(
+ FIELD_MUST_BE_SPECIFIC_CLASS_ERROR_FORMAT,
+ simpleName(InjectedName.class),
+ clazz.getQualifiedName(),
+ injectedNameField.getSimpleName(),
+ String.class.getSimpleName()
));
}
+ // TODO: IGNITE-17166 Must not contain @Value, @ConfigValue etc
if (injectedNameField.getAnnotationMirrors().size() > 1) {
- throw new ProcessorException(String.format(
- "%s.%s must contain only one %s",
- clazz.getQualifiedName(),
- injectedNameField.getSimpleName(),
- simpleName(InjectedName.class)
+ throw new ConfigurationProcessorException(String.format(
+ "%s.%s must contain only one %s",
+ clazz.getQualifiedName(),
+ injectedNameField.getSimpleName(),
+ simpleName(InjectedName.class)
));
}
- if (clazz.getAnnotation(Config.class) == null && clazz.getAnnotation(PolymorphicConfig.class) == null) {
- throw new ProcessorException(String.format(
- "%s %s.%s can only be present in a class annotated with %s",
- simpleName(InjectedName.class),
- clazz.getQualifiedName(),
- injectedNameField.getSimpleName(),
- joinSimpleName(" or ", Config.class, PolymorphicConfig.class)
- ));
- }
+ findFirstPresentAnnotation(clazz, Config.class, PolymorphicConfig.class, AbstractConfiguration.class)
+ .orElseThrow(() -> new ConfigurationProcessorException(String.format(
+ "%s %s.%s can only be present in a class annotated with %s",
+ simpleName(InjectedName.class),
+ clazz.getQualifiedName(),
+ injectedNameField.getSimpleName(),
+ joinSimpleName(" or ", Config.class, PolymorphicConfig.class, AbstractConfiguration.class)
+ )));
}
/**
* Validation of class fields with {@link Name} if present.
*
- * @param clazz Class type.
+ * @param clazz Class type.
* @param fields Class fields.
- * @throws ProcessorException If the class validation fails.
+ * @throws ConfigurationProcessorException If the class validation fails.
*/
private void validateNameFields(TypeElement clazz, List<VariableElement> fields) {
- List<VariableElement> nameFields = collectAnnotatedFields(fields, org.apache.ignite.configuration.annotation.Name.class);
+ List<VariableElement> nameFields = collectFieldsWithAnnotation(fields, org.apache.ignite.configuration.annotation.Name.class);
if (nameFields.isEmpty()) {
return;
@@ -1036,12 +1043,12 @@ public class Processor extends AbstractProcessor {
for (VariableElement nameField : nameFields) {
if (nameField.getAnnotation(ConfigValue.class) == null) {
- throw new ProcessorException(String.format(
- "%s annotation can only be used with %s: %s.%s",
- simpleName(org.apache.ignite.configuration.annotation.Name.class),
- simpleName(ConfigValue.class),
- clazz.getQualifiedName(),
- nameField.getSimpleName()
+ throw new ConfigurationProcessorException(String.format(
+ "%s annotation can only be used with %s: %s.%s",
+ simpleName(org.apache.ignite.configuration.annotation.Name.class),
+ simpleName(ConfigValue.class),
+ clazz.getQualifiedName(),
+ nameField.getSimpleName()
));
}
}
@@ -1051,16 +1058,28 @@ public class Processor extends AbstractProcessor {
* Checks for missing {@link org.apache.ignite.configuration.annotation.Name} for nested schema with {@link InjectedName}.
*
* @param field Class field.
- * @throws ProcessorException If there is no {@link org.apache.ignite.configuration.annotation.Name}
- * for the nested schema with {@link InjectedName}.
+ * @throws ConfigurationProcessorException If there is no {@link org.apache.ignite.configuration.annotation.Name} for the nested schema
+ * with {@link InjectedName}.
*/
private void checkMissingNameForInjectedName(VariableElement field) {
TypeElement fieldType = (TypeElement) processingEnv.getTypeUtils().asElement(field.asType());
- List<VariableElement> fields = collectAnnotatedFields(fields(fieldType), InjectedName.class);
+ TypeElement superClassFieldType = superClass(fieldType);
+
+ List<VariableElement> fields;
+
+ if (!isClass(superClassFieldType.asType(), Object.class)
+ && findFirstPresentAnnotation(superClassFieldType, AbstractConfiguration.class).isPresent()) {
+ fields = concat(
+ collectFieldsWithAnnotation(fields(fieldType), InjectedName.class),
+ collectFieldsWithAnnotation(fields(superClassFieldType), InjectedName.class)
+ );
+ } else {
+ fields = collectFieldsWithAnnotation(fields(fieldType), InjectedName.class);
+ }
if (!fields.isEmpty() && field.getAnnotation(org.apache.ignite.configuration.annotation.Name.class) == null) {
- throw new ProcessorException(String.format(
+ throw new ConfigurationProcessorException(String.format(
"Missing %s for field: %s.%s",
simpleName(org.apache.ignite.configuration.annotation.Name.class),
field.getEnclosingElement(),
@@ -1068,4 +1087,124 @@ public class Processor extends AbstractProcessor {
));
}
}
+
+ /**
+ * Checks configuration schema with {@link AbstractConfiguration}.
+ *
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
+ * @throws ConfigurationProcessorException If validation fails.
+ */
+ private void validateAbstractConfiguration(TypeElement clazz, List<VariableElement> fields) throws ConfigurationProcessorException {
+ checkIncompatibleClassAnnotations(
+ clazz,
+ AbstractConfiguration.class,
+ incompatibleSchemaClassAnnotations(AbstractConfiguration.class)
+ );
+
+ checkNotExistSuperClass(clazz, AbstractConfiguration.class);
+
+ checkNotContainsPolymorphicIdField(clazz, AbstractConfiguration.class, fields);
+ }
+
+ /**
+ * Checks configuration schema with {@link ConfigurationRoot}.
+ *
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
+ * @throws ConfigurationProcessorException If validation fails.
+ */
+ private void validateConfigurationRoot(TypeElement clazz, List<VariableElement> fields) throws ConfigurationProcessorException {
+ checkIncompatibleClassAnnotations(
+ clazz,
+ ConfigurationRoot.class,
+ incompatibleSchemaClassAnnotations(ConfigurationRoot.class)
+ );
+
+ checkNotContainsPolymorphicIdField(clazz, ConfigurationRoot.class, fields);
+
+ TypeElement superClazz = superClass(clazz);
+
+ if (!isClass(superClazz.asType(), Object.class)) {
+ checkSuperclassContainAnyAnnotation(clazz, superClazz, AbstractConfiguration.class);
+
+ List<VariableElement> superClazzFields = fields(superClazz);
+
+ checkNoConflictFieldNames(clazz, superClazz, fields, superClazzFields);
+
+ String invalidFieldInSuperClassFormat = "Field with %s in superclass are not allowed [class=%s, superClass=%s]";
+
+ if (!collectFieldsWithAnnotation(superClazzFields, InjectedName.class).isEmpty()) {
+ throw new ConfigurationProcessorException(String.format(
+ invalidFieldInSuperClassFormat,
+ simpleName(InjectedName.class),
+ clazz.getQualifiedName(),
+ superClazz.getQualifiedName()
+ ));
+ }
+
+ if (!collectFieldsWithAnnotation(superClazzFields, InternalId.class).isEmpty()) {
+ throw new ConfigurationProcessorException(String.format(
+ invalidFieldInSuperClassFormat,
+ simpleName(InternalId.class),
+ clazz.getQualifiedName(),
+ superClazz.getQualifiedName()
+ ));
+ }
+ }
+ }
+
+ /**
+ * Checks configuration schema with {@link Config}.
+ *
+ * @param clazz Type element under validation.
+ * @param fields Non-static fields of the class under validation.
+ * @throws ConfigurationProcessorException If validation fails.
+ */
+ private void validateConfig(TypeElement clazz, List<VariableElement> fields) throws ConfigurationProcessorException {
+ checkIncompatibleClassAnnotations(
+ clazz,
+ Config.class,
+ incompatibleSchemaClassAnnotations(Config.class)
+ );
+
+ checkNotContainsPolymorphicIdField(clazz, Config.class, fields);
+
+ TypeElement superClazz = superClass(clazz);
+
+ if (!isClass(superClazz.asType(), Object.class)) {
+ checkSuperclassContainAnyAnnotation(clazz, superClazz, AbstractConfiguration.class);
+
+ List<VariableElement> superClazzFields = fields(superClazz);
+
+ checkNoConflictFieldNames(clazz, superClazz, fields, superClazzFields);
+
+ String fieldAlreadyPresentInSuperClassFormat = "Field with %s is already present in the superclass [class=%s, superClass=%s]";
+
+ if (!collectFieldsWithAnnotation(superClazzFields, InjectedName.class).isEmpty()
+ && !collectFieldsWithAnnotation(fields, InjectedName.class).isEmpty()) {
+ throw new ConfigurationProcessorException(String.format(
+ fieldAlreadyPresentInSuperClassFormat,
+ simpleName(InjectedName.class),
+ clazz.getQualifiedName(),
+ superClazz.getQualifiedName()
+ ));
+ }
+
+ if (!collectFieldsWithAnnotation(superClazzFields, InternalId.class).isEmpty()
+ && !collectFieldsWithAnnotation(fields, InternalId.class).isEmpty()) {
+ throw new ConfigurationProcessorException(String.format(
+ fieldAlreadyPresentInSuperClassFormat,
+ simpleName(InternalId.class),
+ clazz.getQualifiedName(),
+ superClazz.getQualifiedName()
+ ));
+ }
+ }
+ }
+
+ @SafeVarargs
+ private Class<? extends Annotation>[] incompatibleSchemaClassAnnotations(Class<? extends Annotation>... compatibleAnnotations) {
+ return difference(supportedAnnotationTypes(), Set.of(compatibleAnnotations)).toArray(Class[]::new);
+ }
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorException.java
similarity index 68%
rename from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
rename to modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorException.java
index 4282aa6ef..d21af15a6 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ProcessorException.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorException.java
@@ -17,15 +17,28 @@
package org.apache.ignite.internal.configuration.processor;
+import org.jetbrains.annotations.Nullable;
+
/**
* Annotation processing exception.
*/
-public class ProcessorException extends RuntimeException {
- public ProcessorException(String message) {
+public class ConfigurationProcessorException extends RuntimeException {
+ /**
+ * Constructor.
+ *
+ * @param message Error massage.
+ */
+ public ConfigurationProcessorException(String message) {
super(message);
}
- public ProcessorException(String message, Throwable cause) {
+ /**
+ * Constructor.
+ *
+ * @param message Error message.
+ * @param cause Cause
+ */
+ public ConfigurationProcessorException(String message, @Nullable Throwable cause) {
super(message, cause);
}
}
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Utils.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtils.java
similarity index 58%
rename from modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Utils.java
rename to modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtils.java
index b5a5565c8..3191ca063 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/Utils.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtils.java
@@ -18,24 +18,26 @@
package org.apache.ignite.internal.configuration.processor;
import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
import com.squareup.javapoet.ClassName;
import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
import java.util.stream.Stream;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
/**
* Annotation processing utilities.
*/
-public class Utils {
- /** Private constructor. */
- private Utils() {
- }
-
+class ConfigurationProcessorUtils {
/**
- * Get {@link ClassName} for configuration class' public interface.
+ * Returns {@link ClassName} for configuration class public interface.
*
* @param schemaClassName Configuration schema ClassName.
- * @return Configuration's public interface ClassName.
*/
public static ClassName getConfigurationInterfaceName(ClassName schemaClassName) {
return ClassName.get(
@@ -45,10 +47,9 @@ public class Utils {
}
/**
- * Get {@link ClassName} for configuration VIEW object class.
+ * Returns {@link ClassName} for configuration VIEW object class.
*
* @param schemaClassName Configuration schema ClassName.
- * @return Configuration VIEW object ClassName.
*/
public static ClassName getViewName(ClassName schemaClassName) {
return ClassName.get(
@@ -58,10 +59,9 @@ public class Utils {
}
/**
- * Get {@link ClassName} for configuration CHANGE object class.
+ * Returns {@link ClassName} for configuration CHANGE object class.
*
* @param schemaClassName Configuration schema ClassName.
- * @return Configuration CHANGE object ClassName.
*/
public static ClassName getChangeName(ClassName schemaClassName) {
return ClassName.get(
@@ -71,24 +71,49 @@ public class Utils {
}
/**
- * Returns the simple name of the annotation as: @Config.
+ * Returns the simple name of the annotation as: {@code @Config}.
*
* @param annotationClass Annotation class.
- * @return Simple name of the annotation.
*/
public static String simpleName(Class<? extends Annotation> annotationClass) {
return '@' + annotationClass.getSimpleName();
}
/**
- * Create a string with simple annotation names like: @Config and @PolymorphicConfig.
+ * Creates a string with simple annotation names like: {@code @Config} and {@code @PolymorphicConfig}.
*
- * @param delimiter Delimiter between elements.
+ * @param delimiter Delimiter between elements.
* @param annotations Annotations.
- * @return String with simple annotation names.
*/
@SafeVarargs
public static String joinSimpleName(String delimiter, Class<? extends Annotation>... annotations) {
- return Stream.of(annotations).map(Utils::simpleName).collect(joining(delimiter));
+ return Stream.of(annotations).map(ConfigurationProcessorUtils::simpleName).collect(joining(delimiter));
+ }
+
+ /**
+ * Returns the first annotation found for the class.
+ *
+ * @param clazz Class type.
+ * @param annotationClasses Annotation classes that will be searched for the class.
+ */
+ @SafeVarargs
+ public static Optional<? extends Annotation> findFirstPresentAnnotation(
+ TypeElement clazz,
+ Class<? extends Annotation>... annotationClasses
+ ) {
+ return Stream.of(annotationClasses).map(clazz::getAnnotation).filter(Objects::nonNull).findFirst();
+ }
+
+ /**
+ * Collect fields with annotation.
+ *
+ * @param fields Fields.
+ * @param annotationClass Annotation class.
+ */
+ public static List<VariableElement> collectFieldsWithAnnotation(
+ Collection<VariableElement> fields,
+ Class<? extends Annotation> annotationClass
+ ) {
+ return fields.stream().filter(f -> f.getAnnotation(annotationClass) != null).collect(toList());
}
}
diff --git a/modules/configuration-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/modules/configuration-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 4f1a31303..d7bf62188 100644
--- a/modules/configuration-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/modules/configuration-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -1 +1 @@
-org.apache.ignite.internal.configuration.processor.Processor
\ No newline at end of file
+org.apache.ignite.internal.configuration.processor.ConfigurationProcessor
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/UtilsTest.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtilsTest.java
similarity index 89%
rename from modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/UtilsTest.java
rename to modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtilsTest.java
index dde3a026b..62d30dc9d 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/UtilsTest.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessorUtilsTest.java
@@ -17,8 +17,8 @@
package org.apache.ignite.internal.configuration.processor;
-import static org.apache.ignite.internal.configuration.processor.Utils.joinSimpleName;
-import static org.apache.ignite.internal.configuration.processor.Utils.simpleName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.joinSimpleName;
+import static org.apache.ignite.internal.configuration.processor.ConfigurationProcessorUtils.simpleName;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.ignite.configuration.annotation.Config;
@@ -26,9 +26,9 @@ import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.junit.jupiter.api.Test;
/**
- * Class for testing the {@link Utils}.
+ * Class for testing the {@link ConfigurationProcessorUtils}.
*/
-public class UtilsTest {
+public class ConfigurationProcessorUtilsTest {
@Test
void testSimpleName() {
assertEquals("@Config", simpleName(Config.class));
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/AbstractConfiguration.java
similarity index 66%
copy from modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java
copy to modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/AbstractConfiguration.java
index cc749cce1..447f63a3a 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/AbstractConfiguration.java
@@ -17,7 +17,7 @@
package org.apache.ignite.configuration.annotation;
-import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
@@ -25,17 +25,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
- * This annotation marks configuration schema field as a configuration tree node.
- * <pre><code>
- * {@literal @}Config
- * public class FooConfigurationSchema {
- * {@literal @}ConfigValue
- * public SomeOtherConfiguration someOther;
- * }
- * </code></pre>
+ * This annotation marks a class as an abstract configuration schema. Has basically the same properties as a {@link PolymorphicConfig}, but
+ * its type cannot be changed and its inheritors must be annotated with either {@link Config} or {@link ConfigurationRoot}. Configuration
+ * schemas with this annotation cannot be used as a nested (sub)configuration.
+ *
+ * @see Config
+ * @see ConfigurationRoot
+ * @see PolymorphicConfig
*/
-@Target({FIELD})
+@Target(TYPE)
@Retention(RUNTIME)
@Documented
-public @interface ConfigValue {
+public @interface AbstractConfiguration {
}
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/Config.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/Config.java
index d17aacc92..08b030a81 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/Config.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/Config.java
@@ -56,7 +56,7 @@ import java.lang.annotation.Target;
*
* @see ConfigurationRoot
*/
-@Target({TYPE})
+@Target(TYPE)
@Retention(RUNTIME)
@Documented
public @interface Config {
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java
index cc749cce1..2a9c38ed1 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/ConfigValue.java
@@ -34,7 +34,7 @@ import java.lang.annotation.Target;
* }
* </code></pre>
*/
-@Target({FIELD})
+@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface ConfigValue {
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/InjectedName.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/InjectedName.java
index f1728fbfb..a53745600 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/InjectedName.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/annotation/InjectedName.java
@@ -49,10 +49,12 @@ import java.lang.annotation.Target;
* </code></pre>
*
* <p>NOTE: Field must be a {@link String} and the only one (with this annotation) in the schema, field name is used instead of
- * {@link NamedConfigValue#syntheticKeyName()}, it can be used in schemas with {@link Config} and {@link PolymorphicConfig}.
+ * {@link NamedConfigValue#syntheticKeyName()}, it can be used in schemas with {@link Config}, {@link PolymorphicConfig} and
+ * {@link AbstractConfiguration}.
*
* @see Config
* @see PolymorphicConfig
+ * @see AbstractConfiguration
* @see ConfigValue
* @see NamedConfigValue
* @see Name
diff --git a/modules/configuration/README.md b/modules/configuration/README.md
index dc20e5205..0fffbc359 100644
--- a/modules/configuration/README.md
+++ b/modules/configuration/README.md
@@ -32,16 +32,28 @@ Instances of this interface are generated automatically and are mandatory for re
An example configuration schema may look like the following:
```java
-@ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+@ConfigurationRoot(rootName = "rootLocal", type = ConfigurationType.LOCAL)
public static class ParentConfigurationSchema {
@NamedConfigValue
- private NamedElementConfigurationSchema elements;
+ public NamedElementConfigurationSchema elements;
@ConfigValue
- private ChildConfigurationSchema child;
+ public ChildConfigurationSchema child;
+
+ @ConfigValue
+ public PolymorphicConfigurationSchema polymorphicChild;
+
+ @ConfigValue
+ public SecondChildConfigurationSchema secondChild;
+}
+
+@ConfigurationRoot(rootName = "rootDistributed", type = ConfigurationType.DISTRIBUTED)
+public static class SecondParentConfigurationSchema extends AbstractRootConfigurationSchema {
+ @ConfigValue
+ public ChildConfigurationSchema child;
@ConfigValue
- private PolymorphicConfigurationSchema polymorphicChild;
+ public SecondChildConfigurationSchema secondChild;
}
@Config
@@ -54,6 +66,12 @@ public static class ChildConfigurationSchema {
public String str2;
}
+@Config
+public static class SecondChildConfigurationSchema extends AbstractConfigurationSchema {
+ @Value(hasDefault = true)
+ public long longVal = 0;
+}
+
@PolymorphicConfig
public static class PolymorphicConfigurationSchema {
@PolymorphicId(hasDefault = true)
@@ -65,6 +83,18 @@ public static class FirstPolymorphicInstanceConfigurationSchema extends Polymorp
@Value(hasDefault = true)
public int intVal = 0;
}
+
+@AbstractConfiguration
+public static class AbstractRootConfigurationSchema {
+ @Value(hasDefault = true)
+ public String strVal = "foobar";
+}
+
+@AbstractConfiguration
+public static class AbstractConfigurationSchema {
+ @Value(hasDefault = true)
+ public int intVal = 0;
+}
```
* `@ConfigurationRoot` marks the root schema. It contains the following properties:
@@ -76,7 +106,9 @@ public static class FirstPolymorphicInstanceConfigurationSchema extends Polymorp
* `@Config` is similar to the `@ConfigurationRoot` but represents an inner configuration node;
* `@PolymorphicConfig` is similar to the `@Config` and an abstract class in java, i.e. it cannot be instantiated, but it can be subclassed;
* `@PolymorphicConfigInstance` marks an inheritor of a polymorphic configuration. This annotation has a single property called `value` -
- a unique identifier among the inheritors of one polymorphic configuration, used to define the type (schema) of the polymorphic configuration we are dealing with now.
+ a unique identifier among the inheritors of one polymorphic configuration, used to define the type (schema) of the polymorphic configuration we are dealing with now;
+* `@AbstractConfiguration` is similar to `@PolymorphicConfig` but its type cannot be changed and its inheritors must be annotated with
+ either `@Config` or `@ConfigurationRoot`. Configuration schemas with this annotation cannot be used as a nested (sub)configuration;
* `@ConfigValue` marks a nested schema field. Cyclic dependencies are not allowed;
* `@NamedConfigValue` is similar to `@ConfigValue`, but such fields represent a collection of properties, not a single
instance. Every element of the collection will have a `String` name, similar to a `Map`.
@@ -307,4 +339,4 @@ Sometimes it's desirable to have a peek into the future, to read the configurati
node. There's API for this purpose.
Please refer to `ConfigurationUtil#directProxy(ConfigurationProperty)` for details. There are many usages of this method in tests. It
-should provide the context.
\ No newline at end of file
+should provide the context.
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGenerator.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGenerator.java
index a5c951917..590269004 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGenerator.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGenerator.java
@@ -120,6 +120,7 @@ import org.apache.ignite.configuration.ConfigurationWrongPolymorphicTypeIdExcept
import org.apache.ignite.configuration.NamedConfigurationTree;
import org.apache.ignite.configuration.NamedListView;
import org.apache.ignite.configuration.RootKey;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.InjectedName;
@@ -154,6 +155,7 @@ import org.objectweb.asm.Type;
* This class is responsible for generating internal implementation classes for configuration schemas. It uses classes from {@code bytecode}
* module to achieve this goal, like {@link ClassGenerator}, for examples.
*/
+// TODO: IGNITE-17167 Split into classes/methods for regular/internal/polymorphic/abstract configuration
public class ConfigurationAsmGenerator {
/** {@link DynamicConfiguration#DynamicConfiguration} constructor. */
private static final Constructor<?> DYNAMIC_CONFIGURATION_CTOR;
@@ -432,7 +434,12 @@ public class ConfigurationAsmGenerator {
+ " is polymorphic but polymorphic extensions are absent");
}
- List<Field> schemaFields = schemaFields(schemaClass);
+ Class<?> schemaSuperClass = schemaClass.getSuperclass();
+
+ List<Field> schemaFields = schemaSuperClass.isAnnotationPresent(AbstractConfiguration.class)
+ ? concat(schemaFields(schemaClass), schemaFields(schemaSuperClass))
+ : schemaFields(schemaClass);
+
Collection<Field> internalExtensionsFields = extensionsFields(internalExtensions, true);
Collection<Field> polymorphicExtensionsFields = extensionsFields(polymorphicExtensions, false);
@@ -751,6 +758,7 @@ public class ConfigurationAsmGenerator {
// constructDefault
addNodeConstructDefaultMethod(
+ schemaClass,
classDef,
specFields,
fieldDefs,
@@ -772,6 +780,10 @@ public class ConfigurationAsmGenerator {
addInternalSchemaTypesMethod(classDef, internalSchemaTypesFieldDef);
}
+ if (schemaClass.getSuperclass().isAnnotationPresent(AbstractConfiguration.class)) {
+ addIsExtendAbstractConfigurationMethod(classDef);
+ }
+
return classDef;
}
@@ -1541,6 +1553,7 @@ public class ConfigurationAsmGenerator {
/**
* Implements {@link InnerNode#constructDefault(String)} method.
*
+ * @param schemaClass Configuration schema class.
* @param classDef Class definition.
* @param specFields Field definitions for the schema and its extensions: {@code _spec#}.
* @param fieldDefs Definitions for all fields in {@code schemaFields}.
@@ -1550,6 +1563,7 @@ public class ConfigurationAsmGenerator {
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
*/
private static void addNodeConstructDefaultMethod(
+ Class<?> schemaClass,
ClassDefinition classDef,
Map<Class<?>, FieldDefinition> specFields,
Map<String, FieldDefinition> fieldDefs,
@@ -1584,7 +1598,12 @@ public class ConfigurationAsmGenerator {
switchBuilder.addCase(fieldName, new BytecodeBlock().ret());
} else {
FieldDefinition fieldDef = fieldDefs.get(fieldName);
- FieldDefinition specFieldDef = specFields.get(schemaField.getDeclaringClass());
+
+ Class<?> fieldType = schemaField.getDeclaringClass();
+
+ FieldDefinition specFieldDef = fieldType.isAnnotationPresent(AbstractConfiguration.class)
+ ? specFields.get(schemaClass)
+ : specFields.get(fieldType);
// this.field = spec_#.field;
switchBuilder.addCase(
@@ -3406,4 +3425,21 @@ public class ConfigurationAsmGenerator {
.append(getThisFieldCode(mtd, internalSchemaTypesFieldDef))
.retObject();
}
+
+ /**
+ * Adds an override for the {@link InnerNode#extendsAbstractConfiguration()} method that returns {@code true}.
+ *
+ * @param innerNodeClassDef {@link InnerNode} class definition.
+ */
+ private static void addIsExtendAbstractConfigurationMethod(ClassDefinition innerNodeClassDef) {
+ MethodDefinition mtd = innerNodeClassDef.declareMethod(
+ of(PUBLIC),
+ "extendsAbstractConfiguration",
+ type(boolean.class)
+ );
+
+ mtd.getBody()
+ .push(true)
+ .retBoolean();
+ }
}
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/InnerNode.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/InnerNode.java
index f3efa681f..e2ea27957 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/InnerNode.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/InnerNode.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.configuration.tree;
import java.util.NoSuchElementException;
import java.util.UUID;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.InjectedName;
import org.apache.ignite.configuration.annotation.InternalConfiguration;
import org.apache.ignite.configuration.annotation.InternalId;
@@ -245,4 +246,11 @@ public abstract class InnerNode implements TraversableTreeNode, ConstructableTre
public boolean isPolymorphic() {
return false;
}
+
+ /**
+ * Returns {@code true} if the config schema extends {@link AbstractConfiguration}.
+ */
+ public boolean extendsAbstractConfiguration() {
+ return false;
+ }
}
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
index 850a80df6..c052ad853 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
@@ -630,7 +630,6 @@ public class ConfigurationUtil {
* PolymorphicId}.
*
* @param schemaClass Configuration schema class.
- * @return Schema fields.
*/
public static List<Field> schemaFields(Class<?> schemaClass) {
return Arrays.stream(schemaClass.getDeclaredFields())
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/validation/ValidationUtil.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/validation/ValidationUtil.java
index 68d02f162..e35285942 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/validation/ValidationUtil.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/validation/ValidationUtil.java
@@ -191,7 +191,7 @@ public class ValidationUtil {
private static @Nullable Field findSchemaField(InnerNode innerNode, String schemaFieldName) throws NoSuchFieldException {
Class<?> schemaType = innerNode.schemaType();
- if (innerNode.isPolymorphic()) {
+ if (innerNode.isPolymorphic() || innerNode.extendsAbstractConfiguration()) {
// Linear search to not fight with NoSuchFieldException.
for (Field field : schemaType.getDeclaredFields()) {
if (field.getName().equals(schemaFieldName)) {
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGeneratorTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGeneratorTest.java
index e32ebe6eb..8c7a9a5e6 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGeneratorTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGeneratorTest.java
@@ -25,6 +25,7 @@ import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
@@ -39,11 +40,13 @@ import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.apache.ignite.configuration.ConfigurationReadOnlyException;
import org.apache.ignite.configuration.ConfigurationWrongPolymorphicTypeIdException;
+import org.apache.ignite.configuration.annotation.AbstractConfiguration;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.ConfigValue;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.InjectedName;
import org.apache.ignite.configuration.annotation.InternalConfiguration;
+import org.apache.ignite.configuration.annotation.InternalId;
import org.apache.ignite.configuration.annotation.Name;
import org.apache.ignite.configuration.annotation.NamedConfigValue;
import org.apache.ignite.configuration.annotation.PolymorphicConfig;
@@ -103,7 +106,7 @@ public class ConfigurationAsmGeneratorTest {
changer = new TestConfigurationChanger(
generator,
- List.of(TestRootConfiguration.KEY, InjectedNameRootConfiguration.KEY),
+ List.of(TestRootConfiguration.KEY, InjectedNameRootConfiguration.KEY, RootFromAbstractConfiguration.KEY),
Map.of(),
new TestConfigurationStorage(LOCAL),
internalExtensions,
@@ -595,6 +598,54 @@ public class ConfigurationAsmGeneratorTest {
assertEquals("p4", rootCfg.nestedNamedPoly().get("p4").name().value());
}
+ @Test
+ void testAbstractConfiguration() throws Exception {
+ RootFromAbstractConfiguration rootFromAbstractConfig = (RootFromAbstractConfiguration) generator.instantiateCfg(
+ RootFromAbstractConfiguration.KEY,
+ changer
+ );
+
+ // Checks for default values.
+
+ assertEquals("test", rootFromAbstractConfig.configFromAbstract().name().value());
+
+ assertEquals("strVal", rootFromAbstractConfig.strVal().value());
+ assertEquals(500100, rootFromAbstractConfig.longVal().value());
+
+ assertEquals(100500, rootFromAbstractConfig.configFromAbstract().intVal().value());
+ assertTrue(rootFromAbstractConfig.configFromAbstract().booleanVal().value());
+
+ // Checks for changes to all fields at once.
+
+ rootFromAbstractConfig.change(ch0 -> ch0
+ .changeLongVal(1)
+ .changeConfigFromAbstract(ch1 -> ch1.changeBooleanVal(false).changeIntVal(1))
+ .changeStrVal("1")
+ ).get(1, SECONDS);
+
+ RootFromAbstractView fromAbstractView0 = rootFromAbstractConfig.value();
+
+ assertEquals("1", fromAbstractView0.strVal());
+ assertEquals(1, fromAbstractView0.longVal());
+
+ assertEquals(1, fromAbstractView0.configFromAbstract().intVal());
+ assertFalse(fromAbstractView0.configFromAbstract().booleanVal());
+
+ // Checks for changes to each field.
+
+ rootFromAbstractConfig.longVal().update(2L).get(1, SECONDS);
+ rootFromAbstractConfig.strVal().update("2").get(1, SECONDS);
+
+ rootFromAbstractConfig.configFromAbstract().intVal().update(2).get(1, SECONDS);
+ rootFromAbstractConfig.configFromAbstract().booleanVal().update(true).get(1, SECONDS);
+
+ assertEquals("2", rootFromAbstractConfig.strVal().value());
+ assertEquals(2, rootFromAbstractConfig.longVal().value());
+
+ assertEquals(2, rootFromAbstractConfig.configFromAbstract().intVal().value());
+ assertTrue(rootFromAbstractConfig.configFromAbstract().booleanVal().value());
+ }
+
/**
* Test root configuration schema.
*/
@@ -828,4 +879,50 @@ public class ConfigurationAsmGeneratorTest {
@PolymorphicConfigInstance(PolyInjectedNameConfigurationSchema.SECOND)
public static class PolyInst1InjectedNameConfigurationSchema extends PolyInjectedNameConfigurationSchema {
}
+
+ /**
+ * Simple abstract schema configuration for root configurations.
+ */
+ @AbstractConfiguration
+ public static class AbstractRootConfigurationSchema {
+ @Value(hasDefault = true)
+ public String strVal = "strVal";
+ }
+
+ /**
+ * Simple abstract schema configuration for configurations.
+ */
+ @AbstractConfiguration
+ public static class AbstractConfigurationSchema {
+ @InjectedName
+ public String name;
+
+ @InternalId
+ public UUID id;
+
+ @Value(hasDefault = true)
+ public int intVal = 100500;
+ }
+
+ /**
+ * Simple root configuration schema that extends {@link AbstractRootConfigurationSchema}.
+ */
+ @ConfigurationRoot(rootName = "rootFromAbstract")
+ public static class RootFromAbstractConfigurationSchema extends AbstractRootConfigurationSchema {
+ @Value(hasDefault = true)
+ public long longVal = 500100;
+
+ @Name("test")
+ @ConfigValue
+ public ConfigFromAbstractConfigurationSchema configFromAbstract;
+ }
+
+ /**
+ * Simple configuration schema that extends {@link AbstractRootConfigurationSchema}.
+ */
+ @Config
+ public static class ConfigFromAbstractConfigurationSchema extends AbstractConfigurationSchema {
+ @Value(hasDefault = true)
+ public boolean booleanVal = true;
+ }
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/CollectionUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/CollectionUtils.java
index 5002ac5e3..ad0372ddb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/CollectionUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/CollectionUtils.java
@@ -27,6 +27,7 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.IntSets;
import java.util.AbstractCollection;
+import java.util.AbstractList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -184,7 +185,6 @@ public final class CollectionUtils {
for (int i = 0; i < collections.length; i++) {
size += collections[i].size();
-
}
return size;
@@ -335,6 +335,66 @@ public final class CollectionUtils {
};
}
+ /**
+ * Concatenates lists.
+ *
+ * @param lists Lists.
+ * @param <T> Type of the elements of lists.
+ * @return Immutable list concatenation.
+ */
+ @SafeVarargs
+ public static <T> List<T> concat(List<T>... lists) {
+ if (lists == null || lists.length == 0) {
+ return List.of();
+ }
+
+ return new AbstractList<>() {
+ /** {@inheritDoc} */
+ @Override
+ public T get(int index) {
+ for (List<T> list : lists) {
+ if (index >= list.size()) {
+ index -= list.size();
+ } else {
+ return list.get(index);
+ }
+ }
+
+ throw new IndexOutOfBoundsException(index);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Iterator<T> iterator() {
+ return concat((Iterable<T>[]) lists).iterator();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int size() {
+ int size = 0;
+
+ for (List<T> list : lists) {
+ size += list.size();
+ }
+
+ return size;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean contains(Object o) {
+ for (List<T> list : lists) {
+ if (list.contains(o)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ };
+ }
+
/**
* Create a collection view that can only be read.
*
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/CollectionUtilsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/CollectionUtilsTest.java
index 41c1835db..f4f18d600 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/CollectionUtilsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/CollectionUtilsTest.java
@@ -176,41 +176,41 @@ public class CollectionUtilsTest {
@Test
void testCollectionUnion() {
- assertTrue(union().isEmpty());
+ assertTrue(union(new Collection[0]).isEmpty());
assertTrue(union((Collection<Object>[]) null).isEmpty());
assertTrue(union(List.of()).isEmpty());
- assertEquals(List.of(1), collect(union(List.of(1), List.of())));
- assertEquals(List.of(1), collect(union(List.of(), List.of(1))));
+ assertEquals(List.of(1), collect(union(List.of(1), Set.of())));
+ assertEquals(List.of(1), collect(union(List.of(), Set.of(1))));
- assertEquals(List.of(1, 2), collect(union(List.of(1), List.of(2))));
- assertEquals(List.of(1, 2, 2), collect(union(List.of(1), List.of(2), List.of(2))));
+ assertEquals(List.of(1, 2), collect(union(List.of(1), Set.of(2))));
+ assertEquals(List.of(1, 2, 2), collect(union(List.of(1), List.of(2), Set.of(2))));
- assertFalse(union().contains(0));
+ assertFalse(union(new Collection[0]).contains(0));
assertFalse(union(List.of()).contains(0));
assertFalse(union(List.of(1)).contains(0));
- assertFalse(union(List.of(1), List.of()).contains(0));
- assertFalse(union(List.of(), List.of(1)).contains(0));
- assertFalse(union(List.of(1), List.of(2, 3)).contains(0));
+ assertFalse(union(List.of(1), Set.of()).contains(0));
+ assertFalse(union(List.of(), Set.of(1)).contains(0));
+ assertFalse(union(List.of(1), Set.of(2, 3)).contains(0));
assertTrue(union(List.of(0)).contains(0));
- assertTrue(union(List.of(), List.of(0)).contains(0));
- assertTrue(union(List.of(0), List.of()).contains(0));
+ assertTrue(union(List.of(), Set.of(0)).contains(0));
+ assertTrue(union(List.of(0), Set.of()).contains(0));
- assertEquals(0, union().size());
+ assertEquals(0, union(new Collection[0]).size());
assertEquals(0, union(List.of()).size());
assertEquals(1, union(List.of(1)).size());
- assertEquals(1, union(List.of(), List.of(1)).size());
- assertEquals(1, union(List.of(1), List.of()).size());
- assertEquals(2, union(List.of(1), List.of(2)).size());
- assertEquals(3, union(List.of(1), List.of(2, 3)).size());
- assertEquals(5, union(List.of(1, 4, 5), List.of(2, 3)).size());
+ assertEquals(1, union(List.of(), Set.of(1)).size());
+ assertEquals(1, union(List.of(1), Set.of()).size());
+ assertEquals(2, union(List.of(1), Set.of(2)).size());
+ assertEquals(3, union(List.of(1), Set.of(2, 3)).size());
+ assertEquals(5, union(List.of(1, 4, 5), Set.of(2, 3)).size());
- List<Integer> integers = new ArrayList<>(List.of(1, 2, 3));
+ Collection<Integer> integers = new ArrayList<>(List.of(1, 2, 3));
Collection<Integer> union = union(integers);
- integers.remove(0);
+ integers.remove(1);
assertEquals(2, union.size());
}
@@ -269,6 +269,58 @@ public class CollectionUtilsTest {
assertEquals(List.of(1, 2, 3), collect(concat(List.of(List.of(1).iterator(), List.of(2, 3).iterator()))));
}
+ @Test
+ void testConcatList() {
+ assertTrue(concat(new List[0]).isEmpty());
+ assertTrue(concat((List<Object>[]) null).isEmpty());
+ assertTrue(concat((List<Object>) List.of()).isEmpty());
+
+ assertEquals(List.of(1), concat(List.of(1), List.of()));
+ assertEquals(List.of(1), concat(List.of(), List.of(1)));
+
+ assertEquals(List.of(1, 2), concat(List.of(1), List.of(2)));
+ assertEquals(List.of(1, 2, 2), concat(List.of(1), List.of(2), List.of(2)));
+
+ assertFalse(concat(new List[0]).contains(0));
+ assertFalse(concat((List<Object>) List.of()).contains(0));
+ assertFalse(concat(List.of(1)).contains(0));
+ assertFalse(concat(List.of(1), List.of()).contains(0));
+ assertFalse(concat(List.of(), List.of(1)).contains(0));
+ assertFalse(concat(List.of(1), List.of(2, 3)).contains(0));
+
+ assertTrue(concat(List.of(0)).contains(0));
+ assertTrue(concat(List.of(), List.of(0)).contains(0));
+ assertTrue(concat(List.of(0), List.of()).contains(0));
+
+ assertEquals(0, concat(new List[0]).size());
+ assertEquals(0, concat((List<Object>) List.of()).size());
+ assertEquals(1, concat(List.of(1)).size());
+ assertEquals(1, concat(List.of(), List.of(1)).size());
+ assertEquals(1, concat(List.of(1), List.of()).size());
+ assertEquals(2, concat(List.of(1), List.of(2)).size());
+ assertEquals(3, concat(List.of(1), List.of(2, 3)).size());
+ assertEquals(5, concat(List.of(1, 4, 5), List.of(2, 3)).size());
+
+ List<Integer> integers = new ArrayList<>(List.of(1, 2, 3));
+
+ List<Integer> union0 = concat(integers);
+
+ integers.remove(1);
+
+ assertEquals(2, union0.size());
+
+ List<Integer> union1 = concat(List.of(0), List.of(1, 2), List.of(3, 4, 5));
+
+ assertEquals(0, union1.get(0));
+ assertEquals(1, union1.get(1));
+ assertEquals(2, union1.get(2));
+ assertEquals(3, union1.get(3));
+ assertEquals(4, union1.get(4));
+ assertEquals(5, union1.get(5));
+
+ assertThrows(IndexOutOfBoundsException.class, () -> union1.get(6));
+ }
+
/**
* Collect of elements.
*