Skip to content
Snippets Groups Projects
Commit b15a0a73 authored by Alexander Diewald's avatar Alexander Diewald
Browse files

Merge branch '3459-checkIDs-avoid-duplicate-save' into 'master'

3459 check i ds avoid duplicate save

See merge request !8
parents f04c3070 489e85b6
No related branches found
No related tags found
1 merge request!83459 check i ds avoid duplicate save
AutoUndoCommandStack.java 6aa645a9ed6e6547539c376fda97284928c4f9d4 GREEN AutoUndoCommandStack.java 6aa645a9ed6e6547539c376fda97284928c4f9d4 GREEN
EMFTransactionalCommand.java ba4b5bead9768b6ce6c955b9238cd96cb722533c GREEN EMFTransactionalCommand.java ba4b5bead9768b6ce6c955b9238cd96cb722533c GREEN
EclipseResourceStorageService.java 1b9722e31a5ec33e4c3f7bb171fc2ce587729bf8 GREEN EclipseResourceStorageService.java 1b9722e31a5ec33e4c3f7bb171fc2ce587729bf8 GREEN
ModelContext.java 85ede185d4b232221a96d0bf37a4c676b105dc00 GREEN ModelContext.java 220944231c0e036f29d4911d2658c33b2427b09f GREEN
NonDirtyingEMFTransactionalCommand.java ec5f282603891096b09f2628155dd27e3a21c588 GREEN NonDirtyingEMFTransactionalCommand.java ec5f282603891096b09f2628155dd27e3a21c588 GREEN
...@@ -34,6 +34,7 @@ import java.util.Iterator; ...@@ -34,6 +34,7 @@ import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
...@@ -151,7 +152,14 @@ class ModelContext implements ITopLevelElement, CommandStackListener { ...@@ -151,7 +152,14 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
} }
}); });
checkIDs(); if(checkIDs()) {
try {
doSave(new NullProgressMonitor());
} catch(IOException | CoreException e) {
error(ToolingKernelActivator.getDefault(),
"Error saving model file when fixing missing/duplicate IDs.", e);
}
}
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
...@@ -182,29 +190,35 @@ class ModelContext implements ITopLevelElement, CommandStackListener { ...@@ -182,29 +190,35 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
} }
/** /**
* Checks whether all IDs are present and unique and updates {@link #maxId}. In case duplicate * Checks whether all IDs are present and unique and updates {@link #maxId}.
* IDs have been detected (which could only be caused by a bug in AF3), these are removed and an * <ul>
* error is logged. * <li>Duplicate IDs indicate a programming error. They are removed and an error is logged</li>
* <li>Missing IDs are silently added.</li>
* </ul>
*
* @return {@code true} iff the model was modified because of missing/duplicated IDs (and hence
* must
* be saved).
*/ */
private void checkIDs() { private boolean checkIDs() {
Set<Integer> ids = new HashSet<Integer>(); Set<Integer> ids = new HashSet<Integer>();
boolean hadMissing = false; // Store String representation of element with duplicated IDs before fixing it
boolean hadDuplicates = false; Map<String, Integer> objWithIdProblem = new HashMap<String, Integer>();
for(Iterator<EObject> i = getRootModelElement().eAllContents(); i.hasNext();) { for(Iterator<EObject> i = getRootModelElement().eAllContents(); i.hasNext();) {
EObject eo = i.next(); EObject eo = i.next();
if(eo instanceof IIdLabeled) { if(eo instanceof IIdLabeled) {
final IIdLabeled element = (IIdLabeled)eo; final IIdLabeled element = (IIdLabeled)eo;
int id = element.getId(); int id = element.getId();
if(id <= 0) { if(id <= 0) {
hadMissing = true; objWithIdProblem.put(element.toString(), null);
} else { } else {
// Reset duplicate IDs. They will be regenerated together with missing IDs. This // Reset duplicate IDs. They will be regenerated together with missing IDs. This
// is a safe operation since at this stage, references are still based on Java // is a safe operation since at this stage, references are still based on Java
// references. Only in the persisted resource, references will be based on IDs, // references. Only in the persisted resource, references will be based on IDs,
// which is why special care must be taken to ensure uniqueness. // which is why special care must be taken to ensure uniqueness.
if(ids.contains(id)) { if(ids.contains(id)) {
hadDuplicates = true; objWithIdProblem.put(element.toString(), element.getId());
runAsNonDirtyingCommand(() -> { runAsNonDirtyingCommand(() -> {
element.setId(0); element.setId(0);
}); });
...@@ -218,24 +232,31 @@ class ModelContext implements ITopLevelElement, CommandStackListener { ...@@ -218,24 +232,31 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
maxId = max(0, maxId); maxId = max(0, maxId);
if(hadMissing || hadDuplicates) { if(!objWithIdProblem.isEmpty()) {
runAsNonDirtyingCommand(() -> { runAsNonDirtyingCommand(() -> {
maxId = generateMissingIDs(getRootModelElement(), maxId); maxId = generateMissingIDs(getRootModelElement(), maxId);
}); });
try {
doSave(new NullProgressMonitor());
} catch(IOException | CoreException e) {
error(ToolingKernelActivator.getDefault(),
"Error saving model file when fixing missing/duplicate IDs.", e);
}
}
if(hadDuplicates) { String msg = "The following missing/duplicate IDs have been fixed in \"";
String msg = "Duplicate IDs have been removed from \""; msg += resource.getURI().lastSegment() + "\".\n";
msg += resource.getURI().lastSegment() + "\". "; msg += "Please report this incident since it indicates a programming error ";
msg += "Please report this incident since it could result in corrupted model files."; msg += "that could result in corrupted model files.\n";
for(Entry<String, Integer> entry : objWithIdProblem.entrySet()) {
Integer id = entry.getValue();
if(id == null) {
msg += " Missing ID added to ";
} else {
msg += " Duplicate ID " + id + " disambiguated for ";
}
String name = entry.getKey();
msg += "element \"" + name + "\"\n";
}
error(ToolingKernelActivator.getDefault(), msg); error(ToolingKernelActivator.getDefault(), msg);
return true;
} }
return false;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment