blob: 060fe3243c176dffa3e6a815886a6edf9f47b427 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Willink Transformations 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:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.cs2as.build.mwe;
import java.io.IOException;
import java.text.MessageFormat;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.mwe.core.WorkflowContext;
import org.eclipse.emf.mwe.core.issues.Issues;
import org.eclipse.emf.mwe.core.lib.AbstractWorkflowComponent2;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
import org.eclipse.emf.mwe2.runtime.Mandatory;
public class VisitableInjector extends AbstractWorkflowComponent2 {
public static class VisitableInfo {
private String baseGenModelURI;
private String targetGenModelURI;
private String className = "Visitable";
private String instanceTypeName = "";
private String mainPackageName;
@Mandatory
public void setTargetGenModel(String genModelURI) {
this.targetGenModelURI = genModelURI;
}
public void setBaseGenModel(String genModelURI) {
this.baseGenModelURI = genModelURI;
}
public void setVisitableClassName(String className) {
this.className = className;
}
public void setMainPackageName(String mainPackage) {
this.mainPackageName = mainPackage;
}
@Mandatory
public void setVisitableInstanceTypeName(String instanceTypeName) {
this.instanceTypeName = instanceTypeName;
}
}
private ResourceSet rSet;
private VisitableInfo visitableInfo;
@Override
public void preInvoke() {
super.preInvoke();
if (visitableInfo.baseGenModelURI == null) {
visitableInfo.baseGenModelURI = visitableInfo.targetGenModelURI;
}
}
@Override
protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, Issues issues) {
try {
EClass visitableClass = getVisitableClass(visitableInfo.baseGenModelURI);
injectInterface(visitableInfo.targetGenModelURI, visitableClass);
} catch(IOException e) {
issues.addError(e.getMessage());
}
}
private EPackage getMainPackage(GenModel targetGenModel, String mainPackageName) {
if (mainPackageName == null) {
GenPackage targetGenPackage = targetGenModel.getGenPackages().get(0); // FIXME what if we have many ?
return targetGenPackage.getEcorePackage();
} else {
for (GenPackage gPackage : targetGenModel.getGenPackages()) {
EPackage mainPackage = getMainPackage(gPackage, mainPackageName);
if (mainPackage != null) {
return mainPackage;
}
}
}
throw new IllegalStateException(MessageFormat.format("EPackage with name {0} not found in GenModel {1}", mainPackageName,targetGenModel.eResource().getURI()));
}
private EPackage getMainPackage(GenPackage targetGenPackage, String mainPackageName) {
EPackage ePackage = targetGenPackage.getEcorePackage();
if (mainPackageName.equals(ePackage.getName())) {
return ePackage;
} else {
for (GenPackage nestedGPackage : targetGenPackage.getNestedGenPackages()) {
EPackage mainPackage = getMainPackage(nestedGPackage, mainPackageName);
if (mainPackage != null) {
return mainPackage;
}
}
return null;
}
}
private void injectInterface(String genModelURI, EClass visitableClass) throws IOException {
Resource targetResource = rSet.getResource(URI.createURI(genModelURI), true);
GenModel targetGenModel = (GenModel) targetResource.getContents().get(0);
boolean targetChanged = false;
for (GenPackage gPackage : targetGenModel.getGenPackages()) {
targetChanged |= injectInterface(gPackage, visitableClass);
}
if (targetChanged) {
targetGenModel.reconcile();
targetResource.save(null);
}
}
private boolean injectInterface(GenPackage targetGenPackage, EClass visitableClass) throws IOException {
EPackage targetEPackage = targetGenPackage.getEcorePackage();
boolean targetChanged = false;
for (EClassifier eClassifier : targetEPackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
EClass eClass = (EClass) eClassifier;
if (eClass.getESuperTypes().size() == 0
&& eClass != visitableClass) {
eClass.getESuperTypes().add(visitableClass);
targetChanged = true;
}
}
}
if (targetChanged) {
targetEPackage.eResource().save(null);
}
return targetChanged;
}
private EClass getVisitableClass(String genModelURI) throws IOException {
Resource resource = rSet.getResource(URI.createURI(genModelURI), true);
GenModel genModel = (GenModel) resource.getContents().get(0);
EPackage ePackage = getMainPackage(genModel, visitableInfo.mainPackageName);
String className = visitableInfo.className;
String instanceTypeName = visitableInfo.instanceTypeName;
for (EClassifier eClassifier : ePackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
EClass eClass = (EClass) eClassifier;
if (className.equals(eClass.getName())
&& instanceTypeName.equals(eClass.getInstanceTypeName())) {
return eClass;
}
}
}
// If not found we create it
EClass visitableClass = EcoreFactory.eINSTANCE.createEClass();
visitableClass.setName(className);
visitableClass.setInstanceTypeName(instanceTypeName);
visitableClass.setAbstract(true);
visitableClass.setInterface(true);
ePackage.getEClassifiers().add(visitableClass);
ePackage.eResource().save(null);
genModel.reconcile();
resource.save(null);
return visitableClass;
}
@Mandatory
public void setResourceSet(ResourceSet rSet) {
this.rSet = rSet;
}
@Mandatory
public void setVisitableInfo(VisitableInfo csTraceInfo) {
this.visitableInfo = csTraceInfo;
}
}