/******************************************************************************* * <copyright> * * Copyright (c) 2005, 2010 SAP AG. * 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: * SAP AG - initial API, implementation and documentation * * </copyright> * *******************************************************************************/ package org.activiti.designer.eclipse.util; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.bpmn2.BaseElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; /** * Collection of general static helper methods. */ public class Util { private static final String DIAGRAM_NAME_PATTERN = "name=\"%s\""; private static final String DIAGRAM_NAME_DEFAULT = String.format(DIAGRAM_NAME_PATTERN, "my_bpmn2_diagram"); /** * Moves the object at the source index of the list to the _target index of * the list and returns the moved object. * * @param targetIndex * the new position for the object in the list. * @param sourceIndex * the old position of the object in the list. * @return the moved object. * @exception IndexOutOfBoundsException * if either index isn't within the size range. */ public static Object moveElementInList(List<Object> list, int targetIndex, int sourceIndex) { if (targetIndex >= list.size() || targetIndex < 0) throw new IndexOutOfBoundsException("targetIndex=" + targetIndex + ", size=" + list.size()); //$NON-NLS-1$ //$NON-NLS-2$ if (sourceIndex >= list.size() || sourceIndex < 0) throw new IndexOutOfBoundsException("sourceIndex=" + sourceIndex + ", size=" + list.size()); //$NON-NLS-1$ //$NON-NLS-2$ Object object = list.get(sourceIndex); if (targetIndex != sourceIndex) { list.remove(sourceIndex); list.add(targetIndex, object); } return object; } /** * Returns true, if the given objects equal, while null is also a valid value. * In detail the check is: (o1 == null && o2 == null) || (o1.equals(o2)). * * @param o1 * The first Object to compare. * @param o2 * The second Object to compare. * @return true, if the given objects equal, while null is also a valid value. */ public static boolean equalsWithNull(Object o1, Object o2) { if (o1 == null && o2 == null) return true; if (o1 == null || o2 == null) return false; return o1.equals(o2); } public static BaseElement[] getAllBpmnElements(IProject project, ResourceSet rSet) { // FIXME: always unload to have our resources refreshed, this is highly // non-performant EList<Resource> resources = rSet.getResources(); for (Resource resource : resources) { resource.unload(); } IFolder folder = project.getFolder("src"); IFolder folderDiagrams = project.getFolder("src/diagrams"); Collection<Diagram> diagrams = new ArrayList<Diagram>(); Set<BaseElement> bpmnElements = new HashSet<BaseElement>(); if (folder.exists()) { List<IResource> membersList = new ArrayList<IResource>(); try { membersList.addAll(Arrays.asList(folder.members())); membersList.addAll(Arrays.asList(folderDiagrams.members())); } catch (CoreException e) { return new BaseElement[0]; } for (IResource resource : membersList) { if (resource instanceof IFile) { IFile file = (IFile) resource; if ("diagram".equals(file.getFileExtension()) || file.getName().equals("Predefined.data")) { // The following call extracts the diagram from the // given file. For the Tutorial diagrams always reside // in a file of their own and are the first root object. // This may of course be different in a concrete tool // implementation, so tool builders should use their own // way of retrieval here Diagram diag = org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal.getEmfService().getDiagramFromFile(file, rSet); if (diag != null) { diagrams.add(diag); } else { // The following call tries to retrieve a URI from // any of the found files to check if there are any // EClasses inside this file. Concrete tools should // use their own logic to browse through their files // (e.g. known by a special extension or residing in // a special folder) instead of this generic logic. URI uri = org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal.getEmfService().getFileURI(file, rSet); Resource fileResource = rSet.getResource(uri, true); if (fileResource != null) { EList<EObject> contents = fileResource.getContents(); for (EObject object : contents) { if (object instanceof BaseElement && !(object instanceof PictogramElement)) { bpmnElements.add((BaseElement) object); } } } } } } } } for (Diagram diagram : diagrams) { Resource resource = diagram.eResource(); if (resource == null) return new BaseElement[0]; EList<EObject> contents = resource.getContents(); for (EObject object : contents) { if (object instanceof BaseElement && !(object instanceof PictogramElement)) { bpmnElements.add((BaseElement) object); } } } return bpmnElements.toArray(new BaseElement[bpmnElements.size()]); } public static InputStream getContentStream(final Content content) { return Util.class.getClassLoader().getResourceAsStream(content.getContentPath()); } public enum Content { NEW_DIAGRAM_CONTENT("src/main/resources/content/new-diagram-content.xml"), NEW_SUBPROCESS_CONTENT("src/main/resources/content/new-subprocess-content.xml"); private final String contentPath; private Content(String contentPath) { this.contentPath = contentPath; } public String getContentPath() { return contentPath; } } /** * Gets the {@link URI} where the diagram resource for a subprocess should be * stored. * * @param diagram * the parent diagram for the subprocess * @param subprocessId * the id of the subprocess * @return the {@link URI} for the subprocess' resource */ public static final URI getSubProcessURI(Diagram diagram, String subprocessId) { final URI baseURI = diagram.eResource().getURI().trimFileExtension(); final URI subProcessURI = baseURI.appendFileExtension(subprocessId).appendFileExtension(diagram.eResource().getURI().fileExtension()); return subProcessURI; } /** * Replaces the document name in the provided contentStream's content and * returns a new stream containing the new content. * * @param diagramName * the name of the document to use * @param contentStream * the original content stream * @return */ public static InputStream swapStreamContents(final String diagramName, final InputStream contentStream) { InputStream result = null; try { Writer writer = new StringWriter(); char[] buffer = new char[1024]; try { Reader reader = new BufferedReader(new InputStreamReader(contentStream, "UTF-8")); int n; while ((n = reader.read(buffer)) != -1) { writer.write(buffer, 0, n); } } finally { contentStream.close(); } String contentString = writer.toString(); contentString = contentString.replace(DIAGRAM_NAME_DEFAULT, String.format(DIAGRAM_NAME_PATTERN, diagramName)); result = new ByteArrayInputStream(contentString.getBytes()); } catch (Exception e) { // TODO } return result; } }