diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/ExceptionHandlingTest.java b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/ExceptionHandlingTest.java
new file mode 100644
index 0000000000..eb0b288382
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/ExceptionHandlingTest.java
@@ -0,0 +1,73 @@
+package com.devonfw.cobigen.eclipse.test;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
+import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.devonfw.cobigen.eclipse.common.constants.external.ResourceConstants;
+import com.devonfw.cobigen.eclipse.test.common.SystemTest;
+import com.devonfw.cobigen.eclipse.test.common.utils.EclipseCobiGenUtils;
+import com.devonfw.cobigen.eclipse.test.common.utils.EclipseUtils;
+
+/**
+ * Test suite for exception handling issues.
+ */
+@RunWith(SWTBotJunit4ClassRunner.class)
+public class ExceptionHandlingTest extends SystemTest {
+
+ /** Root path of the Test Resources */
+ private static final String resourcesRootPath = "src/main/resources/ExceptionHandlingTest/";
+
+ /**
+ * Setup workbench appropriately for tests
+ *
+ * @throws Exception test fails
+ */
+ @BeforeClass
+ public static void setupClass() throws Exception {
+
+ EclipseUtils.cleanWorkspace(bot, true);
+ // import the configuration project for this test
+ EclipseUtils.importExistingGeneralProject(bot, new File(resourcesRootPath + "templates").getAbsolutePath());
+ EclipseUtils.updateMavenProject(bot, ResourceConstants.CONFIG_PROJECT_NAME);
+ }
+
+ /**
+ * Tests for a conflict of old and new templates configuration and proper error message dialog
+ *
+ * @throws Exception Test fails
+ */
+ @Test
+ @Ignore
+ public void testConflictWithTemplateTypesDisplaysErrorDialog() throws Exception {
+
+ // create a new temporary java project and copy java class used as an input for CobiGen
+ String testProjectName = "TestInputProj";
+ IJavaProject project = this.tmpMavenProjectRule.createProject(testProjectName);
+ FileUtils.copyFile(new File(resourcesRootPath + "input/PlainInput.java"),
+ project.getUnderlyingResource().getLocation().append("src/main/java/main/PlainInput.java").toFile());
+ project.getProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
+ this.tmpMavenProjectRule.updateProject();
+
+ // expand the new file in the package explorer
+ SWTBotView view = bot.viewById(JavaUI.ID_PACKAGES);
+ SWTBotTreeItem javaClassItem = view.bot().tree().expandNode(testProjectName, "src/main/java", "main",
+ "PlainInput.java");
+ javaClassItem.select();
+
+ // execute CobiGen
+ EclipseCobiGenUtils.processCobiGenWithExpectedError(bot, javaClassItem, "Invalid context configuration!");
+ }
+
+}
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseCobiGenUtils.java b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseCobiGenUtils.java
index ec9d8406cc..8bf3ca2252 100644
--- a/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseCobiGenUtils.java
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseCobiGenUtils.java
@@ -46,6 +46,20 @@ public static void processCobiGen(SWTWorkbenchBot bot, SWTBotTreeItem input, Str
processCobiGen(bot, input, DEFAULT_TIMEOUT, increments);
}
+ /**
+ * Tries a Generate process with an expected error title.
+ *
+ * @param bot the {@link SWTWorkbenchBot} of the test
+ * @param input input of CobiGen to be selected
+ * @param expectedErrorTitle String of expected error title
+ * @throws Exception test fails
+ */
+ public static void processCobiGenWithExpectedError(SWTWorkbenchBot bot, SWTBotTreeItem input,
+ String expectedErrorTitle) throws Exception {
+
+ processCobiGenWithExpectedError(bot, input, DEFAULT_TIMEOUT, expectedErrorTitle);
+ }
+
/**
* Expands multi layer nodes of following format: node1>node2>finalNode
*
@@ -109,6 +123,31 @@ public static void processCobiGen(SWTWorkbenchBot bot, SWTBotTreeItem input, int
finishButton.click();
}
+ /**
+ * Tries a Generate process with an expected error title.
+ *
+ * @param bot the {@link SWTWorkbenchBot} of the test
+ * @param input input of CobiGen to be selected
+ * @param defaultTimeout timeout to be overwritten
+ * @param expectedErrorTitle String of expected error title
+ * @throws Exception test fails
+ */
+ public static void processCobiGenWithExpectedError(SWTWorkbenchBot bot, SWTBotTreeItem input, int defaultTimeout,
+ String expectedErrorTitle) throws Exception {
+
+ // Open generation wizard with new file as Input
+ ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
+ bot.waitUntil(new AllJobsAreFinished(), defaultTimeout); // build might take some time
+ input.contextMenu("CobiGen").menu("Generate...").click();
+ bot.waitUntil(new AnyShellIsActive(expectedErrorTitle), defaultTimeout);
+
+ takeScreenshot(bot, "InvalidConfigurationDialog");
+
+ SWTBotButton finishButton = bot.button(IDialogConstants.OK_LABEL);
+ bot.waitUntil(widgetIsEnabled(bot.button()));
+ finishButton.click();
+ }
+
/**
* Checks the CobiGen HealthCheck and takes screenshots of it.
*
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseUtils.java b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseUtils.java
index 288b1cc04a..26edf4f958 100644
--- a/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseUtils.java
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/java/com/devonfw/cobigen/eclipse/test/common/utils/EclipseUtils.java
@@ -187,7 +187,7 @@ public static void cleanWorkspace(SWTWorkbenchBot bot, boolean cleanCobiGenConfi
}
break;
} catch (Exception e) {
- LOG.debug("An error occured while trying to delete project: {}", projectName);
+ LOG.debug("An error occured while trying to delete project: {}", projectName, e);
Thread.sleep(500);
if (i == maxRetries) {
LOG.debug("Not able to cleanup the workspace after: {} retries", maxRetries);
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/input/PlainInput.java b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/input/PlainInput.java
new file mode 100644
index 0000000000..fc3a6a09ec
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/input/PlainInput.java
@@ -0,0 +1,5 @@
+package main;
+
+public class PlainInput {
+
+}
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/.project b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/.project
new file mode 100644
index 0000000000..29f3bb6869
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/.project
@@ -0,0 +1,23 @@
+
+
+ CobiGen_Templates
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/logback.xml b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/logback.xml
new file mode 100644
index 0000000000..a7c9f7855e
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/logback.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/pom.xml b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/pom.xml
new file mode 100644
index 0000000000..1246bdb412
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+ com.devonfw.cobigen
+ templates-oasp
+ 1.0.0
+ jar
+ CobiGen OASP Templates
+
+
+ 1.8
+ 1.8
+
+
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+ 2.0
+
+
+
+
\ No newline at end of file
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/context.xml b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/context.xml
new file mode 100644
index 0000000000..5b73512da1
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/context.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/TestOutput.txt.ftl b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/TestOutput.txt.ftl
new file mode 100644
index 0000000000..793aa682b0
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/TestOutput.txt.ftl
@@ -0,0 +1 @@
+This is a test
\ No newline at end of file
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/context.xml b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/context.xml
new file mode 100644
index 0000000000..5b73512da1
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/context.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/templates.xml b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/templates.xml
new file mode 100644
index 0000000000..ab128701e7
--- /dev/null
+++ b/cobigen-eclipse/cobigen-eclipse-test/src/main/resources/ExceptionHandlingTest/templates/src/main/templates/template1/templates.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/ExceptionHandler.java b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/ExceptionHandler.java
index 98d04ee046..139cef1e69 100644
--- a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/ExceptionHandler.java
+++ b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/ExceptionHandler.java
@@ -8,6 +8,7 @@
import org.slf4j.LoggerFactory;
import com.devonfw.cobigen.api.exception.CobiGenRuntimeException;
+import com.devonfw.cobigen.api.exception.ConfigurationConflictException;
import com.devonfw.cobigen.api.exception.InvalidConfigurationException;
import com.devonfw.cobigen.eclipse.common.constants.external.ResourceConstants;
import com.devonfw.cobigen.eclipse.common.exceptions.GeneratorCreationException;
@@ -36,6 +37,8 @@ public static void handle(Throwable e, Shell activeShell) {
} else if (InvalidConfigurationException.class.isAssignableFrom(e.getClass())) {
LOG.warn("Invalid configuration.", e);
openInvalidConfigurationErrorDialog((InvalidConfigurationException) e);
+ } else if (ConfigurationConflictException.class.isAssignableFrom(e.getClass())) {
+ openInvalidConfigurationErrorDialog((ConfigurationConflictException) e);
} else if (GeneratorProjectNotExistentException.class.isAssignableFrom(e.getClass())) {
LOG.error(
"The project '{}' containing the configuration and templates is currently not existent. Please create one or check it out from SVN as stated in the user documentation.",
@@ -56,6 +59,7 @@ public static void handle(Throwable e, Shell activeShell) {
LOG.error("An unexpected exception occurred!", e);
PlatformUIUtil.openErrorDialog("An unexpected exception occurred!", e);
}
+
}
/**
@@ -74,18 +78,21 @@ private static Shell getShell(Shell activeShell) {
*/
private static void openInvalidConfigurationErrorDialog(InvalidConfigurationException e) {
- MessageDialog dialog = new MessageDialog(Display.getDefault().getActiveShell(), "Invalid context configuration!",
- null,
- "Any context/templates configuration has been changed into an invalid state "
- + "OR is simply outdated, if you recently updated CobiGen. "
- + "For further investigation and automatic upgrade options start CobiGen's Health Check."
- + "\n\nOriginal error message: " + e.getMessage(),
- MessageDialog.ERROR, new String[] { "Health Check", "OK" }, 1);
- dialog.setBlockOnOpen(true);
+ PlatformUIUtil.getWorkbench().getDisplay().syncExec(() -> {
+ MessageDialog dialog = new MessageDialog(Display.getDefault().getActiveShell(), "Invalid context configuration!",
+ null,
+ "Any context/templates configuration has been changed into an invalid state "
+ + "OR is simply outdated, if you recently updated CobiGen. "
+ + "For further investigation and automatic upgrade options start CobiGen's Health Check."
+ + "\n\nOriginal error message: " + e.getMessage(),
+ MessageDialog.ERROR, new String[] { "Health Check", "OK" }, 1);
+ dialog.setBlockOnOpen(true);
- int result = dialog.open();
- if (result == 0) {
- new HealthCheckDialog().execute();
- }
+ int result = dialog.open();
+ if (result == 0) {
+ new HealthCheckDialog().execute();
+ }
+ });
}
+
}
diff --git a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/PlatformUIUtil.java b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/PlatformUIUtil.java
index edfb5161aa..41ea49d1b8 100644
--- a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/PlatformUIUtil.java
+++ b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/common/tools/PlatformUIUtil.java
@@ -75,17 +75,14 @@ public static IWorkbenchPage getActiveWorkbenchPage() {
*/
public static void openErrorDialog(final String message, final Throwable cause) {
- getWorkbench().getDisplay().syncExec(new Runnable() {
- @Override
- public void run() {
-
- if (cause == null) {
- MessageDialog.openError(Display.getDefault().getActiveShell(), CobiGenDialogConstants.DIALOG_TITLE_ERROR,
- message);
- } else {
- LinkErrorDialog.openError(Display.getDefault().getActiveShell(), CobiGenDialogConstants.DIALOG_TITLE_ERROR,
- message, createMultiStatus(cause));
- }
+ getWorkbench().getDisplay().syncExec(() -> {
+
+ if (cause == null) {
+ MessageDialog.openError(Display.getDefault().getActiveShell(), CobiGenDialogConstants.DIALOG_TITLE_ERROR,
+ message);
+ } else {
+ LinkErrorDialog.openError(Display.getDefault().getActiveShell(), CobiGenDialogConstants.DIALOG_TITLE_ERROR,
+ message, createMultiStatus(cause));
}
});
diff --git a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/healthcheck/HealthCheckDialog.java b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/healthcheck/HealthCheckDialog.java
index cc2c0be452..47ff73fc81 100644
--- a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/healthcheck/HealthCheckDialog.java
+++ b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/healthcheck/HealthCheckDialog.java
@@ -15,6 +15,7 @@
import com.devonfw.cobigen.api.HealthCheck;
import com.devonfw.cobigen.api.constants.BackupPolicy;
import com.devonfw.cobigen.api.constants.ConfigurationConstants;
+import com.devonfw.cobigen.api.exception.ConfigurationConflictException;
import com.devonfw.cobigen.api.exception.InvalidConfigurationException;
import com.devonfw.cobigen.api.to.HealthCheckReport;
import com.devonfw.cobigen.api.util.CobiGenPaths;
@@ -106,6 +107,11 @@ public void execute() {
+ "=> Please import the configuration project into your workspace as stated in the "
+ "documentation of CobiGen or in the one of your project.";
PlatformUIUtil.openErrorDialog(healthyCheckMessage, null);
+ } catch (ConfigurationConflictException e) {
+ healthyCheckMessage = "An unexpected error occurred! Templates were in a conflicted state.";
+ healthyCheckMessage += "\n\nNo automatic upgrade of the context configuration possible.";
+ PlatformUIUtil.openErrorDialog(healthyCheckMessage, e);
+ LOG.error(healthyCheckMessage, e);
} catch (InvalidConfigurationException e) {
// Won't be reached anymore
healthyCheckMessage = firstStep + "OK.";
diff --git a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/workbenchcontrol/handler/GenerateJob.java b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/workbenchcontrol/handler/GenerateJob.java
index 7af23ca907..9ae3340701 100644
--- a/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/workbenchcontrol/handler/GenerateJob.java
+++ b/cobigen-eclipse/cobigen-eclipse/src/com/devonfw/cobigen/eclipse/workbenchcontrol/handler/GenerateJob.java
@@ -76,8 +76,8 @@ public void run(IProgressMonitor monitor) throws InvocationTargetException, Inte
monitor.beginTask("Searching valid triggers...", 1);
if (!generator.isValidInput(monitor)) {
LOG.info("No matching Trigger. Exiting generate command.");
- PlatformUIUtil.getWorkbench().getDisplay()
- .syncExec(() -> MessageDialog.openInformation(HandlerUtil.getActiveShell(this.event), "No matching Trigger!",
+ PlatformUIUtil.getWorkbench().getDisplay().syncExec(
+ () -> MessageDialog.openInformation(HandlerUtil.getActiveShell(this.event), "No matching Trigger!",
"Your current selection is not valid as input for any generation purpose. "
+ "Please find the specification of valid inputs in the context configuration ('"
+ ResourceConstants.CONFIG_PROJECT_NAME + "/context.xml')."));
diff --git a/cobigen-eclipse/pom.xml b/cobigen-eclipse/pom.xml
index 56a5799c7c..2ec7ef8031 100644
--- a/cobigen-eclipse/pom.xml
+++ b/cobigen-eclipse/pom.xml
@@ -14,7 +14,7 @@
https://oss.sonatype.org/content/groups/public/
- http://download.eclipse.org/releases/photon
+ https://download.eclipse.org/releases/photon
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/main/java/com/devonfw/cobigen/javaplugin/merger/JavaMerger.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/main/java/com/devonfw/cobigen/javaplugin/merger/JavaMerger.java
index 6aaeb9d70f..19dbcae867 100644
--- a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/main/java/com/devonfw/cobigen/javaplugin/merger/JavaMerger.java
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/main/java/com/devonfw/cobigen/javaplugin/merger/JavaMerger.java
@@ -10,6 +10,9 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import com.devonfw.cobigen.api.exception.MergeException;
import com.devonfw.cobigen.api.extension.Merger;
@@ -17,11 +20,14 @@
import com.devonfw.cobigen.api.util.SystemUtil;
import com.devonfw.cobigen.javaplugin.inputreader.JavaParserUtil;
import com.devonfw.cobigen.javaplugin.merger.libextension.ModifyableJavaClass;
+import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaConstructor;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaInitializer;
import com.thoughtworks.qdox.model.JavaMethod;
+import com.thoughtworks.qdox.model.impl.DefaultJavaField;
+import com.thoughtworks.qdox.model.impl.DefaultJavaMethod;
import com.thoughtworks.qdox.parser.ParseException;
/**
@@ -112,6 +118,7 @@ public String merge(File base, String patch, String targetCharset) throws MergeE
*/
private ModifyableJavaClass merge(ModifyableJavaClass baseClass, ModifyableJavaClass patchClass) {
+ baseClass.setAnnotations(mergeAnnotation(baseClass.getAnnotations(), patchClass.getAnnotations()));
mergeImports(baseClass, patchClass);
mergeFields(baseClass, patchClass);
mergeInnerClasses(baseClass, patchClass);
@@ -120,6 +127,24 @@ private ModifyableJavaClass merge(ModifyableJavaClass baseClass, ModifyableJavaC
return baseClass;
}
+ /**
+ * @param baseAnnotations {@link JavaClass} a List of annotations originate from the base class
+ * @param patchAnnotations {@link JavaClass} a List of annotations originate from the patch class
+ */
+ private List mergeAnnotation(List baseAnnotations,
+ List patchAnnotations) {
+
+ List bAnnotations = this.patchOverrides ? patchAnnotations : baseAnnotations;
+ List pAnnotations = this.patchOverrides ? baseAnnotations : patchAnnotations;
+
+ Set annotationNames = bAnnotations.stream().map(a -> a.getType().getName()).collect(Collectors.toSet());
+
+ List annotationsToMerge = pAnnotations.stream()
+ .filter(a -> !annotationNames.contains(a.getType().getName())).collect(Collectors.toList());
+
+ return Stream.of(bAnnotations, annotationsToMerge).flatMap(a -> a.stream()).collect(Collectors.toList());
+ }
+
/**
* Merges all super types of the two class sources
*
@@ -231,9 +256,11 @@ private void mergeFields(ModifyableJavaClass baseClass, ModifyableJavaClass patc
if (baseField == null) {
baseClass.addField(patchField);
} else {
+ ((DefaultJavaField) baseField)
+ .setAnnotations(new ArrayList<>(mergeAnnotation(baseField.getAnnotations(), patchField.getAnnotations())));
if (this.patchOverrides) {
baseClass.replace(baseField, patchField);
- } // else do not override
+ }
}
}
}
@@ -288,11 +315,14 @@ private void mergeMethods(ModifyableJavaClass baseClass, ModifyableJavaClass pat
if (baseMethod == null) {
baseClass.addMethod(patchMethod);
} else {
+ ((DefaultJavaMethod) baseMethod)
+ .setAnnotations(mergeAnnotation(baseMethod.getAnnotations(), patchMethod.getAnnotations()));
if (this.patchOverrides) {
baseClass.replace(baseMethod, patchMethod);
- } // else do not override
+ }
}
}
+
}
/**
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/java/com/devonfw/cobigen/javaplugin/unittest/merger/JavaMergerTest.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/java/com/devonfw/cobigen/javaplugin/unittest/merger/JavaMergerTest.java
index cb9f176e35..e7081800b8 100644
--- a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/java/com/devonfw/cobigen/javaplugin/unittest/merger/JavaMergerTest.java
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/java/com/devonfw/cobigen/javaplugin/unittest/merger/JavaMergerTest.java
@@ -517,4 +517,86 @@ private JavaSource getMergedSource(File baseFile, File patchFile, boolean overri
return getFirstJavaClass(new StringReader(mergedContents)).getSource();
}
+ /**
+ * Tests merging the class annotation into the baseFile
+ *
+ * @throws IOException shouldn't happen
+ * @throws MergeException shouldn't happen either
+ */
+ @Test
+ public void testMergeClassAnnotation() throws IOException, MergeException {
+
+ File baseFile = new File(testFileRootPath + "BaseFile_ClassAnnotation.java");
+ File patchFile = new File(testFileRootPath + "PatchFile_ClassAnnotation.java");
+
+ // with override
+ String mergedContents = new JavaMerger("", true).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Entity");
+ assertThat(mergedContents).contains("@javax.persistence.Table(name=\"Visitor\")");
+
+ // without override
+ mergedContents = new JavaMerger("", false).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Entity");
+ assertThat(mergedContents).contains("@javax.persistence.Table(name=\"Visits\")");
+ }
+
+ /**
+ * Tests merging a property annotation into the baseFile
+ *
+ * @throws IOException shouldn't happen
+ * @throws MergeException shouldn't happen either
+ */
+ @Test
+ public void testMergePropertyAnnotation() throws IOException, MergeException {
+
+ File baseFile = new File(testFileRootPath + "BaseFile_PropertyAnnotation.java");
+ File patchFile = new File(testFileRootPath + "PatchFile_PropertyAnnotation.java");
+
+ // with override
+ String mergedContents = new JavaMerger("", false).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Column(name=\"USER\")");
+ assertThat(mergedContents).contains("@Column(name=\"NAME\")");
+
+ // without override
+
+ mergedContents = new JavaMerger("", true).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Column(name= \"USERNAME\")");
+ assertThat(mergedContents).contains("@Column(name=\"NAME\")");
+
+ }
+
+ /**
+ * Tests merging a Method annotation into the baseFile
+ *
+ * @throws IOException shouldn't happen
+ * @throws MergeException shouldn't happen either
+ */
+ @Test
+ public void testMergeMethodAnnotation() throws IOException, MergeException {
+
+ File baseFile = new File(testFileRootPath + "BaseFile_MethodAnnotation.java");
+ File patchFile = new File(testFileRootPath + "PatchFile_MethodAnnotation.java");
+
+ // with override
+ String mergedContents = new JavaMerger("", true).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Column(name=\"USERNAME\")");
+ assertThat(mergedContents).contains("@Column(name=\"USER\")");
+
+ // without override
+ mergedContents = new JavaMerger("", false).merge(baseFile,
+ FileUtils.readFileToString(patchFile, StandardCharsets.UTF_8), "UTF-8");
+
+ assertThat(mergedContents).contains("@Column(name=\"NAME\")");
+ assertThat(mergedContents).contains("@Column(name=\"USER\")");
+ }
}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_ClassAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_ClassAnnotation.java
new file mode 100644
index 0000000000..1cda116c8c
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_ClassAnnotation.java
@@ -0,0 +1,14 @@
+package com.devonfw.application.jtqj.general.dataaccess.api;
+
+import com.devonfw.application.jtqj.general.common.api.Visitor;
+
+@javax.persistence.Table(name = "Visits")
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ private String username;
+
+ private String name;
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_MethodAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_MethodAnnotation.java
new file mode 100644
index 0000000000..90fc95dd98
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_MethodAnnotation.java
@@ -0,0 +1,21 @@
+package com.devonfw;
+
+/**
+ * Data access object for Visitor entities
+ */
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ private String username;
+
+ private String name;
+
+ @Column(name = "NAME")
+ public String getUsername() {
+ return this.username;
+ }
+
+ public String getName() {
+ return this.Name;
+ }
+
+}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_PropertyAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_PropertyAnnotation.java
new file mode 100644
index 0000000000..d7fc5453de
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/BaseFile_PropertyAnnotation.java
@@ -0,0 +1,20 @@
+package com.devonfw.application.jtqj.general.dataaccess.api;
+
+import javax.persistence.Entity;
+import com.devonfw.application.jtqj.general.common.api.Visitor;
+
+/**
+ * Data access object for Visitor entities
+ */
+@Entity
+@javax.persistence.Table(name = "Visitor")
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ @Column(name = "USER")
+ private String username;
+
+ private String name;
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_ClassAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_ClassAnnotation.java
new file mode 100644
index 0000000000..640c7cc03c
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_ClassAnnotation.java
@@ -0,0 +1,16 @@
+package com.devonfw.application.jtqj.general.dataaccess.api;
+
+import javax.persistence.Entity;
+
+import com.devonfw.application.jtqj.general.common.api.Visitor;
+
+/**
+ * Data access object for Visitor entities
+ */
+@Entity
+@javax.persistence.Table(name = "Visitor")
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_MethodAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_MethodAnnotation.java
new file mode 100644
index 0000000000..5bc2ef2cb3
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_MethodAnnotation.java
@@ -0,0 +1,22 @@
+package com.devonfw;
+
+/**
+ * Data access object for Visitor entities
+ */
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ private String username;
+
+ private String name;
+
+ @Column(name = "USERNAME")
+ public String getUsername() {
+ return this.username;
+ }
+
+ @Column(name = "USER")
+ public String getName() {
+ return this.Name;
+ }
+
+}
diff --git a/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_PropertyAnnotation.java b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_PropertyAnnotation.java
new file mode 100644
index 0000000000..2cea6f2b90
--- /dev/null
+++ b/cobigen-plugins/cobigen-javaplugin-parent/cobigen-javaplugin/src/test/resources/testdata/unittest/merger/PatchFile_PropertyAnnotation.java
@@ -0,0 +1,22 @@
+package com.devonfw.application.jtqj.general.dataaccess.api;
+
+import javax.persistence.Entity;
+
+import com.devonfw.application.jtqj.general.common.api.Visitor;
+
+/**
+ * Data access object for Visitor entities
+ */
+@Entity
+@javax.persistence.Table(name = "Visitor")
+public class VisitorEntity extends ApplicationPersistenceEntity implements Visitor {
+
+ private static final long serialVersionUID = 1L;
+
+ @Column(name = "USERNAME")
+ private String username;
+
+
+ @Column(name = "NAME")
+ private String name;
+}
diff --git a/cobigen-plugins/cobigen-tsplugin/pom.xml b/cobigen-plugins/cobigen-tsplugin/pom.xml
index bce39669c3..8e12e9ec30 100644
--- a/cobigen-plugins/cobigen-tsplugin/pom.xml
+++ b/cobigen-plugins/cobigen-tsplugin/pom.xml
@@ -12,7 +12,7 @@
- 1.1.7
+ 1.1.9
https://registry.npmjs.org/@devonfw/cobigen-nestserver/-/cobigen-nestserver-${server.version}.tgz
https://registry.npmjs.org/@devonfw/cobigen-nestserver-linux/-/cobigen-nestserver-linux-${server.version}.tgz
https://registry.npmjs.org/@devonfw/cobigen-nestserver-macos/-/cobigen-nestserver-macos-${server.version}.tgz
diff --git a/cobigen-plugins/cobigen-tsplugin/src/test/java/com/devonfw/cobigen/tsplugin/merger/TypeScriptMergerTest.java b/cobigen-plugins/cobigen-tsplugin/src/test/java/com/devonfw/cobigen/tsplugin/merger/TypeScriptMergerTest.java
index 5409b88583..c2d702180b 100644
--- a/cobigen-plugins/cobigen-tsplugin/src/test/java/com/devonfw/cobigen/tsplugin/merger/TypeScriptMergerTest.java
+++ b/cobigen-plugins/cobigen-tsplugin/src/test/java/com/devonfw/cobigen/tsplugin/merger/TypeScriptMergerTest.java
@@ -35,8 +35,8 @@ public class TypeScriptMergerTest {
public void testMergingNoOverrides() {
// arrange
- Merger tsMerger = this.activator.bindMerger().stream().filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE))
- .findFirst().get();
+ Merger tsMerger = this.activator.bindMerger().stream()
+ .filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE)).findFirst().get();
File baseFile = new File(testFileRootPath + "baseFile.ts");
// Should merge comments
@@ -74,7 +74,7 @@ public void testMergingNoOverrides() {
}
/**
- * Checks if the ts-merger can be launched and if the iutput is correct with patchOverrides = true
+ * Checks if the ts-merger can be launched and if the output is correct with patchOverrides = true
*/
@Test
public void testMergingOverrides() {
@@ -117,6 +117,29 @@ public void testMergingOverrides() {
}
+ /**
+ * Checks if the ts-merger can merge an export const with patchOverrides = true correctly
+ *
+ * Check: https://github.com/devonfw/cobigen/issues/1291
+ */
+ @Test
+ public void testMergingOverridesExportConst() {
+
+ // arrange
+ Merger tsMerger = this.activator.bindMerger().stream()
+ .filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE_OVERRIDE)).findFirst().get();
+ File baseFile = new File(testFileRootPath + "export_const_base.ts");
+
+ // act
+ String mergedContents = tsMerger.merge(baseFile, readTSFile("export_const_patch.ts"), "UTF-8");
+
+ // Should merge properly
+ assertThat(mergedContents).contains("export const test = {");
+ assertThat(mergedContents).contains("a: false");
+ assertThat(mergedContents).contains("b: true");
+
+ }
+
/**
* We need to test whether we are able to send large amount of data to the server.
*/
@@ -124,8 +147,8 @@ public void testMergingOverrides() {
public void testMergingMassiveFile() {
// arrange
- Merger tsMerger = this.activator.bindMerger().stream().filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE))
- .findFirst().get();
+ Merger tsMerger = this.activator.bindMerger().stream()
+ .filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE)).findFirst().get();
File baseFile = new File(testFileRootPath + "massiveFile.ts");
// act
@@ -143,8 +166,8 @@ public void testMergingMassiveFile() {
public void testReadingEncoding() throws IOException {
// Arrange
- Merger tsMerger = this.activator.bindMerger().stream().filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE))
- .findFirst().get();
+ Merger tsMerger = this.activator.bindMerger().stream()
+ .filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE)).findFirst().get();
File baseFile = new File(testFileRootPath + "baseFile_encoding_UTF-8.ts");
File patchFile = new File(testFileRootPath + "patchFile.ts");
@@ -191,8 +214,8 @@ private String readTSFile(String fileName) {
@Test
public void testNullAndUndefinedTypes() {
- Merger tsMerger = this.activator.bindMerger().stream().filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE))
- .findFirst().get();
+ Merger tsMerger = this.activator.bindMerger().stream()
+ .filter(e -> e.getType().equals(TypeScriptPluginActivator.TSMERGE)).findFirst().get();
File baseFile = new File(testFileRootPath + "nullBase.ts");
String mergedContents = tsMerger.merge(baseFile, readTSFile("nullPatch.ts"), "UTF-8");
assertEquals(false, mergedContents.contains("Not able to merge") || mergedContents.isEmpty());
diff --git a/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_base.ts b/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_base.ts
new file mode 100644
index 0000000000..c32abab595
--- /dev/null
+++ b/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_base.ts
@@ -0,0 +1,5 @@
+export const test: {
+ a: boolean;
+} = {
+ a: false
+};
\ No newline at end of file
diff --git a/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_patch.ts b/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_patch.ts
new file mode 100644
index 0000000000..929e32d013
--- /dev/null
+++ b/cobigen-plugins/cobigen-tsplugin/src/test/resources/testdata/unittest/files/export_const_patch.ts
@@ -0,0 +1,5 @@
+export const test: {
+ b: boolean;
+} = {
+ b: true
+};
\ No newline at end of file
diff --git a/cobigen/cobigen-core-api/src/main/java/com/devonfw/cobigen/api/exception/ConfigurationConflictException.java b/cobigen/cobigen-core-api/src/main/java/com/devonfw/cobigen/api/exception/ConfigurationConflictException.java
new file mode 100644
index 0000000000..fbc9495a69
--- /dev/null
+++ b/cobigen/cobigen-core-api/src/main/java/com/devonfw/cobigen/api/exception/ConfigurationConflictException.java
@@ -0,0 +1,23 @@
+package com.devonfw.cobigen.api.exception;
+
+import java.nio.file.Path;
+
+/** Occurs if a conflict between the configuration was found */
+public class ConfigurationConflictException extends InvalidConfigurationException {
+
+ /** Default serial version UID */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new {@link ConfigurationConflictException} with the given message
+ *
+ * @param filePath file path causing the ConfigurationConflictException or null if not available
+ * @param msg error message of the exception
+ * @param t cause exception
+ */
+ public ConfigurationConflictException(Path filePath, String msg) {
+
+ super(filePath, msg);
+ }
+
+}
diff --git a/cobigen/cobigen-core/src/main/java/com/devonfw/cobigen/impl/config/reader/ContextConfigurationReader.java b/cobigen/cobigen-core/src/main/java/com/devonfw/cobigen/impl/config/reader/ContextConfigurationReader.java
index 7eb0a7b5c5..d8859b3431 100644
--- a/cobigen/cobigen-core/src/main/java/com/devonfw/cobigen/impl/config/reader/ContextConfigurationReader.java
+++ b/cobigen/cobigen-core/src/main/java/com/devonfw/cobigen/impl/config/reader/ContextConfigurationReader.java
@@ -1,13 +1,21 @@
package com.devonfw.cobigen.impl.config.reader;
+import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.devonfw.cobigen.api.constants.ConfigurationConstants;
+import com.devonfw.cobigen.api.exception.ConfigurationConflictException;
import com.devonfw.cobigen.api.exception.InvalidConfigurationException;
+import com.devonfw.cobigen.impl.config.constant.WikiConstants;
import com.devonfw.cobigen.impl.config.entity.Trigger;
import com.devonfw.cobigen.impl.config.entity.io.ContextConfiguration;
import com.google.common.collect.Maps;
@@ -15,11 +23,14 @@
/** The {@link ContextConfigurationReader} reads the context xml */
public class ContextConfigurationReader extends AbstractContextConfigurationReader {
+ /** Logger instance. */
+ private static final Logger LOG = LoggerFactory.getLogger(ContextConfigurationReader.class);
+
/**
- * The constructor.
+ * Creates a new instance of the {@link ContextConfigurationReader} which initially parses the given context file
*
- * @param configRoot the config root directory
- * @throws InvalidConfigurationException if the configuration is not valid
+ * @param configRoot root directory of the configuration
+ * @throws InvalidConfigurationException if the configuration is not valid against its xsd specification
*/
public ContextConfigurationReader(Path configRoot) throws InvalidConfigurationException {
@@ -35,11 +46,18 @@ public ContextConfigurationReader(Path configRoot) throws InvalidConfigurationEx
configRoot = configRoot.resolve(ConfigurationConstants.TEMPLATE_RESOURCE_FOLDER);
contextFile = configRoot.resolve(ConfigurationConstants.CONTEXT_CONFIG_FILENAME);
if (!Files.exists(contextFile)) {
+
throw new InvalidConfigurationException(contextFile, "Could not find any context configuration file.");
+
} else {
+ checkForConflict(configRoot, contextFile);
this.contextFiles.add(contextFile);
}
} else {
+ Path subConfigRoot = configRoot.resolve(ConfigurationConstants.TEMPLATE_RESOURCE_FOLDER);
+ if (Files.isDirectory(subConfigRoot)) {
+ checkForConflict(subConfigRoot, contextFile);
+ }
this.contextFiles.add(contextFile);
}
@@ -48,6 +66,61 @@ public ContextConfigurationReader(Path configRoot) throws InvalidConfigurationEx
readConfiguration();
}
+ /**
+ * Checks if a conflict with the old and modular configuration exists
+ *
+ * @param configRoot Path to root directory of the configuration
+ * @param contextFile Path to context file of the configuration
+ */
+ private void checkForConflict(Path configRoot, Path contextFile) {
+
+ if (!loadContextFilesInSubfolder(configRoot).isEmpty()) {
+ String message = "You are using an old configuration of the templates in addition to new ones. Please make sure this is not the case as both at the same time are not supported. For more details visit this wiki page: "
+ + WikiConstants.WIKI_UPDATE_OLD_CONFIG;
+ ConfigurationConflictException exception = new ConfigurationConflictException(contextFile, message);
+ LOG.error("A conflict with the old and modular configuration exists", exception);
+ throw exception;
+ }
+
+ }
+
+ /**
+ * search for configuration Files in the subfolders of configRoot
+ *
+ * @param configRoot root directory of the configuration
+ * @throws InvalidConfigurationException if the configuration is not valid against its xsd specification
+ */
+ private List loadContextFilesInSubfolder(Path configRoot) {
+
+ List contextPaths = new ArrayList<>();
+
+ List templateDirectories = new ArrayList<>();
+
+ try (Stream files = Files.list(configRoot)) {
+ files.forEach(path -> {
+ if (Files.isDirectory(path)) {
+ templateDirectories.add(path);
+ }
+ });
+ } catch (IOException e) {
+ throw new InvalidConfigurationException(configRoot, "Could not read configuration root directory.", e);
+ }
+
+ for (Path file : templateDirectories) {
+ Path contextPath = file.resolve(ConfigurationConstants.CONTEXT_CONFIG_FILENAME);
+ if (Files.exists(contextPath)) {
+ contextPaths.add(contextPath);
+ }
+ }
+
+ return contextPaths;
+ }
+
+ /**
+ * Loads all {@link Trigger}s of the static context into the local representation
+ *
+ * @return a {@link List} containing all the {@link Trigger}s
+ */
@Override
public Map loadTriggers() {
diff --git a/cobigen/cobigen-core/src/test/java/com/devonfw/cobigen/unittest/config/reader/ContextConfigurationReaderTest.java b/cobigen/cobigen-core/src/test/java/com/devonfw/cobigen/unittest/config/reader/ContextConfigurationReaderTest.java
index 3518af30a6..eee54e6a58 100644
--- a/cobigen/cobigen-core/src/test/java/com/devonfw/cobigen/unittest/config/reader/ContextConfigurationReaderTest.java
+++ b/cobigen/cobigen-core/src/test/java/com/devonfw/cobigen/unittest/config/reader/ContextConfigurationReaderTest.java
@@ -10,8 +10,10 @@
import org.junit.Test;
import com.devonfw.cobigen.api.constants.ConfigurationConstants;
+import com.devonfw.cobigen.api.exception.ConfigurationConflictException;
import com.devonfw.cobigen.api.exception.InvalidConfigurationException;
import com.devonfw.cobigen.impl.CobiGenFactory;
+import com.devonfw.cobigen.impl.config.constant.WikiConstants;
import com.devonfw.cobigen.impl.config.reader.AbstractContextConfigurationReader;
import com.devonfw.cobigen.impl.config.reader.ContextConfigurationReader;
import com.devonfw.cobigen.impl.config.reader.ContextConfigurationReaderFactory;
@@ -61,7 +63,25 @@ public void testInvalidTemplateSets() throws InvalidConfigurationException {
}
/**
- * Tests whether a valid configuration can be read from template-sets/adapted folder
+ * Tests whether an {@link ConfigurationConflictException} will be thrown when both a v2.1 and v2.2 context.xml are
+ * present (new templates with old custom templates). Also tests if the thrown error message contains a link to the
+ * wiki.
+ *
+ * @throws ConfigurationConflictException if a conflict occurred
+ *
+ */
+ @Test
+ public void testConflictConfiguration() throws ConfigurationConflictException {
+
+ Throwable bothPresent = assertThrows(ConfigurationConflictException.class, () -> {
+ new ContextConfigurationReader(Paths.get(testFileRootPath + "conflicted_old_templates"));
+ });
+
+ assertThat(bothPresent instanceof ConfigurationConflictException);
+ assertThat(bothPresent.getMessage()).contains(WikiConstants.WIKI_UPDATE_OLD_CONFIG);
+ }
+
+ /**
*
* @throws Exception test fails
*/
diff --git a/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/context.xml b/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/context.xml
new file mode 100644
index 0000000000..9b2de76c8e
--- /dev/null
+++ b/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/context.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/test_template/context.xml b/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/test_template/context.xml
new file mode 100644
index 0000000000..caccd81ab9
--- /dev/null
+++ b/cobigen/cobigen-core/src/test/resources/testdata/unittest/config/reader/ContextConfigurationReaderTest/conflicted_old_templates/src/main/templates/test_template/context.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/documentation/cobigen-core_configuration.asciidoc b/documentation/cobigen-core_configuration.asciidoc
index 11f1e49016..3d6d16060e 100644
--- a/documentation/cobigen-core_configuration.asciidoc
+++ b/documentation/cobigen-core_configuration.asciidoc
@@ -3,6 +3,8 @@ toc::[]
= Configuration
+== CobiGen HOME directory
+
CobiGen is maintaining a home directory further referenced in this documentation as `$cghome`, which is used to maintain temporary or transient data. The home folder is determined with the following location fall-back:
1. System environment variable `COBIGEN_HOME` (e.g. `C:\project\ide\conf\cobigen-home`)
@@ -18,20 +20,99 @@ The actual configuration of CobiGen is maintained by a single folder or jar. The
4. The lexicographical sorted first configuration jar of the following path pattern `$cghome/templates/templates-([^-]+)-(\\d+\\.?)+.jar` if exists (e.g. `templates-devon4j-2020.04.001`)
5. CobiGen will automatically download the latest jar configuration from maven central with `groupId` `com.devonfw.cobigen` and `artifactId` `templates-devon4j` and take it like described in 4.
-
Within the configuration jar or directory you will find the following structure:
```
CobiGen_Templates
|- templateFolder1
- |- templates.xml
+ |- src
+ |- main
+ |- templates
+ |- template1
+ |- templates
+ |- templates.xml
|- templateFolder2
- |- templates.xml
|- context.xml
```
+Since: CobiGen 2021.12.007:
+
+```
+template-sets
+ |- downloaded
+ |- template-set1.jar
+ |- template-set2.jar
+ |- template-set-utilities.jar
+ |- adapted
+ |- template-set1
+ |- src
+ |- main
+ |- templates
+ |- templates
+ |- context.xml
+ |- templates.xml
+ |- template-set2
+```
+
Find some examples https://github.com/devonfw/cobigen/tree/master/cobigen-templates[here].
+== CobiGen Configuration File
+
+The CobiGen configuration file located at: `$home/.cobigen` can be used to set the path to the custom `templates` as well as the `template sets` project.
+You can also specify attributes to control the behaviour of your template sets.
+
+=== Templates
+
+For a custom templates folder simply set the `templates` parameter like this:
+
+```
+templates=C:\\project\\ide\\conf\\templates
+```
+
+For a custom templates jar simply set the `templates` parameter like this:
+
+```
+templates=C:\\project\\ide\\conf\\templates\\my-custom-templates-devon4j-2021.06.001.jar
+```
+
+=== Template Sets
+Since: CobiGen 2021.12.006
+
+For a custom template-sets folder simply set the `template-sets` parameter like this:
+
+```
+template-sets=C:\\project\\ide\\conf\\template-sets
+```
+
+For a custom template-sets jar simply set the `template-sets` parameter like this:
+
+```
+template-sets=C:\\project\\ide\\conf\\template-sets\\my-custom-template-sets-devon4j-2021.06.001.jar
+```
+
+=== Template set attributes
+Since: CobiGen 2021.12.006
+
+You can specify `template-sets` attributes f.e. to restrict the teams to ask for default templates provided by CobiGen. There are `four` custom template-sets attributes:
+
+* `template-sets.groupIds`: Search for template-set artifacts by that configuration key
+configure multiple (comma separated) `groupIds`. By default, (public) CobiGen `groupId` will be used.
+
+* `template-sets.allow-snapshots`: Allow snapshots of template-sets to be offered for template-set development purposes. By default, no snapshots should be queried.
+
+* `template-sets.disable-default-lookup`: Disable by default querying of default public `groupIds` configured in CobiGen.
+
+* `template-sets.hide:` Hide very specific template sets or versions of template sets.
+
+* An example of how such a configuration should look like:
+
+```
+template-sets.groupIds=com.devonfw.cobigen.templates,jaxen,jakarta.xml.bind
+template-sets.allow-snapshots=true
+template-sets.disable-default-lookup=false
+template-sets.hide=com.devonfw.cobigen.templates:crud-angular-client-app:2021.12.007-SNAPSHOT
+```
+
== Context Configuration
The context configuration (`context.xml`) always has the following root structure:
@@ -335,28 +416,6 @@ folder
Let the `cobigen.properties` file contain the line `relocate=../sub2/${cwd}`. Given that, the relative destination path of `Template.java.ftl` will be resolved to `folder/sub2/Template.java`. Compare `xref:templatescan-node[template scan]` configuration for more information about basic path resolution. The `relocate` property specifies a relative path from the location of the `cobigen.properties`. The `${cwd}` placeholder will contain the remaining relative path from the `cobigen.properties` location to the template file. In this basic example it just contains `Template.java.ftl`, but it may even be any relative path including sub-folders of sub1 and its templates.
Given the `relocate` feature, you can even step out of the root path, which in general is the project/maven module the input is located in. This enables template designers to even address, e.g., maven modules located next to the module the input is coming from.
-=== Custom template-set groupIds for lookup
-
-You can specify template-sets so that it can provide custom template-sets and even restrict the teams to ask for default templates provided by CobiGen. There are `four` custom template-sets attributes:
-
-* `template-sets.groupIds`: Search for template-set artifacts by that configuration key
-configure multiple (comma separated) `groupIds`. By default, (public) CobiGen `groupId` will be used.
-
-* `template-sets.allow-snapshots`: Allow snapshots of template-sets to be offered for template-set development purposes. By default, no snapshots should be queried.
-
-* `template-sets.disable-default-lookup`: Disable by default querying of default public `groupIds` configured in CobiGen.
-
-* `template-sets.hide:` Hide very specific template sets or versions of template sets.
-
-* An example of how such a configuration should look like:
-
-```
-template-sets.groupIds=com.devonfw.cobigen.templates,jaxen,jakarta.xml.bind
-template-sets.allow-snapshots=true
-template-sets.disable-default-lookup=false
-template-sets.hide=com.devonfw.cobigen.templates:crud-angular-client-app:2021.12.007-SNAPSHOT
-```
-
== Basic Template Model
In addition to what is served by the different model builders of the different plug-ins, CobiGen provides a minimal model based on context variables as well as CobiGen properties. The following model is independent of the input format and will be served as a template model all the time:
diff --git a/documentation/guide_dev_troubleshooting.asciidoc b/documentation/guide_dev_troubleshooting.asciidoc
index 8c78495323..7f767f52e1 100644
--- a/documentation/guide_dev_troubleshooting.asciidoc
+++ b/documentation/guide_dev_troubleshooting.asciidoc
@@ -31,7 +31,7 @@ ic (https://devon.s2-eu.capgemini.com/nexus/content/groups/public/): Not authori
==== Solution
-Please note the message Not authorized , ReasonPhrase: Unauthorized. -> [Help 2]!
+Please note the message Not authorized , ReasonPhrase: Unauthorized. -> [Help 2]!
1. Please check, that you run the command by using the console.bat or a similar console initialized with the IDE environment variables.
2. Please check your corporate login in the variables-customized.bat to be correct (`DEVON_NEXUS_USER` and `DEVON_NEXUS_PASSWD`). Make sure, that you restart the console.bat you are working in after changing the variables-customized.bat. Same holds for eclipse instances running. Please restart to make the new values accessible.
@@ -48,7 +48,7 @@ To test changes implemented on the `cobigen-core` you have to follow the next pr
4. Open a console and step into `cobigen/cobigen-eclipse`. Run `mvn clean package -Pp2-build-photon,p2-build-stable,p2-build-experimental`.
5. On Eclipse, go to `cobigen/cobigen-eclipse` and double-click 'plugins.xml'. On the bottom, click on 'runtime' tab. On 'classpath', add a new library and choose the jars you have just installed.
6. Refresh on Eclipse, press F5 on the `cobigen-eclipse` inside Eclipse.
-5. If you still see compilation errors: On Eclipse, right-click `cobigen/cobigen-eclipse` -> Maven -> Update projects.
+5. If you still see compilation errors: On Eclipse, right-click `cobigen/cobigen-eclipse` -> Maven -> Update projects.
== Issues with workspace when Oomph automatic updates don't work (especially for Indian colleagues)
Executing `eclipse-cobigen-development.bat` file will open Eclipse with all the projects automatically imported. Oomph creates 'Working Sets' and set 'Top Level Elements' pointing to that working set. For Countries where proxy restricts Oomph to execute, we see no projects imported into project explorer/Navigator. Rather than trying manual import which later can give build issues we should follow below solution.
@@ -65,7 +65,7 @@ Build Issues could be like:
==== Solution
In Eclipse, you can click the small downward arrow in the upper right corner of the Navigator/Project Explorer view and go to 'Top Level Elements' and point them to 'Projects'. This should show all the projects inside Project Explorer View. Also, Each plugin should point to respective branch.
-== Issue when testing Eclipse plugin by Running as Eclipse Application.
+== Issue when testing Eclipse plugin by Running as Eclipse Application.
Error message will be like:
[source]
----
@@ -83,4 +83,15 @@ Delete or rename the runtime-`EclipseApplication` inside workspaces folder. Re-
3) org.eclipse.core.runtime.CoreException: Plug-in com.devonfw.cobigen.eclipse was unable to load class com.devonfw.cobigen.eclipse.workbenchcontrol.handler.XXXXHandler.
```
-
+== Issue when running Eclipse SWT bot tests via github actions with custom test projects
+Error message on github actions will be like:
+[source]
+----
+org.eclipse.swtbot.swt.finder.widgets.TimeoutException: Timeout after: 15000 ms.: The widget (of type 'Button' and with mnemonic 'Finish' and with style 'SWT.PUSH') was not enabled.
+...
+at com.devonfw.cobigen.eclipse.test.common.utils.EclipseUtils.importExistingGeneralProject(EclipseUtils.java:101)
+----
+But on the local system the build and test process works fine.
+
+==== Solution
+If you add an Eclipse test project, make sure that you git force add the .project file too. Otherwise the importExistingGeneralProject method will fail.