blob: 48a2f4fb71934463bb3a0bc304345c16c58d53b6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Andras Schmidt, Andras Balogh, Istvan Rath and Daniel Varro
* 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:
* Andras Schmidt, Andras Balogh, Istvan Rath - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.copier;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.viatra2.core.IEntity;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IModelManager;
import org.eclipse.viatra2.core.IModelSpace;
import org.eclipse.viatra2.core.IRelation;
import org.eclipse.viatra2.errors.VPMCoreException;
/**
*
* @author Andras Schmidt; modified by Istvan Rath
*
*/
public class ModelCopy {
Map<IModelElement, IModelElement> remap;
Set<IModelElement> toCopy;
TreeMap<IModelElement, IModelElement> src2tg = new TreeMap<IModelElement, IModelElement>();
IModelSpace targetModel;
IModelSpace sourceModel;
IModelManager tModelManager;
/**
* Copy elements from one model into another model. Elements to be copied
* are given as a set of elements. The new place of the elements to be
* copied is given by a map. For example a branch copy has the following
* parameters: toCopy: all elements below the root remap: parent of root's
* fully qualified name -> new parent of root's fully qualified name
*
* @param sourceModel
* the model to copy elements from
* @param targetModel
* the model to copy elements to
* @param toCopy
* elements to be copied
* @param remap
* fqn mapping from old model's fqn to new model's fqn
* @throws VPMCoreException
* @throws ModelCopyException
*/
public static void copyModel(IModelSpace sourceModel,
IModelSpace targetModel, Set<IModelElement> toCopy,
Map<IModelElement, IModelElement> remap) throws VPMCoreException,
ModelCopyException {
ModelCopy mc = new ModelCopy();
mc._copyModel(sourceModel, targetModel, toCopy, remap);
}
/**
* Copy a part of a model into another model.
*
* @param sourceModel
* the source model
* @param targetModel
* the target model
* @param root
* the root of the model part to be copied
* @param destinationContainer
* the container of the copied model in the destination model
* @param doOutEdges
* true: copy edges going out of the copied part of model
* @return returns the root modelement of the copied model part
* @throws VPMCoreException
* @throws ModelCopyException
*/
public static IModelElement copyModel(IModelSpace sourceModel,
IModelSpace targetModel, IModelElement root,
IModelElement destinationContainer, boolean doOutEdges)
throws VPMCoreException, ModelCopyException {
TreeSet<IModelElement> elementsToCopy = new TreeSet<IModelElement>();
addModelElementAndChildren(root, root, elementsToCopy, doOutEdges);
TreeMap<IModelElement, IModelElement> remap = new TreeMap<IModelElement, IModelElement>();
remap.put(root.getNamespace(), destinationContainer);
ModelCopy mc = new ModelCopy();
mc._copyModel(sourceModel, targetModel, elementsToCopy, remap);
IModelElement ret = mc.src2tg.get(root);
return ret;
}
public static IModelElement copyModels(Set<IModelElement> elementsToCopy,
IModelSpace sourceModel, IModelSpace targetModel,
IModelElement root, IModelElement destinationContainer,
boolean doOutEdges) throws VPMCoreException, ModelCopyException {
TreeSet<IModelElement> _elementsToCopy = new TreeSet<IModelElement>();
TreeMap<IModelElement, IModelElement> remap = new TreeMap<IModelElement, IModelElement>();
for (IModelElement e : elementsToCopy) {
addModelElementAndChildren(e, e, _elementsToCopy, doOutEdges);
remap.put(e.getNamespace(), destinationContainer); // FIXME this may
// be dangerous!
}
remap.put(root.getNamespace(), destinationContainer);
ModelCopy mc = new ModelCopy();
mc._copyModel(sourceModel, targetModel, _elementsToCopy, remap);
IModelElement ret = mc.src2tg.get(root);
return ret;
}
private static void addModelElementAndChildren(IModelElement root,
IModelElement me, TreeSet<IModelElement> elementsToCopy,
boolean copyOutEdges) {
// if(me.equals(root)||me.isBelowNamespace(root))
elementsToCopy.add(me);
for (IModelElement _me : me.getElementsInNamespace()) {
if (!copyOutEdges) {
if (_me instanceof IRelation) {
IRelation rel = (IRelation) _me;
IModelElement to = rel.getTo();
if (!(to.equals(root) || to.isBelowNamespace(root))) {
continue;
}
}
}
addModelElementAndChildren(root, _me, elementsToCopy, copyOutEdges);
}
if (copyOutEdges) {
// TODO do we need to copy the incoming edges as well?
for (IModelElement _me : me.getRelationsTo()) {
elementsToCopy.add(_me);
}
}
}
private void _copyModel(IModelSpace sourceModel, IModelSpace targetModel,
Set<IModelElement> toCopy, Map<IModelElement, IModelElement> remap)
throws VPMCoreException, ModelCopyException {
this.remap = remap;
this.toCopy = toCopy;
this.targetModel = targetModel;
this.sourceModel = sourceModel;
tModelManager = targetModel.getModelManager();
Set<IModelElement> roots = findRoots(toCopy);
for (IModelElement root : roots) {
createBranch(root);
}
setTargets();
setTypes();
}
private void setTargets() throws VPMCoreException, ModelCopyException {
for (IModelElement me : toCopy) {
if (!(me instanceof IRelation)) {
continue;
}
IRelation rel = (IRelation) me;
IModelElement tg = targetOf(me);
if (tg == null) {
continue;
}
if (!(tg instanceof IRelation)) {
addError(
"copy model internal error: target of a relation is not relaiton",
me);
continue;
}
IRelation tgRel = (IRelation) tg;
IModelElement to = rel.getTo();
IModelElement tgTo = targetOf(to);
if (tgTo == null) {
addError("target of relation has no map in target model", rel,
to);
continue;
}
tModelManager.setRelationTo(tgRel, tgTo);
IRelation inverse = rel.getInverse();
if (inverse != null) {
IModelElement tgInverse = targetOf(inverse);
if (tgInverse != null && tgInverse instanceof IRelation) {
IRelation rTgInverse = (IRelation) tgInverse;
tModelManager.setRelationInverse(tgRel, rTgInverse);
} else {
addError("Inverse of relation is not mapped to a relation",
rel, inverse);
}
}
}
}
private void setTypes() throws VPMCoreException, ModelCopyException {
for (IModelElement me : toCopy) {
IModelElement tg = targetOf(me);
if (tg == null) {
continue;
}
Collection<IModelElement> types = me.getTypes();
for (IModelElement type : types) {
IModelElement tgType = targetOf(type);
if (tgType != null) {
tModelManager.newInstanceOf(tgType, tg);
} else {
addError(
"Element in target model does not exist, when creating type",
tg, type);
}
}
types = me.getSupertypes();
for (IModelElement type : types) {
IModelElement tgType = targetOf(type);
if (tgType != null) {
tModelManager.newSupertypeOf(tgType, tg);
} else {
addError(
"Element in target model does not exist, when creating supertype",
tg, type);
}
}
}
}
private void createBranch(IModelElement me) throws VPMCoreException,
ModelCopyException {
if (!toCopy.contains(me))
return;
IModelElement newMe = null;
if (me instanceof IEntity) {
IEntity ent = (IEntity) me;
IEntity par = ent.getParent();
IModelElement newPar = targetOf(par);
if (newPar != null && newPar instanceof IEntity) {
IEntity eNewPar = (IEntity) newPar;
newMe = tModelManager.newEntity(ent.getName(), ent.getValue(),
eNewPar);
} else {
addError(
"Parent of copy root entity is not found in target model",
ent);
}
} else {
IRelation rel = (IRelation) me;
IModelElement par = rel.getFrom();
IModelElement newPar = targetOf(par);
if (newPar != null) {
newMe = tModelManager.newRelation(rel.getName(), newPar,
newPar, rel.getMultiplicity(), rel.getIsAggregation(),
null);
} else {
addError(
"Source of copy root relation is not found in target model",
rel);
}
}
if (newMe == null)
return;
addMapping(me, newMe);
tModelManager.setViewInfo(newMe, me.getViewInfo());
tModelManager.setIsFinalType(newMe, me.getIsFinalType());
Collection<IModelElement> children = me.getElementsInNamespace();
for (IModelElement child : children) {
createBranch(child);
}
}
private void addError(String msg, IModelElement cause, IModelElement cause2)
throws ModelCopyException {
System.out.println(msg + " " + cause.toString() + " "
+ cause2.toString());
// TODO
}
private void addError(String msg, IModelElement cause)
throws ModelCopyException {
System.out.println(msg + " " + cause.toString());
// TODO
}
private void addMapping(IModelElement source, IModelElement target) {
src2tg.put(source, target);
}
private IModelElement targetOf(IModelElement source) {
if (remap.containsKey(source)) {
return remap.get(source);
}
IModelElement tg = src2tg.get(source);
if (tg != null)
return tg;
if (targetModel.equals(sourceModel)) {
return source;
}
tg = targetModel.getModelManager().getElementByName(
source.getFullyQualifiedName());
if (tg != null)
return tg;
return null;
}
private Set<IModelElement> findRoots(Set<IModelElement> toCopy) {
TreeSet<IModelElement> ret = new TreeSet<IModelElement>();
for (IModelElement me : toCopy) {
IModelElement namespace = me.getNamespace();
if (namespace == null)
ret.add(me);
else if (!toCopy.contains(namespace)) {
ret.add(me);
}
}
return ret;
}
}