Commit 34cb07ff authored by Romain Bioteau's avatar Romain Bioteau Committed by GitHub
Browse files

fix(emfModel) remove dandling references at import (#291)

fixes BS-16206
parent b3b23b90
/**
* Copyright (C) 2009-2017 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2.0 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.studio.common.emf.tools;
import java.util.Collection;
import java.util.Map;
import org.bonitasoft.studio.common.Activator;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.CrossReferencer;
public class RemoveDanglingReferences {
private final EObject root;
public RemoveDanglingReferences(final EObject root) {
this.root = root;
}
public void execute() {
removeDanglingReferences(root);
}
/**
* Remove all dangling references of all objects that are contained by the root element.
*
* @param element
* the root element
*/
public void removeDanglingReferences(final EObject element) {
if (element.eResource() != null && element.eResource().getResourceSet() != null) {
removeDanglingReferences(new DanglingReferencesDetector(element.eResource()));
}
}
/**
* Removes all dangling references from all the elements in the given resourceSet.
*
* @param resourceSet
* The resourceSet which is to be cleaned of dangling references.
*/
public void removeDanglingReferences(final ResourceSet resourceSet) {
removeDanglingReferences(new DanglingReferencesDetector(resourceSet));
}
/**
* Removes the dangling references of the given cross referencer.
*
* @param referencer
* the referencer
*/
private void removeDanglingReferences(CrossReferencer referencer) {
for (Map.Entry<EObject, Collection<Setting>> entry : referencer.entrySet()) {
for (EStructuralFeature.Setting value : entry.getValue()) {
try {
EcoreUtil.remove(value, entry.getKey());
BonitaStudioLog.warning(
String.format("Dandling reference removed from process at import: %s", value.getEObject()),
Activator.PLUGIN_ID);
} catch (final UnsupportedOperationException e) {
// we know some time the setting is unsettable, just ignore
// that cases
} catch (final NullPointerException e) {
// we don't want to clean unresolved proxies in the model,
// so let's ignore Exceptions coming from that.
}
}
}
}
/**
* Specific {@link CrossReferencer} to detect dangling references.
*/
private static class DanglingReferencesDetector extends EcoreUtil.CrossReferencer {
/**
* Generated serial version UID.
*/
private static final long serialVersionUID = 616050158241084372L;
/**
* Creates an instance for the given resource.
*
* @param resource
* the resource to cross reference.
*/
public DanglingReferencesDetector(Resource resource) {
super(resource);
crossReference();
done();
}
/**
* Creates an instance for the given resource set.
*
* @param resourceSet
* the resource set to cross reference.
*/
public DanglingReferencesDetector(ResourceSet resourceSet) {
super(resourceSet);
crossReference();
done();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.util.EcoreUtil.CrossReferencer#crossReference(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EReference, org.eclipse.emf.ecore.EObject)
*/
@Override
protected boolean crossReference(final EObject eObject, final EReference eReference,
final EObject crossReferencedEObject) {
// A reference is dangling if the referenced object is not attached to a resource
return crossReferencedEObject.eResource() == null;
}
}
}
......@@ -43,6 +43,7 @@ import org.bonitasoft.studio.common.ProjectUtil;
import org.bonitasoft.studio.common.editingdomain.BonitaEditingDomainUtil;
import org.bonitasoft.studio.common.emf.tools.EMFResourceUtil;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.emf.tools.RemoveDanglingReferences;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.platform.tools.CopyInputStream;
import org.bonitasoft.studio.common.repository.model.IRepositoryFileStore;
......@@ -54,6 +55,7 @@ import org.bonitasoft.studio.model.process.Element;
import org.bonitasoft.studio.model.process.MainProcess;
import org.bonitasoft.studio.model.process.Pool;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.model.process.diagram.part.ProcessDiagramEditorUtil;
import org.bonitasoft.studio.model.process.provider.ProcessItemProviderAdapterFactory;
import org.bonitasoft.studio.pics.Pics;
import org.bonitasoft.studio.pics.PicsConstants;
......@@ -285,9 +287,9 @@ public class DiagramRepositoryStore extends
FileUtil.copy(is, fos);
final Map<String, String[]> featureValueFromEObjectType = new EMFResourceUtil(
tmpFile).getFeatureValueFromEObjectType(
"process:MainProcess",
ProcessPackage.Literals.ELEMENT__NAME,
ProcessPackage.Literals.ABSTRACT_PROCESS__VERSION);
"process:MainProcess",
ProcessPackage.Literals.ELEMENT__NAME,
ProcessPackage.Literals.ABSTRACT_PROCESS__VERSION);
if (featureValueFromEObjectType.size() == 1) {
final String[] next = featureValueFromEObjectType.values()
.iterator().next();
......@@ -414,6 +416,8 @@ public class DiagramRepositoryStore extends
.isConfigurationIdValid(diagram)) {
return openError(fileName);
}
//Sanitize model
new RemoveDanglingReferences(diagram).execute();
updateConfigurationId(diagramResource, diagram);
return new FileInputStream(new File(diagramResource.getURI()
.toFileString()));
......@@ -422,7 +426,7 @@ public class DiagramRepositoryStore extends
copyIs.close();
}
if (diagramResource != null) {
diagramResource.delete(Collections.EMPTY_MAP);
diagramResource.delete(Collections.emptyMap());
}
}
}
......@@ -444,7 +448,7 @@ public class DiagramRepositoryStore extends
"Unknown"));
}
try {
diagramResource.save(Collections.EMPTY_MAP);
diagramResource.save(ProcessDiagramEditorUtil.getSaveOptions());
} catch (final IOException e) {
BonitaStudioLog.error(e);
}
......@@ -487,9 +491,9 @@ public class DiagramRepositoryStore extends
private String getModelVersion(final Resource resource) {
final Map<String, String[]> featureValueFromEObjectType = new EMFResourceUtil(
new File(resource.getURI().toFileString()))
.getFeatureValueFromEObjectType(
"process:MainProcess",
ProcessPackage.Literals.MAIN_PROCESS__BONITA_MODEL_VERSION);
.getFeatureValueFromEObjectType(
"process:MainProcess",
ProcessPackage.Literals.MAIN_PROCESS__BONITA_MODEL_VERSION);
String modelVersion = null;
for (final Entry<String, String[]> e : featureValueFromEObjectType
.entrySet()) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment