diff --git a/de.tubs.variantsync.core/pom.xml b/de.tubs.variantsync.core/pom.xml
index b69f88b..0d8aecc 100644
--- a/de.tubs.variantsync.core/pom.xml
+++ b/de.tubs.variantsync.core/pom.xml
@@ -6,10 +6,11 @@
de.tubs.variantsync
de.tubs.variantsync
0.0.3-SNAPSHOT
+ ../pom.xml
de.tubs.variantsync.core
eclipse-plugin
de.tubs.variantsync.core
-
\ No newline at end of file
+
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/VariantSyncPlugin.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/VariantSyncPlugin.java
index b225291..1408770 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/VariantSyncPlugin.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/VariantSyncPlugin.java
@@ -197,11 +197,12 @@ public void listenForActiveClass() {
}
public static void addNature(IProject project) {
- final VariantSyncProgressMonitor progressMonitor = new VariantSyncProgressMonitor("Adding VariantSync nature to " + project.getName());
+ final VariantSyncProgressMonitor progressMonitor = new VariantSyncProgressMonitor(String.format("Adding VariantSync nature to %s", project.getName()));
try {
final IProjectDescription description = project.getDescription();
final String[] natures = description.getNatureIds();
+ // the natures array is copied to a newNatures array, in which the variant NATURE_ID is added as first element
final String[] newNatures = new String[natures.length + 1];
System.arraycopy(natures, 0, newNatures, 1, natures.length);
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/exceptions/ProjectNotFoundException.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/exceptions/ProjectNotFoundException.java
index b80263f..fd095d9 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/exceptions/ProjectNotFoundException.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/exceptions/ProjectNotFoundException.java
@@ -25,7 +25,7 @@ public ProjectNotFoundException(Type type, String message) {
@Override
public String toString() {
- return "A " + (type == Type.CONFIGURATION ? "configuration project" : "variant") + " does not exist in the workspace. " + getMessage();
+ return String.format("A %s does not exist in the workspace. %s", (type == Type.CONFIGURATION ? "configuration project" : "variant"), getMessage());
}
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/ConfigurationProjectManager.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/ConfigurationProjectManager.java
index 45d0285..2553842 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/ConfigurationProjectManager.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/ConfigurationProjectManager.java
@@ -106,7 +106,7 @@ private List findConfigurationProjects() {
for (final IFeatureProject project : CorePlugin.getFeatureProjects()) {
// System.out.print(" project " + project.getProjectName());
if (project.getComposerID().equals("de.tubs.variantsync.core.composer")) {
- LogOperations.logInfo("Found configuration project with name: " + project.getProjectName());
+ LogOperations.logInfo(String.format("Found configuration project with name: %s", project.getProjectName()));
projects.add(project);
// System.out.println(" is variant composing");
} else {
@@ -126,7 +126,7 @@ private void findVariants(ConfigurationProject configurationProject) {
} else {
try {
final IMarker m = file.createMarker("de.tubs.variantsync.marker.error");
- m.setAttribute(IMarker.MESSAGE, "Project " + projectName + " is missing in the workspace");
+ m.setAttribute(IMarker.MESSAGE, String.format("Project %s is missing in the workspace", projectName));
m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
m.setAttribute(IMarker.LINE_NUMBER, 0);
@@ -176,9 +176,9 @@ public ConfigurationProject getActiveConfigurationProject() {
public void propertyChange(FeatureIDEEvent event) {
switch (event.getEventType()) {
case FEATURE_ADD:
- LogOperations.logInfo("Feature added: " + event);
+ LogOperations.logInfo(String.format("Feature added: %s", event));
case MODEL_DATA_SAVED:
- LogOperations.logInfo("Model Event" + event);
+ LogOperations.logInfo(String.format("Model Event %s", event));
if (event.getSource() instanceof IFeatureModel) {
final IFeatureModel model = (IFeatureModel) event.getSource();
final List featureExpressions = getActiveConfigurationProject().getFeatureContextManager().getContextsAsStrings();
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/ConfigurationProject.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/ConfigurationProject.java
index 2c926ab..bca2fe0 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/ConfigurationProject.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/ConfigurationProject.java
@@ -38,7 +38,7 @@ public class ConfigurationProject extends AManager implements ISaveableManager {
private List projects = new ArrayList<>();
public IFeatureProject getFeatureProject() {
- if(configurationProject != null && configurationProject.getProject().exists()) {
+ if ((configurationProject != null) && configurationProject.getProject().exists()) {
return configurationProject;
}
@@ -85,8 +85,8 @@ public Configuration getConfigurationForVariant(IProject project) {
final IFile configPath = (IFile) EclipseFileSystem.getResource(confPath);
final String configFileName = configPath.getName();
final String configName = configFileName.substring(0, configFileName.lastIndexOf('.'));
- System.out.println("[ConfigurationProject.getConfigurationForVariant] Check name equality Project(" + project.getName() + ") with Config("
- + configName + ")");
+ System.out.println(String.format("[ConfigurationProject.getConfigurationForVariant] Check name equality Project(%s) with Config(%s)",
+ project.getName(), configName));
if (configName.equals(project.getName())) {
final ConfigurationManager configurationManager = ConfigurationManager.getInstance(Paths.get(configPath.getRawLocationURI()));
if (configurationManager != null) {
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/FeatureContext.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/FeatureContext.java
index 7bb7cc9..bc44fa5 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/FeatureContext.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/data/FeatureContext.java
@@ -25,6 +25,7 @@ public FeatureContext(String name, FeatureColor highlighter) {
}
public boolean isComposed() {
+ // if the name contains one of the operators "or", "and" or "not" in its middle, the FeatureContext is supposed to be composed
return name.matches(".*(or|and|not).*");
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/CodeMappingFormat.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/CodeMappingFormat.java
index ea80e0a..ca541c6 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/CodeMappingFormat.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/CodeMappingFormat.java
@@ -25,7 +25,8 @@ public class CodeMappingFormat extends AXMLFormat> {
private static final String MAPPINGS = "Mappings";
private static final String SOURCEFILE = "SourceFile";
private static final String CODEMAPPINGS = "CodeMapping";
- private static final Pattern CONTENT_REGEX = Pattern.compile("\\A\\s*(<[?]xml\\s.*[?]>\\s*)?<" + MAPPINGS + "[\\s>]");
+
+ private static final Pattern CONTENT_REGEX = XMLFormatHelper.createContentRegex(MAPPINGS);
public static final String FILENAME = ".mapping.xml";
@@ -108,5 +109,4 @@ public boolean supportsContent(CharSequence content) {
public String getName() {
return "CodeMapping";
}
-
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/FeatureContextFormat.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/FeatureContextFormat.java
index b5013c0..137caaf 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/FeatureContextFormat.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/FeatureContextFormat.java
@@ -18,7 +18,8 @@ public class FeatureContextFormat extends AXMLFormat> {
private static final String ID = "FeatureContexts";
private static final String FEATURE_CONTEXTS = "contexts";
private static final String FEATURE_CONTEXT = "context";
- private static final Pattern CONTENT_REGEX = Pattern.compile("\\A\\s*(<[?]xml\\s.*[?]>\\s*)?<" + FEATURE_CONTEXTS + "[\\s>]");
+
+ private static final Pattern CONTENT_REGEX = XMLFormatHelper.createContentRegex(FEATURE_CONTEXTS);
public static final String FILENAME = ".contexts.xml";
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/PatchFormat.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/PatchFormat.java
index 9609a27..3dca493 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/PatchFormat.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/PatchFormat.java
@@ -33,7 +33,8 @@ public class PatchFormat extends AXMLFormat>> {
private static final String PATCHES = "Patches";
private static final String PATCH = "Patch";
private static final String DELTA = "Delta";
- private static final Pattern CONTENT_REGEX = Pattern.compile("\\A\\s*(<[?]xml\\s.*[?]>\\s*)?<" + PATCHES + "[\\s>]");
+
+ private static final Pattern CONTENT_REGEX = XMLFormatHelper.createContentRegex(PATCHES);
public static final String FILENAME = ".patches.xml";
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/XMLFormatHelper.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/XMLFormatHelper.java
new file mode 100644
index 0000000..8067b83
--- /dev/null
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/managers/persistence/XMLFormatHelper.java
@@ -0,0 +1,12 @@
+package de.tubs.variantsync.core.managers.persistence;
+
+import java.util.regex.Pattern;
+
+public class XMLFormatHelper {
+
+ // the xml pattern should start with an optional standard xml-starting line (e.g. )
+ // followed by an xml tag starting with the content string
+ public static Pattern createContentRegex(String content) {
+ return Pattern.compile("\\A\\s*(<[?]xml\\s.*[?]>\\s*)?<" + content + "[\\s>]");
+ }
+}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/nature/CreateVariantProject.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/nature/CreateVariantProject.java
index 3f1c619..16ef304 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/nature/CreateVariantProject.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/nature/CreateVariantProject.java
@@ -53,7 +53,7 @@ public Object execute(ExecutionEvent event) throws ExecutionException {
}
private IProject createJavaProjectWithVariantNature(String projectName) {
- final VariantSyncProgressMonitor progressMonitor = new VariantSyncProgressMonitor("Create Project " + projectName);
+ final VariantSyncProgressMonitor progressMonitor = new VariantSyncProgressMonitor(String.format("Create Project %s", projectName));
// create project
final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
final IProject project = root.getProject(projectName);
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/APatch.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/APatch.java
index 71102f4..4ed46bf 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/APatch.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/APatch.java
@@ -64,7 +64,7 @@ public boolean isEmpty() {
@Override
public String toString() {
- return "APatch [deltas=" + deltas + "]";
+ return String.format("APatch [deltas= %s ]", deltas);
}
@Override
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/DeltaFactoryManager.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/DeltaFactoryManager.java
index a491f96..fe12a1d 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/DeltaFactoryManager.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/DeltaFactoryManager.java
@@ -115,8 +115,8 @@ public IDeltaFactory getExtension(String id) throws NoSuchExtensionException {
return extension;
}
}
- StringBuilder errorMsg = new StringBuilder("No extension found for ID ").append(id);
- throw new NoSuchExtensionException(errorMsg.toString());
+ final String errorMsg = String.format("No extension found for ID %s", id);
+ throw new NoSuchExtensionException(errorMsg);
}
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDelta.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDelta.java
index 7e1c752..6af8f01 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDelta.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDelta.java
@@ -21,27 +21,29 @@ public DefaultDelta(IFile res, long timestamp, String factoryId) {
@Override
public String getOriginalAsString() {
- String ret = String.valueOf(original.getPosition());
- ret = ret + ":;:";
+ StringBuilder ret = new StringBuilder(String.valueOf(original.getPosition()));
+ ret.append(":;:");
for (final String line : original.getLines()) {
- ret = ret + line + "#:#";
+ ret.append(line);
+ ret.append("#:#");
}
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
- ret = ret + ":;:";
+ ret = new StringBuilder(ret.substring(0, ret.lastIndexOf("#:#")));
+ ret.append(":;:");
for (final String bLine : original.getBefore()) {
- ret = ret + bLine + "#:#";
+ ret.append(bLine);
+ ret.append("#:#");
}
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
- ret = ret + ":;:";
+ ret = new StringBuilder(ret.substring(0, ret.lastIndexOf("#:#")));
+ ret.append(":;:");
for (final String aLine : original.getAfter()) {
- ret = ret + aLine + "#:#";
+ ret.append(aLine);
+ ret.append("#:#");
}
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
- return ret;
+ return ret.substring(0, ret.lastIndexOf("#:#"));
}
@Override
@@ -58,33 +60,36 @@ public void setOriginalFromString(String original) {
@Override
public String getRevisedAsString() {
- String ret = String.valueOf(revised.getPosition());
- ret = ret + ":;:";
+ StringBuilder ret = new StringBuilder(String.valueOf(revised.getPosition()));
+ ret.append(":;:");
for (final String line : revised.getLines()) {
- ret = ret + line + "#:#";
+ ret.append(line);
+ ret.append("#:#");
}
if (!revised.getLines().isEmpty()) {
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
+ ret = new StringBuilder(ret.substring(0, ret.lastIndexOf("#:#")));
}
- ret = ret + ":;:";
+ ret.append(":;:");
for (final String bLine : revised.getBefore()) {
- ret = ret + bLine + "#:#";
+ ret.append(bLine);
+ ret.append("#:#");
}
if (!revised.getBefore().isEmpty()) {
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
+ ret = new StringBuilder(ret.substring(0, ret.lastIndexOf("#:#")));
}
- ret = ret + ":;:";
+ ret.append(":;:");
for (final String aLine : revised.getAfter()) {
- ret = ret + aLine + "#:#";
+ ret.append(aLine);
+ ret.append("#:#");
}
if (!revised.getAfter().isEmpty()) {
- ret = ret.substring(0, ret.lastIndexOf("#:#"));
+ ret = new StringBuilder(ret.substring(0, ret.lastIndexOf("#:#")));
}
- return ret;
+ return ret.toString();
}
@Override
@@ -101,7 +106,7 @@ public void setRevisedFromString(String revised) {
@Override
public String getRepresentation() {
- return "--- (" + original.getPosition() + ") " + original.getLines() + "\n" + "+++ (" + revised.getPosition() + ") " + revised.getLines();
+ return String.format("--- (%s) %s%n+++ (%s) %s", original.getPosition(), original.getLines(), revised.getPosition(), revised.getLines());
}
@Override
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDeltaFactory.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDeltaFactory.java
index 26bd0a1..d3be9aa 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDeltaFactory.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultDeltaFactory.java
@@ -52,7 +52,7 @@ public static IDeltaFactory> getInstance() {
@Override
public String toString() {
- return "DefaultDeltaFactory [getId()=" + getId() + ", getName()=" + getName() + "]";
+ return String.format("DefaultDeltaFactory [getId()=%s, getName()=%s]", getId(), getName());
}
@Override
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultMarkerHandler.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultMarkerHandler.java
index db46718..1e74da1 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultMarkerHandler.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultMarkerHandler.java
@@ -25,6 +25,8 @@ public List getMarkersForDeltas(IFile file, List variantSyncMarkers = new ArrayList<>();
for (final IDelta> delta : deltas) {
final Chunk revised = delta.getRevised();
+ // For the display of markers, the utilities.MarkerUtils.setMarker-method uses Editor/Document-information provided by IDocument.
+ // IDocument is 0-based (so the first line is line 0 in IDocument), which means that every line number has to be reduced by 1
final IVariantSyncMarker variantSyncMarker = new AMarkerInformation(revised.getPosition() - 1, revised.getLines().size() - 1, true);
variantSyncMarker.setContext(delta.getContext());
variantSyncMarkers.add(variantSyncMarker);
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultPatchFactory.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultPatchFactory.java
index 45b23db..e7543c8 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultPatchFactory.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/patch/base/DefaultPatchFactory.java
@@ -36,7 +36,7 @@ public IFile applyDelta(IFile file, IPatch> patch) {
final IDeltaFactory> factory = DeltaFactoryManager.getFactoryById(delta.getFactoryId());
newFile = factory.applyDelta(newFile, delta);
} catch (final NoSuchExtensionException e) {
- LogOperations.logError("Could not find extension with id: " + delta.getFactoryId(), e);
+ LogOperations.logError(String.format("Could not find extension with id: %s", delta.getFactoryId()), e);
}
}
return newFile;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/ResourceCompareInput.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/ResourceCompareInput.java
index 605d2c0..544c03a 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/ResourceCompareInput.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/ResourceCompareInput.java
@@ -68,7 +68,7 @@ class MyDiffNode extends DiffNode {
@Override
public String toString() {
- return "MyDiffNode [fDirty=" + fDirty + ", fLastId=" + fLastId + ", fLastName=" + fLastName + "]";
+ return String.format("MyDiffNode [fDirty=%s, fLastId=%s, fLastName=%s]", fDirty, fLastId, fLastName);
}
private boolean fDirty = false;
@@ -99,7 +99,7 @@ public String getName() {
fLastName = super.getName();
}
if (fDirty) {
- return '<' + fLastName + '>';
+ return String.format("<%s>", fLastName);
}
return fLastName;
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewer.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewer.java
index 3e4465d..5b96392 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewer.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewer.java
@@ -17,7 +17,7 @@
@Deprecated
public class DeltaCompareViewer extends Wizard {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.synchronization.compare";
+ public static final String ID = String.format("%s.views.synchronization.compare", VariantSyncPlugin.PLUGIN_ID);
private final DeltaCompareViewerPage page;
private final IFile file;
private final IDelta> delta;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewerPage.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewerPage.java
index 8d59169..6ec2ab1 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewerPage.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/syncronization/compare/DeltaCompareViewerPage.java
@@ -75,13 +75,13 @@ public void createControl(Composite parent) {
}
public List getSourceCode() {
- return Arrays.asList(sourceViewer.getDocument().get().split("\n"));
+ return Arrays.asList(sourceViewer.getDocument().get().split(String.format("%n")));
}
private String getStringFromList(List entries) {
String str = "";
for (final String el : entries) {
- str += el + "\n";
+ str += String.format("%s%n", el);
}
return str;
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/MarkerUtils.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/MarkerUtils.java
index 2358fb9..8b1361b 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/MarkerUtils.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/MarkerUtils.java
@@ -139,7 +139,7 @@ private static long addMarker(IResource res, int posStart, int posEnd, FeatureCo
IMarker marker = null;
if (res.exists()) {
marker = res.createMarker(getMarker(featureContext.highlighter));
- marker.setAttribute(IMarker.MESSAGE, "Feature: " + featureContext.name);
+ marker.setAttribute(IMarker.MESSAGE, String.format("Feature: %s", featureContext.name));
marker.setAttribute(IMarker.CHAR_START, posStart);
marker.setAttribute(IMarker.CHAR_END, posEnd);
return marker.getId();
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/PerspectiveFactory.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/PerspectiveFactory.java
index 08df5c3..2cbe9ca 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/PerspectiveFactory.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/PerspectiveFactory.java
@@ -19,7 +19,7 @@
*/
public class PerspectiveFactory implements IPerspectiveFactory {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".perspective";
+ public static final String ID = String.format("%s.perspective", VariantSyncPlugin.PLUGIN_ID);
@Override
public void createInitialLayout(IPageLayout layout) {
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/Tree.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/Tree.java
index 8c0117e..293dcac 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/Tree.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/Tree.java
@@ -99,10 +99,10 @@ public String toString() {
if (root != null) {
int i = 0;
TreeNode currentNode = root;
- String ret = root.toString() + "\n";
+ String ret = String.format("%s%n", root.toString());
while ((currentNode == null) && (i < currentNode.getNumberOfChildren())) {
currentNode = currentNode.getChildAt(i);
- ret = ret + currentNode.toString() + "\n";
+ ret += String.format("%s%n", currentNode.toString());
i++;
}
return ret;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/event/VariantSyncEvent.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/event/VariantSyncEvent.java
index 57832df..36a55be 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/event/VariantSyncEvent.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/utilities/event/VariantSyncEvent.java
@@ -143,7 +143,7 @@ public Object getNewValue() {
@Override
public String toString() {
- return "VariantSyncEvent [source=" + source + ", eventType=" + eventType + ", oldValue=" + oldValue + ", newValue=" + newValue + "]";
+ return String.format("VariantSyncEvent [source=%s, eventType=%s, oldValue=%s, newValue=%s]", source, eventType, oldValue, newValue);
}
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/editor/PartAdapter.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/editor/PartAdapter.java
index 3a3656a..33711ca 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/editor/PartAdapter.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/editor/PartAdapter.java
@@ -117,7 +117,7 @@ public IStatus runInUIThread(IProgressMonitor monitor) {
try {
MarkerUtils.cleanResource(currentFile);
} catch (final CoreException e) {
- LogOperations.logError("Cannot clear all markers from: " + currentFile.getFullPath(), e);
+ LogOperations.logError(String.format("Cannot clear all markers from: %s", currentFile.getFullPath()), e);
}
final ConfigurationProject configurationProject = VariantSyncPlugin.getActiveConfigurationProject();
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextManager.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextManager.java
index 4900fc4..49b0132 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextManager.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextManager.java
@@ -14,7 +14,7 @@
*/
public class FeatureContextManager extends Wizard {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.featurecontexts.manage";
+ public static final String ID = String.format("%s.views.featurecontexts.manage", VariantSyncPlugin.PLUGIN_ID);
private final List expressions;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizard.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizard.java
index 3013b78..ddb628a 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizard.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizard.java
@@ -19,7 +19,7 @@
*/
public class FeatureContextWizard extends Wizard {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.featurecontexts.wizard";
+ public static final String ID = String.format("%s.views.featurecontexts.wizard", VariantSyncPlugin.PLUGIN_ID);
private final Iterable features;
private FeatureContext featureContext = null;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizardPage.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizardPage.java
index f4b4e98..73863bd 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizardPage.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/FeatureContextWizardPage.java
@@ -147,12 +147,19 @@ public void handleEvent(Event event) {
final TableItem[] selectedItem = tabFeatures.getTable().getSelection();
if (selectedItem.length > 0) {
String featureName = selectedItem[0].getText();
+ // if the featureName is of the following structure:
+ // arbitrary amount of chars until the first occurence of 1 or more consecutive spaces followed by an arbitrary amount of chars
+ // so, if the featureName contains 1 or more spaces, it is surrounded by double quotes because the space character is needed to put features
+ // together by operators like "and" or "or"
+ // this might be a relict of previous versions because it is currently not even possible to add new features to the feature model which
+ // contain a space character in the middle
if (featureName.matches(".*?\\s+.*")) {
- featureName = "\"" + featureName + "\"";
+ featureName = String.format("\"%s\"", featureName);
} else {
+ // if the featureName equals one of the operator names, it is also surrounded by double quotes for the reasons mentioned above
for (final String op : Operator.NAMES) {
if (featureName.equalsIgnoreCase(op)) {
- featureName = "\"" + featureName + "\"";
+ featureName = String.format("\"%s\"", featureName);
break;
}
}
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/View.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/View.java
index ad07718..5bc3e2b 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/View.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/featurecontext/View.java
@@ -39,7 +39,7 @@
*/
public class View extends ViewPart implements IEventListener {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.featurecontexts";
+ public static final String ID = String.format("%s.views.featurecontexts", VariantSyncPlugin.PLUGIN_ID);
private List expressions;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/ResourceChangesColumnLabelProvider.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/ResourceChangesColumnLabelProvider.java
index 059e9a7..a495b05 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/ResourceChangesColumnLabelProvider.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/ResourceChangesColumnLabelProvider.java
@@ -73,9 +73,11 @@ public void update(ViewerCell cell) {
if (o instanceof IDelta) {
String projects = "";
for (final IProject project : ((IDelta>) o).getSynchronizedProjects()) {
- projects += project.getName() + ", ";
+ projects += String.format("%s, ", project.getName());
+ }
+ if (projects.lastIndexOf(",") != -1) {
+ projects = projects.substring(0, projects.lastIndexOf(","));
}
- projects = projects.lastIndexOf(",") == -1 ? projects : projects.substring(0, projects.lastIndexOf(","));
cell.setText(projects);
}
break;
@@ -83,9 +85,11 @@ public void update(ViewerCell cell) {
if (o instanceof IDelta) {
String projects = "";
for (final IProject project : targetsCalculator.getTargetsWithConflict(((IDelta>) o))) {
- projects += project.getName() + ", ";
+ projects += String.format("%s, ", project.getName());
+ }
+ if (projects.lastIndexOf(",") != -1) {
+ projects = projects.substring(0, projects.lastIndexOf(","));
}
- projects = projects.lastIndexOf(",") == -1 ? projects : projects.substring(0, projects.lastIndexOf(","));
cell.setText(projects);
}
break;
@@ -93,9 +97,11 @@ public void update(ViewerCell cell) {
if (o instanceof IDelta) {
String projects = "";
for (final IProject project : targetsCalculator.getTargetsWithoutConflict(((IDelta>) o))) {
- projects += project.getName() + ", ";
+ projects += String.format("%s, ", project.getName());
+ }
+ if (projects.lastIndexOf(",") != -1) {
+ projects = projects.substring(0, projects.lastIndexOf(","));
}
- projects = projects.lastIndexOf(",") == -1 ? projects : projects.substring(0, projects.lastIndexOf(","));
cell.setText(projects);
}
break;
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/View.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/View.java
index e54ea43..4c458ae 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/View.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/resourcechanges/View.java
@@ -29,7 +29,7 @@
*/
public class View extends ViewPart implements IEventListener {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.resourcechanges";
+ public static final String ID = String.format("%s.views.resourcechanges", VariantSyncPlugin.PLUGIN_ID);
private TreeViewer tvResourceChanges;
public View() {
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/sourcefocus/View.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/sourcefocus/View.java
index dc3f27e..56127b0 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/sourcefocus/View.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/sourcefocus/View.java
@@ -68,7 +68,7 @@ public void run() {
}
}
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.sourcefocus";
+ public static final String ID = String.format("%s.views.sourcefocus", VariantSyncPlugin.PLUGIN_ID);
private Combo cbFeature;
private TreeViewer tvChanges;
@@ -322,7 +322,11 @@ public void selectionChanged(SelectionChangedEvent event) {
return;
}
lastSelections.add(delta);
- ret += ret.isEmpty() ? delta.getRepresentation() : "\n\n" + delta.getRepresentation();
+ if (ret.isEmpty()) {
+ ret += delta.getRepresentation();
+ } else {
+ ret += String.format("%n%n%s", delta.getRepresentation());
+ }
}
}
lbChange.setDocument(new Document(ret));
diff --git a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/targetfocus/View.java b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/targetfocus/View.java
index 0a1e54e..4ebcfdf 100644
--- a/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/targetfocus/View.java
+++ b/de.tubs.variantsync.core/src/de/tubs/variantsync/core/view/targetfocus/View.java
@@ -54,7 +54,7 @@
*/
public class View extends ViewPart implements SelectionListener, ISelectionChangedListener, IEventListener {
- public static final String ID = VariantSyncPlugin.PLUGIN_ID + ".views.targetfocus";
+ public static final String ID = String.format("%s.views.targetfocus", VariantSyncPlugin.PLUGIN_ID);
private Combo cbVariant;
private TreeViewer tvChanges;
@@ -275,7 +275,11 @@ public void selectionChanged(SelectionChangedEvent event) {
return;
}
lastSelections.add(delta);
- ret += ret.isEmpty() ? delta.getRepresentation() : "\n\n" + delta.getRepresentation();
+ if (ret.isEmpty()) {
+ ret += delta.getRepresentation();
+ } else {
+ ret += String.format("%n%n%s", delta.getRepresentation());
+ }
btnSync.setEnabled(true);
}
}
diff --git a/de.variantsync.core/.classpath b/de.variantsync.core/.classpath
new file mode 100644
index 0000000..fd1d061
--- /dev/null
+++ b/de.variantsync.core/.classpath
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/de.variantsync.core/pom.xml b/de.variantsync.core/pom.xml
new file mode 100644
index 0000000..5cfd5f5
--- /dev/null
+++ b/de.variantsync.core/pom.xml
@@ -0,0 +1,94 @@
+
+
+ 4.0.0
+
+ de.tubs.variantsync
+ de.tubs.variantsync
+ 0.0.3-SNAPSHOT
+
+
+ de.tubs.variantsync
+ de.variantsync.core
+ 0.0.3-SNAPSHOT
+
+ de.variantsync.core
+
+ http://www.example.com
+
+
+ UTF-8
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+ compile
+
+
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ maven-surefire-plugin
+ 2.22.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ maven-site-plugin
+ 3.7.1
+
+
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 11
+
+
+
+
+
diff --git a/de.variantsync.core/src/main/java/de/variantsync/core/ast/AST.java b/de.variantsync.core/src/main/java/de/variantsync/core/ast/AST.java
new file mode 100644
index 0000000..5e947f0
--- /dev/null
+++ b/de.variantsync.core/src/main/java/de/variantsync/core/ast/AST.java
@@ -0,0 +1,181 @@
+package de.variantsync.core.ast;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.UUID;
+
+import de.variantsync.core.interfaces.Grammar;
+
+/**
+ * This class represents the Abstract Syntax Tree data structure.
+ *
+ * @param a generic which needs to extend the Grammar class, defining the type of the AST
+ * @param a generic which defines the value of the actual AST
+ * @author eric
+ */
+public class AST, V> {
+
+ private UUID id;
+ private G type;
+ private V value;
+ private List> subtrees;
+
+ // all attributes which should not be visible to the GSON parser need to be at least transient
+ public static transient final String INDENT_STRING = " ";
+ public static transient final String NEXT_SEPARATOR = "\u2502 ";
+ public static transient final String NEXT_ACT_SEPARATOR = "\u251C\u2500 ";
+ public static transient final String LAST_SEPARATOR = "\u2514\u2500 ";
+
+ public AST(UUID id, G type, V value) {
+ this.id = id;
+ this.type = type;
+ this.value = value;
+ this.subtrees = new ArrayList<>();
+ }
+
+ public AST(G type, V value) {
+ this(UUID.randomUUID(), type, value);
+ }
+
+ /**
+ * Empty AST is forbidden at the moment.
+ */
+ private AST() {
+
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public G getType() {
+ return type;
+ }
+
+ /**
+ * @return the subtrees as an unmodifiable List
+ */
+ public List> getSubtrees() {
+ return Collections.unmodifiableList(subtrees);
+ }
+
+ public int getDepth() {
+ int maxDepth = 1;
+ if (subtrees.isEmpty()) {
+ return maxDepth;
+ }
+
+ for (final AST node : subtrees) {
+ maxDepth = Math.max(node.getDepth(), maxDepth);
+ }
+ return ++maxDepth;
+ }
+
+ /**
+ * This method calls the addChild method for each element of the given list. ASTs which would be rejected by the addChild method are skipped.
+ *
+ * @param toAdd List of AST which should be added as subtrees
+ * @return true if all items where successfully added
+ */
+ public boolean addChildren(List> toAdd) {
+ boolean out = toAdd != null;
+ if (out) {
+ for (final AST elem : toAdd) {
+ if (!addChild(elem)) {
+ out = false;
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * This method adds an element to the AST by checking its validity through the the Grammar G and assuring that the element is not null.
+ *
+ * @param toAdd Single AST which should be added as subtree
+ * @return true if the item was successfully added
+ */
+ public boolean addChild(AST toAdd) {
+ if ((toAdd != null) && type.isValidChild(toAdd.type)) {
+ return subtrees.add(toAdd);
+ }
+ return false;
+ }
+
+ public int size() {
+ int tmpSize = 1;
+ for (final AST act : subtrees) {
+ tmpSize += act.size();
+ }
+ return tmpSize;
+ }
+
+ /**
+ * This method returns only the most significant bits of the UUID, the type, value and subtree size as a String of the actual AST.
+ *
+ * @return UUID, Type, Value, subtree size as String
+ */
+ @Override
+ public String toString() {
+ return String.format("[ Id: %d, Type: %s, Value: %s, Subtree-size: %d ]", id.getMostSignificantBits(), type.toString(), value.toString(),
+ subtrees.size());
+ }
+
+ /**
+ * This recursive method prints for each tree element the Grammar type, the Value and (for the sake of readability) only the most significant bits of the
+ * UUID. It returns the whole AST as human readable tree.
+ *
+ * @return AST as readable String
+ */
+ public String printTree() {
+ final StringBuilder result = new StringBuilder();
+ if (value != null) {
+ final int depth = 0;
+
+ final HashSet levelFinished = new HashSet<>(); // determines if all subtrees of the actual tree on this depth have been drawn or not
+ final boolean isActualElementLastElement = false;
+ printTree(result, this, depth, levelFinished, isActualElementLastElement);
+ }
+ return result.toString();
+ }
+
+ private void printTree(StringBuilder result, AST parent, int depth, HashSet levelFinished, boolean isLast) {
+ // print enough INDENT_STRINGS and choose separator according to whether or not there are subtrees left
+ for (int i = 0; i < depth; i++) {
+ StringBuilder line = new StringBuilder(INDENT_STRING).append(NEXT_SEPARATOR);
+ if (levelFinished.contains(i)) {
+ // new depth indent
+ line = new StringBuilder(INDENT_STRING);
+ }
+ if (i == (depth - 1)) {
+ // make separator for next subtree and printing actual subtree fields
+ line = new StringBuilder(INDENT_STRING).append(NEXT_ACT_SEPARATOR);
+ if (isLast) {
+ // last subtree of parent tree, only print last separator for last subtree fields
+ line = new StringBuilder(INDENT_STRING).append(LAST_SEPARATOR);
+ }
+ }
+ result.append(line.toString());
+ }
+ result.append(String.format("%s %s uuid: %d%n", parent.type, parent.value, parent.getId().getMostSignificantBits()));
+ depth++;
+ for (final AST child : parent.subtrees) {
+ isLast = false;
+ if (parent.subtrees.indexOf(child) == (parent.subtrees.size() - 1)) {
+ // reached last child of parent
+ levelFinished.add(depth - 1);
+ isLast = true;
+ } else if (parent.subtrees.indexOf(child) == 0) {
+ // first child of new sub tree with unfinished depth so it needs NEXT_SEPARATOR later
+ levelFinished.remove(depth - 1);
+ }
+ printTree(result, child, depth, levelFinished, isLast);
+ }
+ }
+}
diff --git a/de.variantsync.core/src/main/java/de/variantsync/core/ast/JsonParserASTWithLineGrammar.java b/de.variantsync.core/src/main/java/de/variantsync/core/ast/JsonParserASTWithLineGrammar.java
new file mode 100644
index 0000000..815b057
--- /dev/null
+++ b/de.variantsync.core/src/main/java/de/variantsync/core/ast/JsonParserASTWithLineGrammar.java
@@ -0,0 +1,85 @@
+package de.variantsync.core.ast;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.google.gson.FieldNamingStrategy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ *
+ * Uses gson to import and export ASTs to and from json. A generic use of grammar is not possible, hence for each grammar a different class has to be created.
+ * In this case the used grammar is LineGrammar.
+ *
+ * @author Jeremia Heinle
+ *
+ */
+public class JsonParserASTWithLineGrammar {
+
+ // json parser uses a custom policy to define the name of the field
+ // inside of the json
+ static FieldNamingStrategy customPolicy = new FieldNamingStrategy() {
+
+ @Override
+ public String translateName(Field f) {
+
+ switch (f.getName()) {
+ case "id":
+ return "uuid";
+ case "type":
+ return "grammar_type";
+ default:
+ return f.getName();
+ }
+ }
+
+ };
+
+ static Gson prettyStringGsonBuilder = new GsonBuilder().setPrettyPrinting().setFieldNamingStrategy(customPolicy).create();
+
+ public static String toJson(AST ast) {
+
+ final Type type = new TypeToken>() {}.getType();
+
+ return prettyStringGsonBuilder.toJson(ast, type);
+ }
+
+ public static AST toAST(String json) {
+
+ final Type type = new TypeToken>() {}.getType();
+
+ return prettyStringGsonBuilder.fromJson(json, type);
+ }
+
+ public static String exportAST(Path path, AST ast) {
+
+ final String content = toJson(ast);
+ try {
+ Files.writeString(path, content);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return content;
+ }
+
+ public static AST importAST(Path path) {
+
+ String json = "";
+ try {
+ json = Files.readString(path);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return toAST(json);
+ }
+
+}
diff --git a/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineBasedParser.java b/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineBasedParser.java
new file mode 100644
index 0000000..cdc9c0a
--- /dev/null
+++ b/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineBasedParser.java
@@ -0,0 +1,68 @@
+package de.variantsync.core.ast;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class LineBasedParser {
+
+ public LineBasedParser() {}
+
+ public AST parseDirectory(Path path) throws IOException {
+ AST result = null;
+ if (Files.exists(path)) {
+ if (Files.isDirectory(path)) {
+ result = new AST<>(LineGrammar.Directory, path.getFileName().toString());
+
+ try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) {
+ // DirectoryStream has no specific order. Thus, the entries are added to an ArrayList which can be sorted.
+ final List list = new ArrayList<>();
+ for (final Path entry : directoryStream) {
+ list.add(entry);
+ }
+ Collections.sort(list);
+ for (final Path entry : list) {
+ result.addChild(parseDirectory(entry));
+ }
+
+ }
+ } else {
+ if (!isBinaryFile(path)) {
+ result = new AST<>(LineGrammar.TextFile, path.getFileName().toString());
+ final List fileStream = Files.readAllLines(path);
+ for (final String line : fileStream) {
+ result.addChild(new AST<>(LineGrammar.Line, line));
+ }
+ } else {
+ result = new AST<>(LineGrammar.BinaryFile, path.getFileName().toString());
+ }
+ }
+ } else {
+ throw new FileNotFoundException("This path does not exist: " + path);
+ }
+ return result;
+ }
+
+ private static boolean isBinaryFile(Path file) throws IOException {
+ if (Files.exists(file)) {
+ final String type = Files.probeContentType(file);
+ if (type == null) {
+ // type couldn't be determined => assume binary
+ return true;
+ } else if (type.startsWith("text")) {
+ // non-binary
+ return false;
+ } else {
+ // type isn't text => assume binary
+ return true;
+ }
+ } else {
+ throw new FileNotFoundException("This file does not exist: " + file);
+ }
+ }
+}
diff --git a/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineGrammar.java b/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineGrammar.java
new file mode 100644
index 0000000..6cef70d
--- /dev/null
+++ b/de.variantsync.core/src/main/java/de/variantsync/core/ast/LineGrammar.java
@@ -0,0 +1,37 @@
+package de.variantsync.core.ast;
+
+import de.variantsync.core.interfaces.Grammar;
+
+public enum LineGrammar implements Grammar {
+
+ Directory, TextFile, BinaryFile, Line;
+
+ @Override
+ public boolean isValidChild(LineGrammar child) {
+ if (this == LineGrammar.Directory) {
+ // Dir can't have line as child
+ return child != LineGrammar.Line;
+ } else if ((this == LineGrammar.TextFile) || (this == LineGrammar.BinaryFile)) {
+ // File can't have dir or file as child
+ return child == LineGrammar.Line;
+ } else {
+ // Line is always leaf node
+ return false;
+ }
+
+ }
+
+ @Override
+ public OptionalType getTypeOf(LineGrammar sym) {
+ switch (sym) {
+ case Directory:
+ return OptionalType.Wrapper;
+ case TextFile:
+ case BinaryFile:
+ case Line:
+ return OptionalType.Optional;
+ default:
+ throw new IllegalArgumentException("[BUG] There is not OptionalType for symbol " + sym + " specified!");
+ }
+ }
+}
diff --git a/de.variantsync.core/src/main/java/de/variantsync/core/interfaces/Grammar.java b/de.variantsync.core/src/main/java/de/variantsync/core/interfaces/Grammar.java
new file mode 100644
index 0000000..7a3b7e7
--- /dev/null
+++ b/de.variantsync.core/src/main/java/de/variantsync/core/interfaces/Grammar.java
@@ -0,0 +1,12 @@
+package de.variantsync.core.interfaces;
+
+public interface Grammar {
+
+ enum OptionalType {
+ Wrapper, Optional, Mandatory
+ }
+
+ public boolean isValidChild(T child);
+
+ public OptionalType getTypeOf(T sym);
+}
diff --git a/de.variantsync.core/src/test/java/de/variantsync/core/ASTTest.java b/de.variantsync.core/src/test/java/de/variantsync/core/ASTTest.java
new file mode 100644
index 0000000..16620a6
--- /dev/null
+++ b/de.variantsync.core/src/test/java/de/variantsync/core/ASTTest.java
@@ -0,0 +1,191 @@
+package de.variantsync.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import de.variantsync.core.ast.AST;
+import de.variantsync.core.ast.LineGrammar;
+
+/**
+ * Here you can find the unit tests for the AST data structure. This also tests the (Line)Grammar indirectly.
+ *
+ * @author eric
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING) // run tests in lexicographic order
+public class ASTTest {
+
+ AST root;
+ AST mainDir;
+ AST testDir;
+ AST mainJava;
+ int lineIndex = 0; // only for printTree() testing
+ final int INITIAL_AST_SIZE = 11;
+ final int INITIAL_TOSTRING_ROWS = 10;
+ final int INITIAL_ROOT_VARIABLE_COUNT = 4;
+
+ @Before
+ public void setup() {
+ root = new AST<>(LineGrammar.Directory, "src");
+ mainDir = new AST<>(LineGrammar.Directory, "main");
+ testDir = new AST<>(LineGrammar.Directory, "test");
+ mainJava = new AST<>(LineGrammar.TextFile, "Main.java");
+ final AST emptyJava = new AST<>(LineGrammar.TextFile, "Empty.java");
+ final AST emptyTestJava = new AST<>(LineGrammar.TextFile, "EmptyTest.java");
+ root.addChild(testDir);
+ testDir.addChild(emptyTestJava);
+ root.addChild(mainDir);
+ mainDir.addChild(mainJava);
+ mainDir.addChild(emptyJava);
+
+ mainJava.addChildren(
+ Arrays.asList(new AST<>(LineGrammar.Line, "public class Main {"), new AST<>(LineGrammar.Line, " public static void main(String[] args)"),
+ new AST<>(LineGrammar.Line, " System.out.println(\"Hello World\");"), new AST<>(LineGrammar.Line, " }"),
+ new AST<>(LineGrammar.Line, "}")));
+ }
+
+ @Test
+ public void toStringOnInitialTest() {
+ final String[] lines = root.toString().split(" ");
+ assertEquals(INITIAL_TOSTRING_ROWS, lines.length);
+ // this loop skips the names of the variable and only checks their value
+ for (int i = 2; i < lines.length; i = i + 2) {
+ if (lines[i].charAt(lines[i].length() - 1) == ',') {
+ lines[i] = lines[i].substring(0, lines[i].length() - 1);
+ }
+ switch (i) {
+ case 2:
+ assertEquals(root.getId().getMostSignificantBits(), Long.parseLong(lines[i]));
+ break;
+ case 4:
+ assertEquals(root.getType().toString(), lines[i]);
+ break;
+ case 6:
+ assertEquals(root.getValue().toString(), lines[i]);
+ break;
+ case 8:
+ assertEquals(root.getSubtrees().size(), Integer.parseInt(lines[i]));
+ break;
+ default:
+ throw new IllegalArgumentException(String.format("toStringOnInitialTest has incorrect lines size: %d", i));
+ }
+ }
+ }
+
+ @Test
+ public void addOnInitialTest() {
+ assertFalse(root.addChild(null));
+ assertEquals(INITIAL_AST_SIZE, root.size());
+
+ // Adding new Directory as subtree of a Directory should work
+ AST newTree = new AST<>(LineGrammar.Directory, "newROOT");
+ int oldSize = root.getSubtrees().size();
+ assertTrue(root.addChild(newTree));
+ assertEquals(oldSize + 1, root.getSubtrees().size());
+
+ // Adding new Line as subtree of a Directory should not work
+ newTree = new AST<>(LineGrammar.Line, "!LineYouAreLookingFor");
+ oldSize = root.getSubtrees().size();
+ assertFalse(root.addChild(newTree));
+ assertEquals(oldSize, root.getSubtrees().size());
+ }
+
+ @Test
+ public void addAllOnInitialTest() {
+ assertFalse(root.addChildren(null));
+ assertEquals(INITIAL_AST_SIZE, root.size());
+
+ // Adding new List of ASTs, only the one satisfying the isValidChild of Grammar or != null will be added,
+ // rest is ignored.
+ List> newTrees = Arrays.asList(new AST<>(LineGrammar.Line, "public class Main {"), null,
+ new AST<>(LineGrammar.BinaryFile, "101010"), new AST<>(LineGrammar.TextFile, "fancyFile.txt"), new AST<>(LineGrammar.Directory, "fancyFolder"));
+ int oldSize = root.getSubtrees().size();
+ assertFalse(root.addChildren(newTrees));
+ assertEquals(oldSize + 3, root.getSubtrees().size());
+
+ // Adding only valid subtrees to the root
+ newTrees = Arrays.asList(new AST<>(LineGrammar.Directory, "public class Main {"), new AST<>(LineGrammar.BinaryFile, "101010"));
+ oldSize = root.getSubtrees().size();
+ assertTrue(root.addChildren(newTrees));
+ assertEquals(oldSize + 2, root.getSubtrees().size());
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void addOnSubtreesList() {
+ root.getSubtrees().add(new AST<>(LineGrammar.Directory, "evilDir"));
+ }
+
+ @Test
+ public void sizeOnInitialTest() {
+ assertEquals(INITIAL_AST_SIZE, root.size());
+ }
+
+ @Test
+ public void sizeOnEmptyASTTest() {
+ final AST badAST = new AST<>(null, null);
+ assertEquals(1, badAST.size());
+ }
+
+ @Test
+ public void getDepthOnInitialTest() {
+ assertEquals(4, root.getDepth());
+ }
+
+ @Test
+ public void getDepthOnEmptyASTTest() {
+ final AST badAST = new AST<>(null, null);
+ assertEquals(1, badAST.getDepth());
+ }
+
+ @Test
+ public void printTreeOnInitialTest() {
+ // assure that printTrees has as many rows as the AST has subtrees
+ final String[] lines = root.printTree().split(String.format("%n"));
+ assertEquals(INITIAL_AST_SIZE, lines.length);
+
+ // assure the number of printed variables of the root value
+ final String[] rootAttributes = lines[0].split(" ");
+ assertEquals(INITIAL_ROOT_VARIABLE_COUNT, rootAttributes.length);
+
+ // check root values
+ checkStringRoot(root, rootAttributes);
+
+ // check subtrees
+ checkStringSubTree(root, lines);
+ }
+
+ private void checkStringRoot(AST node, String[] rootAttributes) {
+ assertEquals(0, lineIndex);
+ // this test also tests the order of the attributes but
+ // in general checking like this is not possible due to the nature of AST.INDENT_STRING
+ // but root line does not contain AST.INDENT_STRING
+ assertEquals(node.getType().toString(), rootAttributes[0]); // Type
+ assertEquals(node.getValue(), rootAttributes[1]); // Value
+ assertEquals("uuid:", rootAttributes[2]);
+ assertEquals(((Long) node.getId().getMostSignificantBits()).toString(), rootAttributes[3]); // UUID
+ }
+
+ private void checkStringSubTree(AST node, String[] lines) {
+ lineIndex++;
+ for (final AST child : node.getSubtrees()) {
+ // in contrast to checkStringRoot this only checks if the attributes are contained in the string
+ // but does not assure their order
+ final String line = lines[lineIndex];
+ assertTrue(line.contains(AST.INDENT_STRING));
+ assertTrue(line.contains(AST.NEXT_SEPARATOR) || line.contains(AST.NEXT_ACT_SEPARATOR) || line.contains(AST.LAST_SEPARATOR));
+ assertTrue(line.contains(child.getType().toString()));
+ assertTrue(line.contains(child.getValue()));
+ assertTrue(line.contains(((Long) child.getId().getMostSignificantBits()).toString()));
+
+ checkStringSubTree(child, lines);
+ }
+ }
+}
diff --git a/de.variantsync.core/src/test/java/de/variantsync/core/JsonParserASTWithLineGrammarTest.java b/de.variantsync.core/src/test/java/de/variantsync/core/JsonParserASTWithLineGrammarTest.java
new file mode 100644
index 0000000..90f5038
--- /dev/null
+++ b/de.variantsync.core/src/test/java/de/variantsync/core/JsonParserASTWithLineGrammarTest.java
@@ -0,0 +1,110 @@
+package de.variantsync.core;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import de.variantsync.core.ast.AST;
+import de.variantsync.core.ast.JsonParserASTWithLineGrammar;
+import de.variantsync.core.ast.LineGrammar;
+
+//TODO. Add compare method to AST and then compare ASTs with this method.
+
+public class JsonParserASTWithLineGrammarTest {
+
+ AST exampleAst;
+ Path examplePath;
+
+ @Before
+ public void InitJsonTest() throws IOException {
+ // init
+ exampleAst = new AST<>(LineGrammar.Directory, "src");
+ final AST mainJava = new AST<>(LineGrammar.TextFile, "Main.java");
+ exampleAst.addChild(mainJava);
+ mainJava.addChildren(
+ Arrays.asList(new AST<>(LineGrammar.Line, "public class Main {"), new AST<>(LineGrammar.Line, " public static void main(String[] args)"),
+ new AST<>(LineGrammar.Line, " System.out.println(\"Hello World\");"), new AST<>(LineGrammar.Line, " }"),
+ new AST<>(LineGrammar.Line, "}")));
+
+ examplePath = Path.of("out.txt");
+
+ }
+
+ @Test
+ public void TestJsonParserAST() {
+
+ // export to json
+ final String json = JsonParserASTWithLineGrammar.toJson(exampleAst);
+
+ // import ast from json
+ final AST importAST = JsonParserASTWithLineGrammar.toAST(json);
+
+ // toJson imported AST
+ final String importedJson = JsonParserASTWithLineGrammar.toJson(importAST);
+
+ // print
+ System.out.println("FileFirst:" + json);
+
+ System.out.println("FileSecond:" + importedJson);
+
+ // compare json
+ assertEquals(json, importedJson);
+
+ }
+
+ @Test
+ public void TestJsonParserASTtoFile() throws IOException {
+
+ // export to json file
+ final String json = JsonParserASTWithLineGrammar.exportAST(examplePath, exampleAst);
+
+ // import ast from file
+ final AST importedAST = JsonParserASTWithLineGrammar.importAST(examplePath);
+
+ // toJson imported AST
+ final String importedJson = JsonParserASTWithLineGrammar.toJson(importedAST);
+
+ // print
+ System.out.println("FileFirst:" + json);
+
+ System.out.println("FileSecond:" + importedJson);
+
+ // compare json
+ assertEquals(json, importedJson);
+
+ // delete created file
+ Files.delete(examplePath);
+ }
+
+ @Test
+ public void TestJsonParserASTtoFileToString() throws IOException {
+
+ // export to json file
+ JsonParserASTWithLineGrammar.exportAST(examplePath, exampleAst);
+
+ // import ast from file
+ final AST importedAST = JsonParserASTWithLineGrammar.importAST(examplePath);
+
+ // get toString
+ final String astString = exampleAst.toString();
+ final String importedString = importedAST.toString();
+
+ // print
+ System.out.println("FileFirst:" + astString);
+
+ System.out.println("FileSecond:" + importedString);
+
+ // compare json
+ assertEquals(astString, importedString);
+
+ // delete created file
+ Files.delete(examplePath);
+ }
+
+}
diff --git a/de.variantsync.core/src/test/java/de/variantsync/core/LineBasedParserTest.java b/de.variantsync.core/src/test/java/de/variantsync/core/LineBasedParserTest.java
new file mode 100644
index 0000000..6a6c682
--- /dev/null
+++ b/de.variantsync.core/src/test/java/de/variantsync/core/LineBasedParserTest.java
@@ -0,0 +1,68 @@
+package de.variantsync.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import de.variantsync.core.ast.AST;
+import de.variantsync.core.ast.LineBasedParser;
+import de.variantsync.core.ast.LineGrammar;
+
+//TODO: Add compare method to AST and then compare ASTs with this method.
+
+public class LineBasedParserTest {
+
+ private AST srcDir;
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Before
+ public void setupAST() {
+ srcDir = new AST<>(LineGrammar.Directory, "src");
+ final AST mainDir = new AST<>(LineGrammar.Directory, "main");
+ srcDir.addChild(mainDir);
+ final AST testDir = new AST<>(LineGrammar.Directory, "test");
+ srcDir.addChild(testDir);
+ final AST binFile = new AST<>(LineGrammar.BinaryFile, "BinaryFile");
+ mainDir.addChild(binFile);
+ final AST mainJava = new AST<>(LineGrammar.TextFile, "Main.java");
+ mainDir.addChild(mainJava);
+ mainJava.addChildren(
+ Arrays.asList(new AST<>(LineGrammar.Line, "public class Main {"), new AST<>(LineGrammar.Line, " public static void main(String[] args)"),
+ new AST<>(LineGrammar.Line, " System.out.println(\"Hello World\");"), new AST<>(LineGrammar.Line, " }"),
+ new AST<>(LineGrammar.Line, "}")));
+ }
+
+ @Test
+ public void parseDirectoryTest() throws IOException {
+ final Path src = tempFolder.newFolder("src").toPath();
+ final Path mainDir = Files.createDirectory(Paths.get(src + File.separator + "main"));
+ final Path testDir = Files.createDirectory(Paths.get(src + File.separator + "test"));
+ final Path mainFile = Files.createFile(Paths.get(mainDir + File.separator + "Main.java"));
+ final String fileContent =
+ String.format("public class Main {%n public static void main(String[] args)%n System.out.println(\"Hello World\");%n }%n}");
+ Files.writeString(mainFile, fileContent);
+
+ final Path binFile = Files.createFile(Paths.get(mainDir + File.separator + "BinaryFile"));
+ final byte[] bytes = "stringForCreationOfByteArray".getBytes();
+ Files.write(binFile, bytes);
+
+ final LineBasedParser parser = new LineBasedParser();
+ final AST parsedAST = parser.parseDirectory(src);
+
+ // Testing only the equality of the toString() methods at the moment
+ // waiting for equals() method for AST for comparison of the real AST-Objects
+ // TODO: FIX THIS
+ // assertEquals(parsedAST.toString(), srcDir.toString());
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 0893581..7725576 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,6 @@
+
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
de.tubs.variantsync
de.tubs.variantsync
@@ -9,9 +10,10 @@
2.1.0
2.1.0
+ 3.8.1
UTF-8
- https://download.eclipse.org/releases/2020-09/
-
+ https://download.eclipse.org/releases/2019-12/
+
@@ -19,27 +21,38 @@
de.tubs.variantsync.core
de.tubs.variantsync.core.feature
de.tubs.variantsync.update
-
+ de.variantsync.core
- de.tubs.variantsync.core-test
+ de.tubs.variantsync.core-test
-
+
eclipse-release
${eclipse-repo.url}
p2
-
+
featureide
http://featureide.cs.ovgu.de/update/v3/
p2
-
+
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-version}
+
+
+ 11
+
+
+
org.eclipse.tycho
tycho-maven-plugin
@@ -52,16 +65,16 @@
${tycho-version}
true
-
- SYSTEM
+
+ SYSTEM
-
+
org.eclipse.tycho
target-platform-configuration
${tycho-version}
-
+
consider
@@ -103,8 +116,8 @@
-
+