/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.generators; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.m2m.qvt.oml.BasicModelExtent; import org.eclipse.m2m.qvt.oml.ModelExtent; import org.eclipse.papyrus.customization.properties.generation.messages.Messages; import org.eclipse.papyrus.customization.properties.generation.wizard.widget.FileChooser; import org.eclipse.papyrus.views.properties.contexts.DataContextElement; import org.eclipse.papyrus.views.properties.contexts.Property; import org.eclipse.papyrus.views.properties.root.PropertiesRoot; import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager; import org.eclipse.papyrus.customization.properties.generation.Activator; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; /** * An IGenerator to create Property view contexts from an Ecore metamodel * FIXME : The generator doesn't seem to keep the Metaclass inheritance * * @author Camille Letavernier */ public class EcoreGenerator extends AbstractQVTGenerator { private FileChooser sourceFileChooser; private EPackage ecorePackage; public void createControls(Composite parent) { Composite root = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; root.setLayout(layout); Label sourceLabel = new Label(root, SWT.NONE); sourceLabel.setText(Messages.EcoreGenerator_source); GridData data = new GridData(); data.widthHint = 100; sourceLabel.setLayoutData(data); sourceFileChooser = new FileChooser(root, false); sourceFileChooser.setFilterExtensions(new String[]{ "ecore" }); //$NON-NLS-1$ sourceFileChooser.addListener(this); } public String getDescription() { return Messages.EcoreGenerator_ecoreGeneratorDescription; } public boolean isReady() { return sourceFileChooser.getFilePath() != null; } public String getName() { return Messages.EcoreGenerator_ecoreGeneratorName; } public boolean isSelectedSingle(Property property) { EStructuralFeature feature = getFeature(property); if(feature.isDerived()) { return false; } if(!feature.isChangeable()) { return false; } if(feature instanceof EReference) { EReference reference = (EReference)feature; if(reference.isContainer() || reference.isContainment()) return false; } return true; } /** * Retrieve the EStructuralFeature corresponding to the given property * * @param property * @return * The EStructuralFeature corresponding to the given property */ protected EStructuralFeature getFeature(Property property) { List<String> path = getPath(property); path.remove(0); //Root = EPackage EPackage currentPackage = ecorePackage; EClassifier classifier = findClassifier(path, currentPackage); if(classifier == null) { return null; } if(!(classifier instanceof EClass)) { return null; } EClass eClass = (EClass)classifier; return eClass.getEStructuralFeature(property.getName()); } /** * Retrieve the Classifier corresponding to the given path, in the given EPackage * * @param path * The list of package and subpackages names, and the classifier name, i.e. * the list of segments in the classifier's qualified name * @param source * The root EPackage in which the classifier should be retrieved * @return * The corresponding EClassifier, or null if it couldn't be retrieved */ protected EClassifier findClassifier(List<String> path, EPackage source) { String qualifier = path.get(0); EClassifier classifier = source.getEClassifier(qualifier); if(classifier == null) { source = findSubPackage(source, qualifier); if(source == null) { return null; } path.remove(0); return findClassifier(path, source); } else { return classifier; } } /** * Retrieve the subpackage corresponding to the given packageName, in the given * package * * @param currentPackage * The EPackage in which the subpackage should be found * @param packageName * The name of the EPackage to find * @return * The corresponding EPackage, or null if it couldn't be found */ protected EPackage findSubPackage(EPackage currentPackage, String packageName) { for(EPackage pack : currentPackage.getESubpackages()) { if(pack.getName().equals(packageName)) return pack; } return null; } private List<String> getPath(Property property) { List<String> result = getPath(property.getContextElement()); return result; } private List<String> getPath(DataContextElement element) { List<String> result; if(element.getPackage() == null) { result = new LinkedList<String>(); } else { result = getPath(element.getPackage()); } result.add(element.getName()); return result; } public boolean isSelectedMultiple(Property property) { if(!isSelectedSingle(property)) { return false; } EStructuralFeature feature = getFeature(property); Set<String> validDataTypes = new HashSet<String>(Arrays.asList(new String[]{ "int", "boolean", "float", "double" })); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ if(feature.getEType() instanceof EDataType) { if(validDataTypes.contains(((EDataType)feature.getEType()).getInstanceTypeName())) return true; } if(feature.getEType() instanceof EEnum) { return true; } return false; } public boolean isSelectedSingle(Property property, DataContextElement element) { return isSelectedSingle(property); } public boolean isSelectedMultiple(Property property, DataContextElement element) { return isSelectedMultiple(property); } @Override protected URI getTransformationURI() { return URI.createPlatformPluginURI(Activator.PLUGIN_ID+"/transforms/ecore2datacontext.qvto", true); //$NON-NLS-1$ } @Override protected List<ModelExtent> getModelExtents() { try { URI packageURI = URI.createPlatformResourceURI(sourceFileChooser.getFilePath(), true); ecorePackage = (EPackage)loadEMFModel(packageURI); ModelExtent inPackage = new BasicModelExtent(Collections.singletonList(ecorePackage)); PropertiesRoot root = ConfigurationManager.instance.getPropertiesRoot(); ModelExtent inRoot = new BasicModelExtent(Collections.singletonList(root)); LinkedList<ModelExtent> result = new LinkedList<ModelExtent>(); result.add(inPackage); result.add(inRoot); result.add(getOutContextExtent()); return result; } catch (Exception ex) { return null; } } }