blob: 1457f63032654264f6659f57a1bb2fa407ac65eb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2016 EclipseSource Muenchen GmbH 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:
* Stefan Dirix - initial API and implementation
* Laurent Delaigue - Log invalid configuration
* Philip Langer - javadoc
*******************************************************************************/
package org.eclipse.emf.compare.diagram.ide.ui.papyrus.util;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.compare.diagram.ide.ui.papyrus.internal.CompareDiagramIDEUIPapyrusPlugin;
import org.eclipse.emf.compare.diagram.ide.ui.papyrus.internal.CompareUIPapyrusMessages;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.papyrus.infra.core.resource.AbstractBaseModel;
import org.eclipse.papyrus.infra.core.resource.IModel;
import org.eclipse.papyrus.infra.core.resource.ModelsReader;
/**
* This class can be used to handle the model extension point of Papyrus.
*
* @author Stefan Dirix <sdirix@eclipsesource.com>
* @since 2.4
*/
public final class ModelExtensionUtil {
/**
* Defined because the corresponding field in ModelsReader is private.
*/
private static final String FILE_EXTENSION_ATTRIBUTE = "fileExtension"; //$NON-NLS-1$
/**
* Defined because the corresponding field in ModelsReader is private.
*/
private static final String CLASSNAME_ATTRIBUTE = "classname"; //$NON-NLS-1$
/**
* Method name to request save parameters.
*/
private static final String SAVE_PARAMETERS_METHOD = "getSaveOptions"; //$NON-NLS-1$
/**
* Disallow Constructor for Util classes.
*/
private ModelExtensionUtil() {
// Disallow Constructor
}
/**
* Checks the platform registry for extensions registered on the model extension point of Papyrus.
*
* @return A possibly empty array of {@link IConfigurationElement}s.
*/
public static IConfigurationElement[] getModelExtensions() {
return Platform.getExtensionRegistry().getConfigurationElementsFor(
org.eclipse.papyrus.infra.core.Activator.PLUGIN_ID, ModelsReader.EXTENSION_POINT_NAME);
}
/**
* Determines all file extensions directly registered with the model extension point of Papyrus.
*
* @return A possibly empty collection of registered file extensions. Does not contain {@code null} values
* or duplicates.
*/
public static Collection<String> getRegisteredFileExtensions() {
Set<String> fileExtensions = new LinkedHashSet<String>();
IConfigurationElement[] modelExtensions = getModelExtensions();
for (IConfigurationElement element : modelExtensions) {
if (ModelsReader.MODEL_ELEMENT_NAME.equals(element.getName())) {
String fileExtension = element.getAttribute(FILE_EXTENSION_ATTRIBUTE);
if (fileExtension != null) {
fileExtensions.add(fileExtension);
}
}
}
return fileExtensions;
}
/**
* <p>
* Returns the save parameters for the given {@code resourceExtension}. First a dynamic instance of the
* model registered to the extension point is created. If this model offers the option to determine its
* save options, they will be returned. If any error occurs during that process, the default save options
* for Papyrus models will be returned. If no dynamic instance can be created or the dynamic instance does
* not offer a way to determine its save options, an empty map will be returned.
* </p>
* <p>
* If multiple models are registered for the same file extension only the first model is looked at.
* </p>
*
* @param resourceExtension
* The file extension for which the save parameters are tried to be determined.
* @return A map with save options if they were successfully determined, an empty map otherwise.
*/
public static Map<?, ?> getSaveParameters(String resourceExtension) {
IConfigurationElement[] modelExtensions = getModelExtensions();
Map<?, ?> saveOptions = Collections.EMPTY_MAP;
for (IConfigurationElement element : modelExtensions) {
if (ModelsReader.MODEL_ELEMENT_NAME.equals(element.getName())) {
String fileExtension = element.getAttribute(FILE_EXTENSION_ATTRIBUTE);
if (fileExtension != null && fileExtension.equals(resourceExtension)) {
// Try to load the IModel class and request save parameters if the IModel class extends
// the AbstractBaseModel. This should not fail but maybe does anyway since the IModel
// class can't be initialized here. If this is the case return the default Papyrus save
// parameters.
try {
IModel imodel = (IModel)element.createExecutableExtension(CLASSNAME_ATTRIBUTE);
if (imodel instanceof AbstractBaseModel) {
try {
AbstractBaseModel model = (AbstractBaseModel)imodel;
// use reflection since there is no good reason why this method is protected
// instead of public (like the static default version since version 1.1.0).
// Also
// protected means it is part of the API and will not change.
Method getSaveParametersMethod = model.getClass().getDeclaredMethod(
SAVE_PARAMETERS_METHOD, new Class[0]);
getSaveParametersMethod.setAccessible(true);
saveOptions = (Map<?, ?>)getSaveParametersMethod.invoke(model, new Object[0]);
// CHECKSTYLE:OFF We do want to catch any exception
} catch (Exception e) {
// CHECKSTYLE:ON
return getDefaultSaveOptions();
}
}
} catch (CoreException e) {
// Configuration problem
CompareDiagramIDEUIPapyrusPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, CompareDiagramIDEUIPapyrusPlugin.PLUGIN_ID,
CompareUIPapyrusMessages.getString(
"ModelExtensionUtil.InvalidConfig", fileExtension))); //$NON-NLS-1$
}
break; // We have found the extension, no need to continue iterating
}
}
}
if (saveOptions == null) {
saveOptions = Collections.EMPTY_MAP;
}
return saveOptions;
}
/**
* This method returns the default save options of {@link AbstractBaseModel}.
*
* @return The default save options of {@link AbstractBaseModel}.
*/
private static Map<?, ?> getDefaultSaveOptions() {
DefaultSaveOptionsClass saveOptions = new DefaultSaveOptionsClass();
return saveOptions.getMyDefaultSaveOptions();
}
/**
* Workaround class to access the default save options which are hidden behind a "protected" barrier
* before version 1.1.0.
*/
private static class DefaultSaveOptionsClass extends AbstractBaseModel {
public Map<?, ?> getMyDefaultSaveOptions() {
return getSaveOptions();
}
@Override
protected String getModelFileExtension() {
return null;
}
@Override
public String getIdentifier() {
return null;
}
/**
* Stub implementation, which always returns <code>false</code>.
* <p>
* Since Papyrus 2.0, {@link AbstractBaseModel} forces us to implement
* {@link AbstractBaseModel#canPersist(EObject)}. We omit <code>@Override</code> on purpose to be
* backward compatible.
* </p>
*
* @param eObject
* This parameter will be ignored.
* @return <code>false</code>.
*/
@SuppressWarnings("all")
public boolean canPersist(EObject eObject) {
return false;
}
/**
* Stub implementation, which does nothing.
* <p>
* Since Papyrus 2.0, {@link AbstractBaseModel} forces us to implement
* {@link AbstractBaseModel#persist(EObject)}. We omit <code>@Override</code> on purpose to be
* backward compatible.
* </p>
*
* @param eObject
* This parameter will be ignored.
*/
@SuppressWarnings("all")
public void persist(EObject eObject) {
// no implementation
}
}
}