/*****************************************************************************
* Copyright (c) 2008 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Added support for Image's name
*
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Image;
import org.eclipse.uml2.uml.Stereotype;
// TODO: Auto-generated Javadoc
/**
* Utility class for <code>org.eclipse.uml2.uml.Image</code><BR>
*/
public class ImageUtil {
/**
* ID of the EAnnotation where "expression" (used to select stereotype icon) is stored on image.
*/
public static String IMAGE_PAPYRUS_EA = "image_papyrus";
/**
* KEY of the EAnnotation where "expression" (used to select stereotype icon) is stored on
* image.
*/
public static String IMAGE_EXPR_KEY = "image_expr_key";
/**
* KEY of the EAnnotation where "kind" (kind = icon/shape) is stored on image.
*/
public static String IMAGE_KIND_KEY = "image_kind_key";
/**
* KEY of the EAnnotation where the image's name is stored
*
* @see {@link #getName(Image)}
* @see {@link #setName(Image, String)}
*/
public static String IMAGE_NAME_KEY = "image_name_key";
/**
* Set the content of an {@link Image} with a file (containing an image).
*
* @param image
* the UML {@link Image} to set
* @param imageFile
* the icon
*/
// @unused
public static void setContent(Image image, File imageFile) {
try {
String rawImageData = "";
if(imageFile != null) {
byte[] byteFlow = getBytesFromFile(imageFile);
rawImageData = "";
// file reading
for(byte element : byteFlow) {
rawImageData = rawImageData + element + "%";
}
} else {
rawImageData = null;
}
image.setContent(rawImageData);
} catch (Exception ex) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getLocalizedMessage(), ex));
}
}
/**
* Get the content of an {@link Image} as {@link org.eclipse.swt.graphics.Image}
*
* @param image
* the UML {@link Image} to set
*
* @return {@link org.eclipse.swt.graphics.Image} content
*/
public static org.eclipse.swt.graphics.Image getContent(Image image) throws Exception {
if(image == null) {
// null parameter
return null;
}
if(image.getContent() == null) {
// null image
return null;
}
// else
String rawData = image.getContent();
StringTokenizer strToken = new StringTokenizer(rawData, "%");
byte[] target = new byte[strToken.countTokens()];
// decoding image
int j = 0;
while(strToken.hasMoreTokens()) {
target[j] = (new Byte(strToken.nextToken()).byteValue());
j++;
}
org.eclipse.swt.graphics.Image decodedImage = new org.eclipse.swt.graphics.Image(null, new ByteArrayInputStream(target));
return decodedImage;
}
/**
* Get the image specified by the location property of an {@link Image} as {@link org.eclipse.swt.graphics.Image}
*
* @param image
* the UML {@link Image} to set
*
* @return {@link org.eclipse.swt.graphics.Image} image
*/
public static org.eclipse.swt.graphics.Image getImageFromLocation(Image image) {
org.eclipse.swt.graphics.Image swtImage = null;
// Try to instantiate an SWT image from the path stored
// in UML Image location property
String location = image.getLocation();
if((location != null) && !("".equals(location))) {
URI iconURI = URI.createURI(location);
if(iconURI.isRelative()) {
String err_msg = "Incorrect implementation of relative location." + location;
Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, err_msg, new Exception(err_msg)));
URI pluginURI = URI.createPlatformPluginURI(location, true); // <- TODO : fix this to retrieve the related plug-in URI
iconURI = iconURI.resolve(pluginURI);
}
try {
ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(new URL(iconURI.toString()));
swtImage = imageDescriptor.createImage();
} catch (Exception e) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Could not create image from location : " + location, e));
}
}
return swtImage;
}
/**
* Read an image file content.
*
* @param file
* the file
*
* @return a table of bytes of the file content
*
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if(length > Integer.MAX_VALUE) {
throw new IOException("Image too big to encode");
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while((offset < bytes.length) && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
}
// Ensure all the bytes have been read in
if(offset < bytes.length) {
throw new IOException("Could not completely read file " + file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
/**
* Associates an expression to an image.
*
* @param image
* the image
* @param expression
* the expression
*/
public static void setExpression(Image image, String expression) {
EAnnotation ea_Image = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
// Create annotation for icon selection if it does not exist
if(ea_Image == null) {
ea_Image = image.createEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
}
// If expression == "" remove the EAnnotation
if("".equals(expression)) {
ea_Image.getDetails().removeKey(IMAGE_EXPR_KEY);
} else {
ea_Image.getDetails().put(ImageUtil.IMAGE_EXPR_KEY, expression);
}
cleanImageAnnotation(ea_Image);
}
/**
* Returns the expression associated to the image.
*
* @param image
* the image
*
* @return the expression associated to the image
*/
public static String getExpression(org.eclipse.uml2.uml.Image image) {
EAnnotation ea_ImageExpr = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
String expr = null;
if((ea_ImageExpr != null) && (ea_ImageExpr.getDetails().containsKey(ImageUtil.IMAGE_EXPR_KEY))) {
expr = ea_ImageExpr.getDetails().get(ImageUtil.IMAGE_EXPR_KEY);
}
return expr;
}
/**
* Associates a name to an Image.
*
* The UML Image is not a NamedElement : the name is stored as an
* EAnnotation, and is not mandatory. The name should only be used for
* displaying the image's label : this is *not* an identifier.
*
* @param image
* The image
* @param name
* The name
*/
public static void setName(Image image, String name) {
EAnnotation ea_Image = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
// Create annotation for icon selection if it does not exist
if(ea_Image == null) {
ea_Image = image.createEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
}
// If expression == "" remove the EAnnotation
if("".equals(name)) {
ea_Image.getDetails().removeKey(IMAGE_NAME_KEY);
} else {
ea_Image.getDetails().put(ImageUtil.IMAGE_NAME_KEY, name);
}
cleanImageAnnotation(ea_Image);
}
/**
* Returns the name associated to the image
*
* The UML Image is not a NamedElement : the name is stored as an
* EAnnotation, and is not mandatory. The name should only be used for
* displaying the image's label : this is *not* an identifier.
*
* @param image
* the image
* @return
* the name associated to the image
*/
public static String getName(Image image) {
EAnnotation ea_Image = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
String name = null;
if((ea_Image != null) && (ea_Image.getDetails().containsKey(IMAGE_NAME_KEY))) {
name = ea_Image.getDetails().get(IMAGE_NAME_KEY);
}
return name;
}
/**
* Removes the EAnnotation from the Image if the annotation doesn't contain any valid key
*
* @param annotation
*/
private static void cleanImageAnnotation(EAnnotation annotation) {
EMap<String, String> details = annotation.getDetails();
if(details.isEmpty()) {
//if(!(details.containsKey(IMAGE_NAME_KEY)) && !(details.containsKey(IMAGE_KIND_KEY) && !(details.containsKey(IMAGE_NAME_KEY)))) {
annotation.setEModelElement(null);
}
}
/**
* Associates kind to an image.
*
* @param image
* the image
* @param kind
* of image (icon / shape)
*/
// @unused
public static void setKind(org.eclipse.uml2.uml.Image image, String kind) {
EAnnotation ea_Image = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
// Create annotation for icon selection if it does not exist
if(ea_Image == null) {
ea_Image = image.createEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
}
// If expression == "" remove the EAnnotation
if("".equals(kind)) {
ea_Image.getDetails().removeKey(IMAGE_KIND_KEY);
} else {
ea_Image.getDetails().put(ImageUtil.IMAGE_KIND_KEY, kind);
}
cleanImageAnnotation(ea_Image);
}
/**
* Returns the kind of the image (icon or shape for Papyrus).
*
* @param image
* the image
*
* @return kind of image
*/
public static String getKind(org.eclipse.uml2.uml.Image image) {
EAnnotation ea_ImageExpr = image.getEAnnotation(ImageUtil.IMAGE_PAPYRUS_EA);
String kind = null;
if((ea_ImageExpr != null) && (ea_ImageExpr.getDetails().containsKey(ImageUtil.IMAGE_KIND_KEY))) {
kind = ea_ImageExpr.getDetails().get(ImageUtil.IMAGE_KIND_KEY);
}
return kind;
}
/**
* Evaluates the "Expression" EAnnotation associated to the image.
*
* @param element
* on which the stereotype (owning current image) is applied
* @param image
* the image
*
* @return true if the expression is correct
*/
public static boolean evalExpression(Image image, Element element) {
/*
* Expression has the form : propName = Literal
*/
/* Firstly we extract the propertyName and the literal */
String propName = null;
String literal = null;
Stereotype st = (Stereotype)image.getOwner();
// Retrieve Expression
String expression = ImageUtil.getExpression(image);
if(expression == null) {
// No expression to check
return false;
}
// Parse and test expression
StringTokenizer sToken = new StringTokenizer(expression.replace(" ", ""), "=");
if(sToken.countTokens() == 2) {
propName = sToken.nextToken();
literal = sToken.nextToken();
} else {
// Bad formed expression --> ignore
return false;
}
if(element.getValue(st, propName) != null) {
/* extract property value from applied stereotype */
Object val = element.getValue(st, propName);
if(val instanceof EnumerationLiteral) {
if(((EnumerationLiteral)val).getLabel().equals(literal)) {
return true;
}
}
}
// In any other case (bad expression, not property found...)
return false;
}
/**
* Test expression on every image, stop on first verified expression.
*
* @param element
* the element to check
* @param images
* the list of images to check
*
* @return first image verifying its expression
*/
public static Image findImageVerifyingExpression(Element element, EList<Image> images) {
Image image = null;
Iterator<Image> it = images.iterator();
while((image == null) && it.hasNext()) {
Image current = it.next();
if(ImageUtil.evalExpression(current, element)) {
image = current;
}
}
return image;
}
/**
* Create an Id to store and retrieve image (SWT) In registry.
*
* @param image
* the image
*
* @return the image id
*/
public static String getImageId(Image image) {
String id = "";
Stereotype owner = (Stereotype)image.getOwner();
id += owner.getQualifiedName() + "_img_" + owner.getIcons().indexOf(image);
return id;
}
}