blob: cca7d3ffee8f70876cc15c957f100d50e6852b08 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Bundesinstitut für Risikobewertung 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:
* Bundesinstitut für Risikobewertung - initial API and implementation
*******************************************************************************/
package org.eclipse.stem.model.transform.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.stem.model.codegen.CodeGenConstants;
import org.eclipse.stem.model.codegen.ModelGeneratorDescriptors;
import org.eclipse.stem.model.codegen.descriptor.ModelGeneratorDescriptor;
import org.eclipse.stem.model.metamodel.Compartment;
import org.eclipse.stem.model.metamodel.CompartmentGroup;
import org.eclipse.stem.model.metamodel.CompartmentType;
import org.eclipse.stem.model.metamodel.MetamodelFactory;
import org.eclipse.stem.model.metamodel.Model;
import org.eclipse.stem.model.metamodel.ModelParam;
import org.eclipse.stem.model.metamodel.ModelType;
import org.eclipse.stem.model.metamodel.Package;
import org.eclipse.stem.model.transform.EPackageManager;
/**
* Utility to transform EMF Ecore to STEM metamodel definitions.
* Scans all projects in the workspace (or from a given list) and
* performs the transformation.
*
*/
public class EcoreToMetamodelTransformer implements IApplication
{
private Map<EClass,Model> modelMap = new HashMap<EClass,Model>();
private Map<EClass,CompartmentGroup> labelMap = new HashMap<EClass,CompartmentGroup>();
// private Map<EClass,CompartmentGroup> labelValueMap = new HashMap<EClass,CompartmentGroup>();
@Override
public Object start(IApplicationContext context) throws Exception
{
// EPackageManager mgr = EPackageManager.getInstance();
IWorkspaceRoot wsr = ResourcesPlugin.getWorkspace().getRoot();
List<IProject> projects = new ArrayList<IProject>();
projects.add(wsr.getProject("org.eclipse.stem.diseasemodels"));
projects.add(wsr.getProject("org.eclipse.stem.populationmodels"));
projects.add(wsr.getProject("org.eclipse.stem.diseasemodels.vector"));
projects.add(wsr.getProject("org.eclipse.stem.diseasemodels.multipopulation"));
projects.add(wsr.getProject("org.eclipse.stem.diseasemodels.globalinfluenzamodel"));
projects.add(wsr.getProject("org.eclipse.stem.diseasemodels.forcing"));
// mgr.loadECoresFromProjects(projects, new NullProgressMonitor());
//mgr.loadECoresFromProjects(Arrays.asList(wsr.getProjects()), new NullProgressMonitor());
List<EPackage> pkgs = loadProjectsInOrder(projects);
System.out.println(pkgs);
preProcess(pkgs);
process(pkgs);
// for (Entry<String,EPackage> entry : mgr.getLoadedPackages().entrySet()) {
// System.out.println(entry.getKey());
// }
//
Thread.sleep(1000);
return Status.OK_STATUS;
}
private List<EPackage> loadProjectsInOrder(List<IProject> projects)
{
List<EPackage> pkgs = new ArrayList<EPackage>();
Map<IProject, List<IFile>> files = EPackageManager.getInstance().findECoresInWorkspace(new NullProgressMonitor());
for (IProject project : projects) {
List<IFile> ecores = files.get(project);
if (ecores != null) {
for (IFile ecore : ecores) {
URI ecoreURI = URI.createPlatformResourceURI(ecore.getFullPath().toString(), true);
try {
EObject obj = EPackageManager.getInstance().load(ecoreURI);
if (obj instanceof EPackage) {
pkgs.add((EPackage)obj);
}
} catch (Exception e) {
}
}
}
}
return pkgs;
}
private void process(Collection<EPackage> pkgs)
{
for (EPackage pkg : pkgs) {
process(pkg);
}
}
private void serialize(Package pkg, EPackage ePkg)
{
URI eCoreURI = ePkg.eResource().getURI();
URI metamodelURI = URI.createPlatformResourceURI(eCoreURI.toPlatformString(true).replace(".ecore", ".metamodel"), true);
// System.out.println(eCoreURI +"/"+ metamodelURI);
ResourceSet rs = EPackageManager.getInstance().getResourceSet();
try {
Resource r = rs.createResource(metamodelURI);
r.getContents().add(pkg);
r.save(null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void process(EPackage ePkg)
{
//System.out.println(ePkg.eResource().getURI());
Package pkg = MetamodelFactory.eINSTANCE.createPackage();
pkg.setName(ePkg.getName());
pkg.setPackagePrefix(ePkg.getNsPrefix());
for (EClassifier classifier : ePkg.getEClassifiers()) {
if (classifier instanceof EClass) {
process(pkg, (EClass)classifier);
}
}
assignGroupsToModels(pkg);
if (pkg.getModels().size() > 0) {
serialize(pkg,ePkg);
}
}
private void process(Package pkg, EClass eClass)
{
Model m = modelMap.get(eClass);
if (m != null) {
m = processModel(m);
if (m != null) {
pkg.getModels().add(m);
}
//return m;
}
CompartmentGroup cg = labelMap.get(eClass);
if (cg != null) {
cg = processCompartmentGroup(cg);
if (cg != null) {
pkg.getCompartmentGroups().add(cg);
}
}
}
private void assignGroupsToModels(Package pkg)
{
for (Model m : pkg.getModels()) {
for (CompartmentGroup cg : pkg.getCompartmentGroups()) {
if (cg.getName().equals(m.getName())) {
m.setCompartments(cg);
break;
}
}
}
}
private CompartmentGroup processCompartmentGroup(CompartmentGroup cg)
{
EClass labelValueClass = cg.getValueClass();
EClass labelClass = (EClass)labelValueClass.getEPackage().getEClassifier(labelValueClass.getName().replace("Value", ""));
cg.setName(labelClass.getName().replace("Label", ""));
cg.setClass(labelClass);
//cg.setValueClass(labelValueClass);
CompartmentGroup parentCG = getParentCGFromMap(cg);
if (parentCG == null && !("PopulationModel".equals(cg.getName()) || "DiseaseModel".equals(cg.getName()))) {
EClass parentClass = labelClass.getESuperTypes().get(0);
System.err.println("Null CG parent: "+ cg +" <= "+ parentClass.getName() +" ("+ parentClass.eResource() +")");
return null;
}
cg.setParentGroup(parentCG);
collectCompartments(cg);
return cg;
}
private CompartmentType getTypeForAttribute(EAttribute attr)
{
if (attr.getName().toLowerCase().contains("incidence")) {
return CompartmentType.INCIDENCE;
} else if (attr.getName().toLowerCase().contains("deaths")) {
return CompartmentType.DEATHS;
}
return CompartmentType.STANDARD;
}
private void collectCompartments(CompartmentGroup cg)
{
for (EAttribute attr : cg.getValueClass().getEAttributes()) {
Compartment compartment = MetamodelFactory.eINSTANCE.createCompartment();
compartment.setDataType(EcorePackage.Literals.EDOUBLE);
compartment.setName(attr.getName());
compartment.setType(getTypeForAttribute(attr));
cg.getCompartments().add(compartment);
}
}
private Model processModel(Model m)
{
EClass eClass = m.getClass_();
m.setName(eClass.getName());
Model parentModel = getParentModelFromMap(m);//modelMap.get(parentClass);
if (m.getName().contains("Deterministic") || m.getName().contains("Stochastic")) {
System.out.println("Excluding "+ m.getName());
return null;
}
if (parentModel == null && !("PopulationModel".equals(m.getName()) || "DiseaseModel".equals(m.getName()))) {
EClass parentClass = eClass.getESuperTypes().get(0);
System.err.println("Null Model Parent: "+ m +" <= "+ parentClass.getName() +" ("+ parentClass.eResource() +")");
return null;
}
m.setParentModel(parentModel);
ModelGeneratorDescriptor descriptor = ModelGeneratorDescriptors.getInstance().getDescriptorForEClass(eClass);
if (descriptor != null) {
ModelType type = ModelType.get(descriptor.getModelType());
m.setModelType(type);
}
collectModelParams(m);
return m;
//System.out.println("Processing "+ m);
}
private void collectModelParams(Model model)
{
EClass eClass = model.getClass_();
for (EAttribute attr : eClass.getEAttributes()) {
ModelParam param = MetamodelFactory.eINSTANCE.createModelParam();
if (attr.getEType() instanceof EDataType) {
param.setDataType((EDataType)attr.getEType());
} else {
System.err.println("Unsupported data type for "+attr.getName() + ": "+ attr.getEType());
param.setDataType(EcorePackage.Literals.EDOUBLE);
}
param.setName(attr.getName());
param.setDefaultValue(attr.getDefaultValueLiteral());
param.setDisplayName(formatString(attr.getName()));
model.getParameters().add(param);
}
for (EReference ref : eClass.getEReferences()) {
ModelParam param = MetamodelFactory.eINSTANCE.createModelParam();
param.setName(ref.getName());
param.setDataType(ref.getEType());
param.setDefaultValue(ref.getDefaultValueLiteral());
param.setDisplayName(formatString(ref.getName()));
model.getParameters().add(param);
}
//System.out.println(model.getName() + " / "+ eClass.getEAttributes());
}
private String formatString(String data)
{
StringBuilder sb = new StringBuilder();
char[] chars = data.toCharArray();
sb.append(Character.toUpperCase(chars[0]));
for (int idx=1; idx<chars.length; idx++) {
if (Character.isUpperCase(chars[idx])) {
if (Character.isLowerCase(chars[idx-1])
|| (chars.length > idx+1 && Character.isLowerCase(chars[idx+1]))) {
sb.append(" ");
}
}
sb.append(chars[idx]);
}
return sb.toString();
}
private Model getParentModelFromMap(Model m)
{
EClass parentClass = m.getClass_().getESuperTypes().get(0);
Model parentModel = modelMap.get(parentClass);
if (parentModel == null) {
for (Entry<EClass,Model> entry : modelMap.entrySet()) {
EClass eClass = entry.getKey();
if (eClass.getEPackage().getNsURI().equals(parentClass.getEPackage().getNsURI()) &&
eClass.getName().equals(parentClass.getName())) {
parentModel = entry.getValue();
}
}
}
return parentModel;
}
private CompartmentGroup getParentCGFromMap(CompartmentGroup cg)
{
EClass parentClass = cg.getValueClass().getESuperTypes().get(0);
CompartmentGroup parentGroup = labelMap.get(parentClass);
if (parentGroup == null) {
for (Entry<EClass,CompartmentGroup> entry : labelMap.entrySet()) {
EClass eClass = entry.getKey();
if (eClass.getEPackage().getNsURI().equals(parentClass.getEPackage().getNsURI()) &&
eClass.getName().equals(parentClass.getName())) {
parentGroup = entry.getValue();
}
}
}
return parentGroup;
}
@SuppressWarnings("unused")
private String classToString(Object object)
{
return object.getClass().getName() + "@" + Integer.toHexString(object.hashCode());
}
private void preProcess(Collection<EPackage> pkgs)
{
for (EPackage pkg : pkgs) {
for (EClassifier classifier : pkg.getEClassifiers()) {
if (classifier instanceof EClass) {
preProcessEClass((EClass)classifier);
}
}
}
}
private void preProcessEClass(EClass eClass)
{
if (CodeGenConstants.INTEGRATION_DECORATOR_DESCRIPTOR.isSuperTypeOf(eClass)) {
Model m = MetamodelFactory.eINSTANCE.createModel();
m.setClass(eClass);
modelMap.put(eClass, m);
}
// if (CodeGenConstants.INTEGRATION_LABEL_DESCRIPTOR.isSuperTypeOf(eClass)) {
// CompartmentGroup cg = MetamodelFactory.eINSTANCE.createCompartmentGroup();
// cg.setClass(eClass);
//
// labelMap.put(eClass, cg);
// }
if (CodeGenConstants.INTEGRATION_LABEL_VALUE_DESCRIPTOR.isSuperTypeOf(eClass)) {
CompartmentGroup cg = MetamodelFactory.eINSTANCE.createCompartmentGroup();
cg.setValueClass(eClass);
labelMap.put(eClass, cg);
}
}
@Override
public void stop()
{
}
}