sysmodelmgr/com.symbian.smt.gui/src/com/symbian/smt/gui/ChangeManager.java
changeset 0 522a326673b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysmodelmgr/com.symbian.smt.gui/src/com/symbian/smt/gui/ChangeManager.java	Thu Mar 11 19:08:43 2010 +0200
@@ -0,0 +1,353 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+package com.symbian.smt.gui;
+
+import java.io.File;
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+
+import com.symbian.smt.gui.editors.svgeditor.SVGEditor;
+
+public class ChangeManager {
+	static HashMap<String, Boolean> dirtyProjects = new HashMap<String, Boolean>();
+
+	private String checkModelNameExtension(final IProject project,
+			final IResource addedFile, String newOutputName) {
+		if (!newOutputName.endsWith(".svg")) {
+			final StringBuilder fullName = new StringBuilder();
+			fullName.append(newOutputName);
+			fullName.append(".svg");
+
+			newOutputName = fullName.toString();
+			final String outputName = fullName.toString();
+
+			// The file has the extension added and is moved to the new filename
+			WorkspaceJob wj = new WorkspaceJob("auto-rename") {
+				@Override
+				public IStatus runInWorkspace(IProgressMonitor monitor)
+						throws CoreException {
+					IPath newLocation = addedFile.getFullPath()
+							.addFileExtension("svg");
+					addedFile
+							.move(newLocation, true, new NullProgressMonitor());
+
+					project.getFile(outputName).setDerived(true);
+
+					return new Status(IStatus.OK, Activator.PLUGIN_ID,
+							IStatus.OK, "auto-rename succeeded", null);
+				}
+			};
+			wj.schedule();
+		}
+
+		return newOutputName;
+	}
+
+	private void checkPropertyChangeMarkers(final IProject project) {
+		try {
+			IMarker[] mMarkers = project.findMarkers(IMarker.MESSAGE, false, 0);
+
+			for (final IMarker aMarker : mMarkers) {
+				if (aMarker.getAttribute(IMarker.MESSAGE) != null) {
+					if (aMarker.getAttribute(IMarker.MESSAGE).equals(
+							"properties changed")) {
+						dirtyProjects.put(project.getName(), true);
+
+						try {
+							aMarker.delete();
+						} catch (CoreException e) {
+							// Do nothing, the markers are a bit unstable, an
+							// exception will only occur if the marker has
+							// already been deleted.
+						}
+					}
+				}
+			}
+		} catch (CoreException e) {
+			Logger.log(e.getMessage(), e);
+		}
+	}
+
+	public void closeEditor(final IFile oldProjectFile) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				IWorkbenchPage page = PlatformUI.getWorkbench()
+						.getActiveWorkbenchWindow().getActivePage();
+				IEditorPart oldEditor = page.findEditor(new FileEditorInput(
+						oldProjectFile));
+				page.closeEditor(oldEditor, false);
+			}
+		});
+	}
+
+	private IResourceDelta[] getAddedItems(IResourceDelta delta,
+			IProject project) {
+		IResourceDelta[] added = null;
+
+		if (delta.getFullPath().equals(Path.ROOT)) {
+			IResourceDelta[] children = delta
+					.getAffectedChildren(IResourceDelta.CHANGED);
+			for (IResourceDelta child : children) {
+				added = child.getAffectedChildren(IResourceDelta.ADDED);
+				break;
+			}
+		} else if (project.getFullPath().equals(delta.getFullPath())) {
+			added = delta.getAffectedChildren(IResourceDelta.ADDED);
+		}
+
+		return added;
+	}
+
+	private IResourceDelta[] getDeletedItems(IResourceDelta delta,
+			IProject project) {
+		IResourceDelta[] deleted = null;
+
+		if (delta.getFullPath().equals(Path.ROOT)) {
+			IResourceDelta[] children = delta
+					.getAffectedChildren(IResourceDelta.CHANGED);
+			for (IResourceDelta child : children) {
+				deleted = child.getAffectedChildren(IResourceDelta.REMOVED);
+				break;
+			}
+		} else if (project.getFullPath().equals(delta.getFullPath())) {
+			deleted = delta.getAffectedChildren(IResourceDelta.REMOVED);
+		}
+
+		return deleted;
+	}
+
+	private IPath getDeltaPath(IResourceDelta delta, IProject project) {
+		IPath deltaPath = null;
+
+		if (delta.getFullPath().equals(Path.ROOT)) {
+			IResourceDelta[] children = delta
+					.getAffectedChildren(IResourceDelta.CHANGED);
+			for (IResourceDelta child : children) {
+				deltaPath = child.getFullPath();
+				break;
+			}
+		} else if (project.getFullPath().equals(delta.getFullPath())) {
+			deltaPath = delta.getFullPath();
+		}
+
+		return deltaPath;
+	}
+
+	public void handleDelta(IResourceDelta delta, final IProject project) {
+		checkPropertyChangeMarkers(project);
+
+		if (delta != null) {
+			IScopeContext projectScope = new ProjectScope(project);
+			PersistentDataStore store = new PersistentDataStore(projectScope
+					.getNode(Activator.PLUGIN_ID));
+
+			// Check to see if the System Model diagram name has changed
+			checkPropertyChangeMarkers(project); // True means that name has
+													// changed
+
+			// Get the added and deleted items, we use these to work out what
+			// has happened
+			IResourceDelta[] deletedItems = getDeletedItems(delta, project);
+			IResourceDelta[] addedItems = getAddedItems(delta, project);
+
+			// If the diagram has been deleted but a new one hasn't been added
+			// then close the editor
+			if (addedItems != null & deletedItems != null
+					&& deletedItems.length == 1 && addedItems.length == 0) {
+				final String deletedfile = deletedItems[0].getFullPath()
+						.toString();
+				String outputName = store.getOutputFilename();
+				String resourceName = getDeltaPath(delta, project).append(
+						outputName).toString();
+
+				// Check that it was the system model diagram what was deleted,
+				// we are not interested in any other files
+				if (deletedfile.equals(resourceName)) {
+					IFile oldProjectFile = project.getFile(store
+							.getOutputFilename());
+					closeEditor(oldProjectFile);
+					dirtyProjects.put(project.getName(), true);
+				}
+			}
+
+			// Otherwise if the diagram has been deleted and a new one added
+			// then the diagram has been renamed
+			else if (addedItems != null & deletedItems != null
+					&& deletedItems.length == 1 && addedItems.length == 1) {
+				String outputName = store.getOutputFilename();
+
+				if (outputName == null) {
+					return;
+				}
+
+				final String deletedfile = deletedItems[0].getFullPath()
+						.toString();
+				final String addedfile = addedItems[0].getFullPath().toString();
+
+				String resourceName = getDeltaPath(delta, project).append(
+						outputName).toString();
+
+				if (addedfile.equals(resourceName)
+						|| deletedfile.equals(resourceName)) {
+					final String oldOutputName = new File(deletedfile)
+							.getName();
+
+					// Will add the .svg extension if required and also rename
+					// the file
+					final String newOutputName = checkModelNameExtension(
+							project, addedItems[0].getResource(), new File(
+									addedfile).getName());
+
+					// Update the project properties with the new model name
+					updatePropertiesWithModelName(store, resourceName,
+							deletedfile, newOutputName);
+
+					final IFile newProjectFile = project.getFile(newOutputName);
+
+					Boolean isDirty = false;
+
+					if (dirtyProjects.containsKey(project.getName())) {
+						isDirty = dirtyProjects.get(project.getName());
+					}
+
+					if (delta.getAffectedChildren(IResourceDelta.CHANGED).length <= 1
+							&& !isDirty) {
+						Display.getDefault().asyncExec(new Runnable() {
+
+							public void run() {
+								if (newProjectFile.exists()
+										&& !newProjectFile.isPhantom()) {
+									try {
+										IWorkbenchPage page = PlatformUI
+												.getWorkbench()
+												.getActiveWorkbenchWindow()
+												.getActivePage();
+										FileEditorInput editorInput = new FileEditorInput(
+												newProjectFile);
+
+										IEditorPart oldEditor = page
+												.findEditor(new FileEditorInput(
+														project
+																.getFile(oldOutputName)));
+										page.closeEditor(oldEditor, false);
+
+										page.openEditor(editorInput,
+												SVGEditor.ID);
+
+									} catch (PartInitException e) {
+										Logger.log(e.getMessage(), e);
+									}
+								}
+							}
+						});
+					}
+				}
+			} else { // Nothing has been deleted and nothing has been added - A
+						// file has been amended.
+				IResourceDelta[] children = delta
+						.getAffectedChildren(IResourceDelta.CHANGED);
+
+				for (IResourceDelta child : children) {
+					if (child.getResource() instanceof IFile) {
+						if (child.getResource().getFileExtension()
+								.equalsIgnoreCase("xml")) {
+							dirtyProjects.put(project.getName(), true);
+						}
+					} else if (child.getResource() instanceof IProject) {
+						if (child.getFlags() == IResourceDelta.OPEN) {
+							dirtyProjects.put(child.getResource().getName(),
+									true);
+						}
+					} else if (child.getResource() instanceof IFolder) {
+						IResourceDelta[] moreChildren = child
+								.getAffectedChildren(IResourceDelta.CHANGED);
+						for (IResourceDelta littlerChild : moreChildren) {
+							if (littlerChild.getResource().getFileExtension()
+									.equalsIgnoreCase("xml")) {
+								dirtyProjects.put(project.getName(), true);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public void remove(IProject project) {
+		if (dirtyProjects.containsKey(project.getName())) {
+			dirtyProjects.remove(project.getName());
+		}
+	}
+	
+	public boolean needsBuilding(IProject project) {
+		if (dirtyProjects.containsKey(project.getName())) {
+			return dirtyProjects.get(project.getName());
+		}
+
+		IScopeContext projectScope = new ProjectScope(project);
+		PersistentDataStore store = new PersistentDataStore(projectScope
+				.getNode(Activator.PLUGIN_ID));
+
+		if (!project.getFile(store.getOutputFilename()).exists()) {
+			return true;
+		}
+
+		return false;
+	}
+
+	public void reset(IProject project) {
+		dirtyProjects.put(project.getName(), false);
+	}
+
+	private void updatePropertiesWithModelName(final PersistentDataStore store,
+			final String resourceName, final String deletedfile,
+			final String outName) {
+		WorkspaceJob wj = new WorkspaceJob("updating properties") {
+			@Override
+			public IStatus runInWorkspace(IProgressMonitor monitor)
+					throws CoreException {
+				if (deletedfile.equals(resourceName)) {
+					store.setOutputFilename(outName);
+				}
+				return new Status(IStatus.OK, Activator.PLUGIN_ID, IStatus.OK,
+						"updating properties succeeded", null);
+			}
+		};
+		wj.schedule();
+	}
+}