blob: d24b9233fd28b3cea1cf0b9edaf449dd9649b1d5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2010 BMW Car IT, Technische Universitaet Muenchen, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* BMW Car IT - Initial API and implementation
* Technische Universitaet Muenchen - Major refactoring and extension
*******************************************************************************/
package org.eclipse.emf.edapt.history.reconstruction;
import java.util.Map.Entry;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edapt.internal.common.MetamodelExtent;
import org.eclipse.emf.edapt.spi.history.Add;
import org.eclipse.emf.edapt.spi.history.Change;
import org.eclipse.emf.edapt.spi.history.CompositeChange;
import org.eclipse.emf.edapt.spi.history.Create;
import org.eclipse.emf.edapt.spi.history.Delete;
import org.eclipse.emf.edapt.spi.history.Move;
import org.eclipse.emf.edapt.spi.history.Remove;
import org.eclipse.emf.edapt.spi.history.Set;
/**
* Reconstructor for reconstructing a certain version of the metamodel by
* visiting the history in backward direction.
*
* @author herrmama
* @author $Author$
* @version $Rev$
* @levd.rating RED Rev:
*/
public class EcoreBackwardReconstructor extends BackwardReconstructorBase {
/** Target folder of the reproduced metamodel. */
private final URI folder;
/** Switch to perform reconstruction depending on change. */
private EcoreReconstructorSwitch ecoreSwitch;
/** Constructor. */
public EcoreBackwardReconstructor(URI folder) {
this.folder = folder;
}
/** {@inheritDoc} */
@Override
public void init(Mapping mapping, MetamodelExtent extent) {
ecoreSwitch = new EcoreReconstructorSwitch();
for (final EPackage p : extent.getRootPackages()) {
final String filename = mapping.getSource(p).eResource().getURI()
.lastSegment();
final URI uri = folder.appendSegment(filename);
Resource resource = resourceSet.getResource(uri, false);
if (resource == null) {
resource = resourceSet.createResource(uri);
}
resource.getContents().add(p);
}
super.init(mapping, extent);
}
/** {@inheritDoc} */
@Override
public void startChange(Change change) {
super.startChange(change);
if (change instanceof Create) {
ecoreSwitch.doSwitch(change);
}
}
/** {@inheritDoc} */
@Override
public void endChange(Change change) {
super.endChange(change);
if (!(change instanceof Create)) {
ecoreSwitch.doSwitch(change);
}
}
/** Switch to perform reconstruction depending on change. */
private class EcoreReconstructorSwitch extends
EcoreReconstructorSwitchBase<Object> {
/** {@inheritDoc} */
@Override
public Object caseSet(Set operation) {
final EObject element = mapping.getTarget(operation.getElement());
final EStructuralFeature feature = operation.getFeature();
final Object value = mapping.resolveTarget(operation.getOldValue());
set(element, feature, value);
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseCreate(Create operation) {
final EObject element = mapping.getTarget(operation.getElement());
Resource toRemove = null;
if (operation.getTarget() == null) {
if (element.eResource().getContents().size() == 1) {
toRemove = element.eResource();
}
}
delete(element);
if (toRemove != null) {
resourceSet.getResources().remove(toRemove);
}
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseDelete(Delete operation) {
final EObject target = mapping.getTarget(operation.getTarget());
final EReference reference = operation.getReference();
final org.eclipse.emf.ecore.util.EcoreUtil.Copier copier = new org.eclipse.emf.ecore.util.EcoreUtil.Copier();
final EObject reproducedElement = copier.copy(operation.getElement());
copier.copyReferences();
for (final Entry<EObject, EObject> entry : copier.entrySet()) {
mapping.map(entry.getKey(), entry.getValue());
extent.addToExtent(entry.getValue());
}
add(target, reference, reproducedElement);
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseMove(Move operation) {
final EObject element = mapping.getTarget(operation.getElement());
final EObject source = mapping.getTarget(operation.getSource());
final EReference reference = operation.getReference();
move(element, source, reference);
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseAdd(Add operation) {
final EObject element = mapping.getTarget(operation.getElement());
final Object value = mapping.resolveTarget(operation.getValue());
final EStructuralFeature feature = operation.getFeature();
remove(element, feature, value);
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseRemove(Remove operation) {
final EObject element = mapping.getTarget(operation.getElement());
final Object value = mapping.resolveTarget(operation.getValue());
final EStructuralFeature feature = operation.getFeature();
add(element, feature, value);
return operation;
}
/** {@inheritDoc} */
@Override
public Object caseCompositeChange(CompositeChange operation) {
return operation;
}
}
}