blob: f4861ec98c2fa1a9168a1261867e6f4d0d631b1f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jonas - initial API and implementation
******************************************************************************/
package org.eclipse.e4.internal.tools.wizards.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.fragment.MModelFragment;
import org.eclipse.e4.ui.model.fragment.MModelFragments;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* Helper to merge two Fragments Files into one.
*
* @author Jonas
*
*/
public class FragmentMergeHelper {
/**
* Merges a source {@link MModelFragments} into a target. Adds missing
* imports. Replaces existing imports, which get added as elements by those.
*
* @param sourceFragments
* an {@link MModelFragments}
* @param targetFragments
* an {@link MModelFragments}
*/
public static void merge(MModelFragments sourceFragments, MModelFragments targetFragments) {
targetFragments.getFragments().addAll(sourceFragments.getFragments());
final List<MApplicationElement> sourceImports = new ArrayList<>();
consolidateImports(targetFragments);
sourceImports.addAll(sourceFragments.getImports());
for (final MApplicationElement sourceImport : sourceImports) {
boolean doImport = true;
for (final MApplicationElement targetImport : targetFragments.getImports()) {
if (haveSameID(sourceImport, targetImport)) {
doImport = false;
changeReferenceToExistingElement(targetFragments.getFragments(), targetImport, sourceImport);
break;
}
}
if (doImport) {
targetFragments.getImports().add(sourceImport);
}
}
}
/**
* Replaces imports by elements which got imported.
*
* @param targetFragments
*/
private static void consolidateImports(MModelFragments targetFragments) {
final List<MModelFragment> fragments = targetFragments.getFragments();
for (final MModelFragment fragment : fragments) {
final List<MApplicationElement> elements = fragment.getElements();
for (final MApplicationElement element : elements) {
final MApplicationElement previousImport = getPreviousImport(element, targetFragments);
if (previousImport != null) {
changeReferenceToExistingElement(targetFragments.getFragments(), element, previousImport);
}
}
}
}
/**
* Finds imports which have the same ID as an element which got imported.
*
* @param element
* The {@link MApplicationElement} to search for in the imports
* @param targetFragments
* The {@link MModelFragments} to search in
* @return The existing import or null if there is none.
*/
private static MApplicationElement getPreviousImport(MApplicationElement element, MModelFragments targetFragments) {
final List<MApplicationElement> imports = targetFragments.getImports();
for (final MApplicationElement imported : imports) {
if (haveSameID(element, imported)) {
return imported;
}
}
return null;
}
/**
* @param fragments
* The {@link MModelFragments} to search for existing references
* @param target
* The element to link to
* @param source
* The existing element to unlink
*/
private static void changeReferenceToExistingElement(List<MModelFragment> fragments, MApplicationElement target,
MApplicationElement source) {
final Collection<Setting> settings = EcoreUtil.UsageCrossReferencer.find((EObject) source, fragments);
for (final Setting setting : settings) {
if (setting.getEStructuralFeature().isMany()) {
@SuppressWarnings("unchecked")
final List<MApplicationElement> list = (List<MApplicationElement>) setting.getEObject()
.eGet(setting.getEStructuralFeature());
list.remove(source);
list.add(target);
} else {
setting.getEObject().eSet(setting.getEStructuralFeature(), target);
}
}
EcoreUtil.delete((EObject) source);
}
/**
*
* @param firstElement
* an {@link MApplicationElement}
* @param secondElement
* an {@link MApplicationElement}
* @return whether both elements have a non-empty and non-null ID and the
* IDs are equal
*/
public static boolean haveSameID(MApplicationElement firstElement, MApplicationElement secondElement) {
if (firstElement.getElementId() == null || secondElement.getElementId() == null) {
return false;
}
if (firstElement.getElementId().isEmpty() || secondElement.getElementId().isEmpty()) {
return false;
}
if (firstElement.getElementId().equals(secondElement.getElementId())) {
return true;
}
return false;
}
}