blob: 23cfd0e1cec7640bf639a340ba2ec8692e84d154 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.exporter.services;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.mylyn.docs.intent.client.ui.logger.IntentUiLogger;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter;
import org.eclipse.mylyn.docs.intent.core.compiler.TraceabilityIndex;
import org.eclipse.mylyn.docs.intent.core.compiler.TraceabilityIndexEntry;
import org.eclipse.mylyn.docs.intent.markup.gen.services.ImageServices;
/**
* Utility class allowing to determine the images associated to some EObject, and copy them inside the
* exported documentation.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
public final class CopyImageUtils {
/**
* The {@link AdapterFactoryItemDelegator} to use to get images from {@link EObject}s.
*/
private static AdapterFactoryItemDelegator itemDelegator;
/**
* The resource set to use.
*/
private static ResourceSetImpl resourceSet;
/**
* Private constructor.
*/
private CopyImageUtils() {
}
/**
* Determines the image associated to the given EObject and copies it inside the exported documentation.
*
* @param any
* the eobject to get the image from
* @param repositoryAdapter
* the repository adapter to use to access to informations (traceability index...)
* @param outputFolder
* the target folder in which image will be copied
* @return the image associated to the given EObject
*/
public static String copyImageAndGetImageID(EObject any, RepositoryAdapter repositoryAdapter,
File outputFolder) {
String qualifiedImageID = "";
// Step 1: getting the image URL thanks to the item delegator
Object imageURL = getImageURL(any);
if (imageURL instanceof URL) {
try {
// Step 2: resolve URL
URL resolvedURL = FileLocator.resolve((URL)imageURL);
EClassifier classifier = null;
if (any instanceof EClassifier) {
classifier = (EClassifier)any;
} else {
classifier = any.eClass();
}
// If default "Item" image has been
if (resolvedURL.toString().contains("org.eclipse.emf.edit")
&& resolvedURL.toString().endsWith("/icons/full/obj16/Item.gif")) {
// we search for an "edit" plugin in the workspace
imageURL = getImageFromWorkspace(classifier, repositoryAdapter);
if (imageURL != null) {
resolvedURL = (URL)imageURL;
}
}
// Step 3: copy image in the exported documentation
if (resolvedURL != null && resolvedURL.getFile() != null && outputFolder != null) {
qualifiedImageID = copyImageIfNeeded(classifier, outputFolder, resolvedURL,
resolvedURL.openStream());
}
} catch (IOException e) {
IntentUiLogger.logError(e);
}
}
return qualifiedImageID;
}
/**
* Searches for an edit plugin corresponding to the given EObject and tries to retrieve its associated
* image.
*
* @param repositoryAdapter
* the repository adapter to use to access to informations (traceability index...)
* @param any
* the eobject to get the image from
* @return the URL of the image corresponding to the given EObject, null if none found
*/
private static URL getImageFromWorkspace(EClassifier any, RepositoryAdapter repositoryAdapter) {
// If the core.resource plugin is not available, we return null
if (EMFPlugin.IS_RESOURCES_BUNDLE_AVAILABLE) {
TraceabilityIndex projectTraceabilityIndex = IntentAcceleoServices
.getTraceabilityIndex(repositoryAdapter);
if (projectTraceabilityIndex != null) {
for (TraceabilityIndexEntry entry : projectTraceabilityIndex.getEntries()) {
if (any.eResource().getURI().toString().contains(entry.getGeneratedResourcePath())) {
URI metamodelURI = entry.getResourceDeclaration().getUri();
doGetImageFromWorkspace(metamodelURI, any);
}
}
}
}
return null;
}
/**
* Searches for an edit plugin corresponding to the given EObject and tries to retrieve its associated
* image.
*
* @param metamodelURI
* the {@link URI}
* @param classifier
* the {@link EObject} to get the image from
* @return the URL of the image associated to the given classifier (if any found)
*/
private static URL doGetImageFromWorkspace(URI metamodelURI, EClassifier classifier) {
URL imageURL = null;
if (metamodelURI != null && metamodelURI.toString().replace("\"", "").endsWith("ecore")) {
URI genModelURI = URI.createURI(metamodelURI.toString().replace("\"", "")
.replace("ecore", "genmodel"));
try {
Resource resource = getResourceSet().getResource(genModelURI, true);
if (resource.getContents().isEmpty()
|| !(resource.getContents().iterator().next() instanceof GenModel)) {
return null;
}
String editIconsDirectory = ((GenModel)resource.getContents().iterator().next())
.getEditIconsDirectory();
IFolder folder = ResourcesPlugin.getWorkspace().getRoot()
.getFolder(new Path(editIconsDirectory + "/full/obj16"));
if (folder.exists()) {
for (String imageExtension : new String[] {"gif", "png",
}) {
if (folder.getFile(classifier.getName() + "." + imageExtension).exists()) {
imageURL = new URL("file:/"
+ folder.getFile(classifier.getName() + "." + imageExtension)
.getLocation().toString());
}
}
}
// CHECKSTYLE:OFF
} catch (RuntimeException e) {
// CHECKSTYLE:ON
IntentUiLogger.logInfo("Cannot find genmodel at " + genModelURI
+ ". Default image will be use to display " + classifier.getName());
} catch (MalformedURLException e) {
IntentUiLogger.logError(e);
}
}
return imageURL;
}
/**
* Returns the URL of the image associated to the given {@link EObject} through AdapterFactories.
*
* @param any
* the element to get the image from
* @return the URL of the image associated to the given {@link EObject}
*/
private static Object getImageURL(EObject any) {
Object imageURL = null;
// Step 1: getting the image URL thanks to the item delegator
if (any instanceof EClass && ((EClassifier)any).getEPackage() != null) {
EObject instance = ((EClassifier)any).getEPackage().getEFactoryInstance().create((EClass)any);
imageURL = getItemDelegator(any).getImage(instance);
} else {
imageURL = getItemDelegator(any).getImage(any);
}
// Step 2: convert image location into URL format if needed
if (!(imageURL instanceof URL)) {
if (imageURL instanceof URI) {
try {
imageURL = new URL(imageURL.toString());
} catch (MalformedURLException e) {
// silent catch
}
} else {
if (imageURL instanceof org.eclipse.emf.edit.provider.ComposedImage) {
imageURL = ((org.eclipse.emf.edit.provider.ComposedImage)imageURL).getImages().iterator()
.next();
}
}
}
return imageURL;
}
/**
* Copies the image associated to the given classifier (and with the given URL) into the given output
* folder.
*
* @param classifier
* the type associated to the image
* @param outputFolder
* the output folder in which the image will be copied
* @param imageURL
* the URL of the image to copy
* @param sourceStream
* an input stream on the image
* @return the path where the image was copied
* @throws IOException
* if files cannot be properly accessed
*/
private static String copyImageIfNeeded(EClassifier classifier, File outputFolder, URL imageURL,
InputStream sourceStream) throws IOException {
String packageName = "";
if (classifier.getEPackage() != null) {
packageName = classifier.getEPackage().getName();
}
File targetFile = new File(outputFolder.getAbsolutePath() + "/icons/generated/" + packageName
+ imageURL.getFile().substring(imageURL.getFile().lastIndexOf('/')));
// create folders if needed :
new File(outputFolder.getAbsolutePath() + "/icons/generated/" + packageName).mkdirs();
if (!targetFile.exists()) {
ImageServices.copyFile(sourceStream, targetFile);
}
String copiedImagePath = targetFile.getAbsolutePath().toString();
String outputFolderPath = outputFolder.getAbsolutePath();
return "../" + copiedImagePath.substring(outputFolderPath.length());
}
/**
* Returns the {@link AdapterFactoryItemDelegator} to use for getting images associated to the given
* EObject.
*
* @param any
* the EObject the EObject to get the image from
* @return the {@link AdapterFactoryItemDelegator} to use for getting images associated to the given
* EObject
*/
private static AdapterFactoryItemDelegator getItemDelegator(EObject any) {
if (itemDelegator == null) {
ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());
itemDelegator = new AdapterFactoryItemDelegator(adapterFactory);
}
return itemDelegator;
}
/**
* Returns the Resource set to use.
*
* @return the resource set to use
*/
private static ResourceSet getResourceSet() {
if (resourceSet == null) {
resourceSet = new ResourceSetImpl();
}
return resourceSet;
}
/**
* Disposes the service.
*/
public static void dispose() {
if (itemDelegator != null) {
((ComposedAdapterFactory)itemDelegator.getAdapterFactory()).dispose();
}
resourceSet = null;
itemDelegator = null;
}
}