blob: 454ec686bc66b4b23f13965d4d3fa81fd86674fd [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.CreateChildCommand;
import org.eclipse.emf.edit.command.PasteFromClipboardCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.epf.common.serviceability.DebugTrace;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.events.ILibraryChangeListener;
import org.eclipse.epf.library.layout.LayoutResources;
import org.eclipse.epf.library.persistence.ILibraryResourceSet;
import org.eclipse.epf.library.prefs.PreferenceConstants;
import org.eclipse.epf.library.project.MethodLibraryProject;
import org.eclipse.epf.library.services.LibraryModificationHelper;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.persistence.MultiFileXMISaveImpl;
import org.eclipse.epf.persistence.refresh.IRefreshEvent;
import org.eclipse.epf.persistence.refresh.IRefreshListener;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.util.LibrarySchedulingRule;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IPropertyListener;
/**
* The abstract Library Manager. Real implementation of ILibraryManager must
* subclass this.
*
* @author Phong Nguyen Le
* @author Kelvin Low
* @author Jinhua Xi
*
* @since 1.0
*/
public abstract class AbstractLibraryManager implements ILibraryManager {
public static final int PROP_DIRTY = 1;
/**
* The library name.
*/
public static final String ARG_LIBRARY_NAME = "library.name"; //$NON-NLS-1$
// If true, generate debug traces.
protected static boolean debug = LibraryPlugin.getDefault().isDebugging();
// The managed library.
protected MethodLibrary library;
// The default editing domain for the managed library.
protected AdapterFactoryEditingDomain editingDomain;
// A list of listeners that monitor changes to the managed library.
private List libraryChangedListeners = new ArrayList();
// A list of listeners that have been detached from the managed library.
private List detachedLibraryChangedListeners = new ArrayList();
// A list of listeners that monitor resource changes in the managed library.
private ListenerList resourceChangeListeners = new ListenerList();
// The save library options.
private Map saveOptions;
// If true, skip all event processing.
protected boolean skipEventProcessing = false;
// TODO: find a better way to notify the change in library instead of
// relying on the command stack listener
private CommandStackListener commandStackListener = new CommandStackListener() {
public void commandStackChanged(final EventObject event) {
if (debug) {
DebugTrace.print(this, "commandStackChanged", "event=" + event); //$NON-NLS-1$ //$NON-NLS-2$
}
if (!skipEventProcessing) {
SafeUpdateController.asyncExec(new Runnable() {
public void run() {
// Try to select the affected objects.
Command mostRecentCommand = LibraryUtil
.unwrap(((CommandStack) event.getSource())
.getMostRecentCommand());
if (mostRecentCommand != null) {
if (mostRecentCommand instanceof AddCommand) {
AddCommand cmd = (AddCommand) mostRecentCommand;
EObject owner = cmd.getOwner();
// need to send owner changed notification for
// all element types
//
// 156028 - Reference from WP and Guidence was
// not detected
// when deselect the related element from
// configuration
Collection objs = new ArrayList();
objs.add(owner);
notifyListeners(
ILibraryChangeListener.OPTION_CHANGED,
objs);
if (!(owner instanceof MethodConfiguration)) {
objs = mostRecentCommand.getResult();
notifyListeners(
ILibraryChangeListener.OPTION_NEWCHILD,
objs);
// Update the configuration selection if the
// object is a newly added method package.
if (owner instanceof MethodPackage) {
objs = LibraryUtil
.getContainedElements(owner,
objs);
if (!objs.isEmpty()) {
addNewPackagesToConfiguration(objs);
}
}
}
} else if (mostRecentCommand instanceof PasteFromClipboardCommand) {
Collection objs = mostRecentCommand.getResult();
notifyListeners(
ILibraryChangeListener.OPTION_NEWCHILD,
objs);
PasteFromClipboardCommand cmd = ((PasteFromClipboardCommand) mostRecentCommand);
// Update the configuration selection if the
// object is a newly added method package.
if (cmd.getOwner() instanceof MethodPackage) {
objs = LibraryUtil.getContainedElements(cmd
.getOwner(), objs);
if (!objs.isEmpty()) {
addNewPackagesToConfiguration(objs);
}
}
} else if (mostRecentCommand instanceof CreateChildCommand) {
notifyListeners(
ILibraryChangeListener.OPTION_NEWCHILD,
mostRecentCommand.getAffectedObjects());
} else if (mostRecentCommand != null) {
notifyListeners(
ILibraryChangeListener.OPTION_CHANGED,
mostRecentCommand.getAffectedObjects());
}
}
}
});
}
}
};
// Listen to changes to the managed method library.
private INotifyChangedListener notifyChangedListener = new INotifyChangedListener() {
public void notifyChanged(Notification notification) {
if (debug) {
DebugTrace.print(this,
"notifyChanged", "notification=" + notification); //$NON-NLS-1$ //$NON-NLS-2$
}
if (!skipEventProcessing) {
int eventType = notification.getEventType();
switch (eventType) {
case Notification.ADD: {
// A method element, typically a method plug-in, has been
// added to the managed library without using an editing
// command.
Object notifier = notification.getNotifier();
Object value = notification.getNewValue();
if ((notifier instanceof MethodLibrary)
&& (value instanceof MethodPlugin)) {
Collection affectedObjects = new ArrayList();
affectedObjects.add(value);
notifyListeners(ILibraryChangeListener.OPTION_NEWCHILD,
affectedObjects);
}
break;
}
case Notification.SET: {
Object notifier = notification.getNotifier();
if (notifier != null) {
Collection affectedObjects = new ArrayList();
affectedObjects.add(notifier);
notifyListeners(ILibraryChangeListener.OPTION_CHANGED,
affectedObjects);
}
break;
}
case Notification.REMOVE: {
// Either a method element has been removed from the
// containing element, or a method element reference has
// been deleted.
Object notifier = notification.getNotifier();
Object oldValue = notification.getOldValue();
Collection affectedObjects = new ArrayList();
if (oldValue instanceof EObject
&& ((EObject) oldValue).eContainer() == null) {
// A method element has been deleted.
affectedObjects.add(oldValue);
notifyListeners(ILibraryChangeListener.OPTION_DELETED,
affectedObjects);
} else {
// A method element reference has been deleted, notify
// the listeners that the containing method element has
// changed.
affectedObjects.add(notifier);
notifyListeners(ILibraryChangeListener.OPTION_CHANGED,
affectedObjects);
}
break;
}
case Notification.REMOVE_MANY: {
// Two or more method elements have been removed from
// the containing element, or tw or more method element
// reference have been deleted.
List oldValue = new ArrayList((Collection) notification
.getOldValue());
ArrayList deletedElements = new ArrayList();
ArrayList removedReferences = new ArrayList();
if (!oldValue.isEmpty()) {
for (Iterator iter = oldValue.iterator(); iter
.hasNext();) {
Object element = iter.next();
if (element instanceof EObject) {
if (((EObject) element).eContainer() == null) {
deletedElements.add(element);
} else {
removedReferences.add(element);
}
}
}
}
if (!deletedElements.isEmpty()) {
// Two or more method elements have been deleted.
notifyListeners(ILibraryChangeListener.OPTION_DELETED,
deletedElements);
}
if (!removedReferences.isEmpty()) {
// Two or more method element reference has been
// deleted.
notifyListeners(ILibraryChangeListener.OPTION_CHANGED,
removedReferences);
}
break;
}
}
}
}
};
// Listen to managed method library resource changes.
private Adapter resourceChangedListener = new AdapterImpl() {
public void notifyChanged(Notification msg) {
if (debug) {
DebugTrace.print(this, "notifyChanged", "msg=" + msg); //$NON-NLS-1$ //$NON-NLS-2$
}
if (msg.getFeatureID(null) == Resource.RESOURCE__IS_MODIFIED
&& msg.getEventType() == org.eclipse.emf.common.notify.Notification.SET) {
firePropertyChange(msg.getNotifier(), PROP_DIRTY);
}
}
};
// Listen to persistence refresh events.
private IRefreshListener refreshListener = new IRefreshListener() {
public void notifyRefreshed(IRefreshEvent event) {
if (debug) {
DebugTrace.print(this, "notifyRefreshed", "event=" + event); //$NON-NLS-1$ //$NON-NLS-2$
}
handleRefreshEvent(event);
}
};
// Listen to preference store changes.
private IPropertyChangeListener preferenceStoreChangeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(
PreferenceConstants.PREF_BACK_UP_BEFORE_SAVE)) {
saveOptions.put(MultiFileXMISaveImpl.BACK_UP_BEFORE_SAVE, event
.getNewValue());
} else if (event.getProperty().equals(
PreferenceConstants.PREF_DISCARD_UNRESOLVED_REFERENCES)) {
saveOptions.put(
MultiFileXMISaveImpl.DISCARD_UNRESOLVED_REFERENCES,
event.getNewValue());
}
}
};
/**
* Creates a new instance.
*/
public AbstractLibraryManager() {
init();
}
/**
* Performs the necessary initialization.
*/
protected void init() {
if (debug) {
DebugTrace.print(this, "init"); //$NON-NLS-1$
}
LibraryPlugin.getDefault().getPreferenceStore()
.addPropertyChangeListener(preferenceStoreChangeListener);
// Create the adapter factory.
List factories = new ArrayList();
factories.add(new ResourceItemProviderAdapterFactory());
factories.add(new ReflectiveItemProviderAdapterFactory());
ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
factories);
// Create the command stack.
BasicCommandStack commandStack = new BasicCommandStack();
// Create the resource set.
ILibraryResourceSet resourceSet = createResourceSet();
resourceSet.addRefreshListener(refreshListener);
RefreshJob.getInstance().setResourceSet(resourceSet);
// Initialize the library save options.
saveOptions = resourceSet.getDefaultSaveOptions();
boolean b = LibraryPlugin.getDefault().getPreferenceStore().getBoolean(
PreferenceConstants.PREF_BACK_UP_BEFORE_SAVE);
saveOptions.put(MultiFileXMISaveImpl.BACK_UP_BEFORE_SAVE, Boolean
.valueOf(b));
b = LibraryPlugin.getDefault().getPreferenceStore().getBoolean(
PreferenceConstants.PREF_DISCARD_UNRESOLVED_REFERENCES);
saveOptions.put(MultiFileXMISaveImpl.DISCARD_UNRESOLVED_REFERENCES,
Boolean.valueOf(b));
// Create the editing domain.
editingDomain = new AdapterFactoryEditingDomain(adapterFactory,
commandStack, resourceSet);
// Register the editing domain.
registerEditingDomain(editingDomain);
}
/**
* Saves the managed method library.
*
* @throw <code>LibraryServiceException</code> if an error occurs while
* performing the operation
*/
public void saveMethodLibrary() throws LibraryServiceException {
if (debug) {
DebugTrace.print(this, "saveMethodLibrary"); //$NON-NLS-1$
}
try {
if (library != null) {
skipEventProcessing = true;
ILibraryResourceSet resourceSet = ((ILibraryResourceSet) editingDomain
.getResourceSet());
resourceSet.save(saveOptions);
((BasicCommandStack) editingDomain.getCommandStack())
.saveIsDone();
skipEventProcessing = false;
firePropertyChange(library, PROP_DIRTY);
}
} catch (Exception e) {
throw new LibraryServiceException(e);
} finally {
skipEventProcessing = false;
}
}
/**
* Discards all changes made to the managed method library.
*/
public void discardMethodLibraryChanges() {
if (debug) {
DebugTrace.print(this, "discardMethodLibraryChanges"); //$NON-NLS-1$
}
for (Iterator it = getEditingDomain().getResourceSet().getResources()
.iterator(); it.hasNext();) {
Resource resource = (Resource) it.next();
resource.setModified(false);
}
}
/**
* Closes the managed method library.
*
* @return a method library
* @throw <code>LibraryServiceException</code> if an error occurs while
* performing the operation
*/
public void closeMethodLibrary() throws LibraryServiceException {
if (debug) {
String msg = "library=" + library + ", memory on entry=" //$NON-NLS-1$ //$NON-NLS-2$
+ (Runtime.getRuntime().totalMemory() - Runtime
.getRuntime().freeMemory());
DebugTrace.print(this, "closeMethodLibrary", msg); //$NON-NLS-1$
}
//String libPath = LibraryService.getInstance()
// .getCurrentMethodLibraryPath();
File libFile = new File(library.eResource().getURI().toFileString());
String libPath = libFile.getParentFile().getAbsolutePath();
// remove the configuration managers associated with this library
LibraryService.getInstance().removeConfigurationManagers(library);
removeResourceChangedListeners();
// Clear the temp layout resources.
LayoutResources.clear();
ILibraryResourceSet resourceSet = (ILibraryResourceSet) editingDomain
.getResourceSet();
resourceSet.unload();
// Unlocks the method library.
unlockMethodLibrary();
try {
// Close the method library project file.
MethodLibraryProject.closeProject(libPath, null);
} catch (Exception e) {
throw new LibraryServiceException(e);
}
RefreshJob.getInstance().reset();
// Activates the garbage collector.
Runtime.getRuntime().gc();
if (debug) {
String msg = "library=" + library + ", memory on exit=" //$NON-NLS-1$ //$NON-NLS-2$
+ (Runtime.getRuntime().totalMemory() - Runtime
.getRuntime().freeMemory());
DebugTrace.print(this, "closeMethodLibrary", msg); //$NON-NLS-1$
}
}
/**
* Gets the managed method library.
*
* @return a method library
*/
public MethodLibrary getMethodLibrary() {
if (debug) {
DebugTrace.print(this, "getMethodLibrary", "library=" + library); //$NON-NLS-1$ //$NON-NLS-2$
}
return library;
}
/**
* Sets the managed method library.
*
* @param library
* a method library
*/
public void setMethodLibrary(MethodLibrary library) {
if (debug) {
DebugTrace.print(this, "setMethodLibrary", "library=" + library); //$NON-NLS-1$ //$NON-NLS-2$
}
if (this.library != null) {
Resource resource = (Resource) this.library.eResource();
if (resource != null) {
resource.getContents().clear();
resource.getContents().add(library);
}
}
this.library = library;
}
/**
* Gets the adapter factory for the managed method library.
*
* @return an adapter factory
*/
public ComposedAdapterFactory getAdapterFactory() {
if (debug) {
DebugTrace.print(this, "getAdapterFactory"); //$NON-NLS-1$
}
return (ComposedAdapterFactory) getEditingDomain().getAdapterFactory();
}
/**
* Gets the editing domain for the managed method library.
*
* @return an editing domain
*/
public AdapterFactoryEditingDomain getEditingDomain() {
if (debug) {
DebugTrace.print(this,
"getEditingDomain", "editingDomain=" + editingDomain); //$NON-NLS-1$ //$NON-NLS-2$
}
return editingDomain;
}
/**
* Registers an editing domain with the managed method library.
*
* @param domain
* an editing domain
*/
public void registerEditingDomain(AdapterFactoryEditingDomain domain) {
if (debug) {
DebugTrace.print(this, "registerEditingDomain", "domain=" + domain); //$NON-NLS-1$ //$NON-NLS-2$
}
// Add a listener to monitor library changes made in the given editing
// domain.
((ComposedAdapterFactory) domain.getAdapterFactory())
.addListener(notifyChangedListener);
// Add a listener to monitor changes made to the command stack.
// This is used to select the most recently affected objects in the
// viewer.
domain.getCommandStack().addCommandStackListener(commandStackListener);
}
/**
* Adds a listener to monitor changes to the managed method library.
*
* @param listener
* a library change listener
*/
public void addListener(ILibraryChangeListener listener) {
synchronized (libraryChangedListeners) {
if (debug) {
DebugTrace.print(this, "addListener", "listener=" + listener); //$NON-NLS-1$ //$NON-NLS-2$
}
if (!libraryChangedListeners.contains(listener)) {
libraryChangedListeners.add(listener);
}
}
}
/**
* Removes a listener that was added to monitor changes to the managed
* method library.
*
* @param listener
* a library change listener
*/
public void removeListener(ILibraryChangeListener listener) {
synchronized (detachedLibraryChangedListeners) {
if (debug) {
DebugTrace
.print(this, "removeListener", "listener=" + listener);
}
// Cache the listener and remove it just before dispatching the
// library changed events.
if (!detachedLibraryChangedListeners.contains(listener)) {
detachedLibraryChangedListeners.add(listener);
}
}
}
/**
* Adds a listener to monitor resource changes in the managed method
* library.
*
* @param listener
* a property change listener
*/
public void addPropertyListener(IPropertyListener listener) {
if (debug) {
DebugTrace.print(this,
"addPropertyListener", "listener=" + listener); //$NON-NLS-1$ //$NON-NLS-2$
}
resourceChangeListeners.add(listener);
}
/**
* Removes a listener that was added to monitor resource changes in the
* managed method library.
*
* @param listener
* a property change listener
*/
public void removePropertyListener(IPropertyListener listener) {
if (debug) {
DebugTrace.print(this,
"removePropertyListener", "listener=" + listener); //$NON-NLS-1$ //$NON-NLS-2$
}
resourceChangeListeners.remove(listener);
}
/**
* Starts listening to command processing on a command stack.
*
* @param commandStack
* a command stack
*/
public void startListeningTo(CommandStack commandStack) {
if (debug) {
DebugTrace.print(this,
"startListeningTo", "commandStack=" + commandStack); //$NON-NLS-1$ //$NON-NLS-2$
}
commandStack.addCommandStackListener(commandStackListener);
}
/**
* Stops listening to command processing on a command stack.
*
* @param commandStack
* a command stack
*/
public void stopListeningTo(CommandStack commandStack) {
if (debug) {
DebugTrace.print(this,
"stopListeningTo", "commandStack=" + commandStack); //$NON-NLS-1$ //$NON-NLS-2$
}
commandStack.removeCommandStackListener(commandStackListener);
}
/**
* Starts listening to change notifications sent from an adapter factory.
*
* @param adapterFactory
* an adapter factory
*/
public void startListeningTo(ComposedAdapterFactory adapterFactory) {
if (debug) {
DebugTrace.print(this,
"startListeningTo", "adapterFactory=" + adapterFactory); //$NON-NLS-1$ //$NON-NLS-2$
}
adapterFactory.addListener(notifyChangedListener);
}
/**
* Stops listening to change notifications sent from an adapter factory.
*
* @param adapterFactory
* an adapter factory
*/
public void stopListeningTo(ComposedAdapterFactory adapterFactory) {
if (debug) {
DebugTrace.print(this,
"stopListeningTo", "adapterFactory=" + adapterFactory); //$NON-NLS-1$ //$NON-NLS-2$
}
adapterFactory.removeListener(notifyChangedListener);
}
/**
* Gets a method element from the managed method library.
*
* @param guid
* the method element's GUID.
*
* @return a method element of <code>null</code>
*/
public MethodElement getMethodElement(String guid) {
if (debug) {
DebugTrace.print(this, "getMethodElement", "guid=" + guid); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
ILibraryResourceSet resourceSet = (ILibraryResourceSet) library
.eResource().getResourceSet();
if (resourceSet != null) {
return (MethodElement) resourceSet.getEObject(guid);
}
} catch (Throwable th) {
}
return null;
}
/**
* Gets the relative URI of a method element in the managed method library.
*
* @param element
* a method element
* @return a relative URI
*/
public URI getElementRelativeURI(MethodElement element) {
if (debug) {
DebugTrace.print(this,
"getElementRelativeURI", "element=" + element); //$NON-NLS-1$ //$NON-NLS-2$
}
if (element != null) {
Resource resource = library.eResource();
if (resource != null) {
URI libraryURI = resource.getURI();
URI elementURI = element.eResource().getURI();
return elementURI.deresolve(libraryURI);
}
}
return null;
}
/**
* Checks whether the managed method library is read only.
*
* @return <code>true</code> if the method library is read only
*/
public boolean isMethodLibraryReadOnly() {
if (debug) {
DebugTrace.print(this, "isMethodLibraryReadOnly"); //$NON-NLS-1$
}
URI libraryURI = library.eResource().getURI();
if(libraryURI.isFile()) {
File libraryXMIFile = new File(libraryURI.toFileString());
return libraryXMIFile.exists() && !libraryXMIFile.canWrite();
}
return false;
}
/**
* Checks whether the managed method library content has been modified.
*
* @return <code>true</code> if the managed method library content has
* been modified
*/
public boolean isMethodLibraryModified() {
if (debug) {
DebugTrace.print(this, "isMethodLibraryModified"); //$NON-NLS-1$
}
for (Iterator it = getEditingDomain().getResourceSet().getResources()
.iterator(); it.hasNext();) {
Resource resource = (Resource) it.next();
if (resource.isModified()) {
return true;
}
}
return false;
}
/**
* Checks whether the managed method library has any unresolved proxy.
*
* @return <code>true</code> if the managed method library has an
* unresolved proxy.
*/
public boolean hasUnresolvedProxy() {
if (debug) {
DebugTrace.print(this, "hasUnresolvedProxy"); //$NON-NLS-1$
}
ILibraryResourceSet resourceSet = ((ILibraryResourceSet) editingDomain
.getResourceSet());
return resourceSet.hasUnresolvedProxy();
}
/**
* Reloads the given resources.
*
* @param resources
* a collection of resources
* @return a collection of resources that have reloaded
*/
public Collection reloadResources(final Collection resources) {
if (debug) {
System.out
.println("AbstractLibraryManager.reloadResources(): START"); //$NON-NLS-1$
}
try {
final ArrayList reloadedResources = new ArrayList();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
reloadedResources.addAll(doReloadResources(resources));
}
};
try {
ResourcesPlugin.getWorkspace().run(runnable,
new LibrarySchedulingRule(library),
IWorkspace.AVOID_UPDATE, new NullProgressMonitor());
} catch (Exception e) {
LibraryPlugin.getDefault().getLogger().logError(e);
}
return reloadedResources;
} finally {
if (debug) {
System.out
.println("AbstractLibraryManager.doReloadResources(): END"); //$NON-NLS-1$
}
}
}
private Collection doReloadResources(Collection resources) {
if (debug) {
DebugTrace.print(this, "reloadResources"); //$NON-NLS-1$
}
if (library == null) {
return Collections.EMPTY_LIST;
}
// check if resources to reload contains any elements cached in
// LibraryService
// to update them
//
LibraryService libSvc = (LibraryService) LibraryService.getInstance();
Resource currentLibResource = null;
ILibraryManager currentLibMgr = null;
Resource currentConfigResource = null;
MethodConfiguration currentConfig = null;
List configResources = new ArrayList();
List configs = new ArrayList();
for (Iterator iter = resources.iterator(); iter.hasNext();) {
Resource resource = (Resource) iter.next();
MethodElement e = PersistenceUtil.getMethodElement(resource);
if (e == libSvc.getCurrentMethodLibrary()) {
currentLibMgr = libSvc.getCurrentLibraryManager();
currentLibResource = resource;
} else if (e == libSvc.getCurrentMethodConfiguration()) {
currentConfigResource = resource;
currentConfig = libSvc.getCurrentMethodConfiguration();
} else if (e instanceof MethodConfiguration) {
configResources.add(resource);
configs.add(e);
}
}
ILibraryResourceSet resourceSet = (ILibraryResourceSet) library
.eResource().getResourceSet();
Collection reloadedResources = resourceSet.reloadResources(resources);
if (!reloadedResources.isEmpty()) {
if (currentLibResource != null || currentConfigResource != null) {
// update cached elements in LibraryService and this library
// manager
//
for (Iterator iter = reloadedResources.iterator(); iter
.hasNext();) {
Resource resource = (Resource) iter.next();
if (resource == currentLibResource) {
MethodElement e = PersistenceUtil
.getMethodElement(resource);
if (e instanceof MethodLibrary) {
MethodLibrary newLib = (MethodLibrary) e;
libSvc.setCurrentMethodLibrary(newLib);
if (currentLibMgr instanceof AbstractLibraryManager) {
libSvc.removeLibraryManager(currentLibMgr);
((AbstractLibraryManager) currentLibMgr)
.updateMethodLibrary(newLib);
libSvc.setLibraryManager(currentLibMgr);
}
}
}
if (resource == currentConfigResource) {
MethodElement e = PersistenceUtil
.getMethodElement(resource);
if (e instanceof MethodConfiguration) {
// remove config manager of old current config
//
libSvc.removeConfigurationManager(currentConfig);
MethodConfiguration config = (MethodConfiguration) e;
libSvc.setCurrentMethodConfiguration(config);
}
} else if (!configResources.isEmpty()) {
int id = configResources.indexOf(resource);
if (id != -1) {
// remove config manager of old config
//
libSvc
.removeConfigurationManager((MethodConfiguration) configs
.get(id));
}
}
}
}
// TODO: Review implementation.
Suppression.cleanUp();
}
return reloadedResources;
}
/**
* @param newLib
*/
private void updateMethodLibrary(MethodLibrary newLib) {
library = newLib;
}
/**
* Gets the options used for saving the managed method library.
*
* @return a map of method library specific save options
*/
public Map getSaveOptions() {
if (debug) {
DebugTrace.print(this, "getSaveOptions"); //$NON-NLS-1$
}
return saveOptions;
}
/**
* Adds a new method plug-in to the managed method library.
*
* @param plugin
* a method plug-in
* @throw <code>LibraryServiceException</code> if an error occurs while
* performing the operation
*/
public void addMethodPlugin(final MethodPlugin plugin)
throws LibraryServiceException {
if (debug) {
DebugTrace.print(this, "addMethodPlugin", "plugin=" + plugin); //$NON-NLS-1$ //$NON-NLS-2$
}
// This operation will cause an UI update. It must be executed in
// the main UI to aoid an Invalid Thread Access exception.
final Exception[] exceptions = new Exception[1];
try {
SafeUpdateController.syncExec(new Runnable() {
public void run() {
library.getMethodPlugins().add(plugin);
ILibraryPersister.FailSafeMethodLibraryPersister persister = Services
.getLibraryPersister(getLibraryPersisterType()).getFailSafePersister();
try {
persister.save(library.eResource());
persister.commit();
} catch (Exception e) {
persister.rollback();
exceptions[0] = e;
return;
}
plugin.eResource().eAdapters().add(resourceChangedListener);
}
});
} catch (Exception e) {
throw new LibraryServiceException(e);
}
if (exceptions[0] != null) {
throw new LibraryServiceException(exceptions[0]);
}
}
/**
* Disposes all resources allocated by this library manager.
*/
public void dispose() {
if (preferenceStoreChangeListener != null) {
LibraryPlugin
.getDefault()
.getPreferenceStore()
.removePropertyChangeListener(preferenceStoreChangeListener);
}
if (libraryChangedListeners.size() > 0) {
libraryChangedListeners.clear();
}
if (detachedLibraryChangedListeners.size() > 0) {
detachedLibraryChangedListeners.clear();
}
if (resourceChangeListeners.size() > 0) {
resourceChangeListeners.clear();
}
editingDomain = null;
library = null;
}
/**
* Checks the arguments used for creating a new method element.
*
* @param containingElement
* the parent/containing method element
* @param name
* a name for the new method element
* @throw <code>LibraryServiceException</code> if an error occurs while
* performing the operation.
*/
protected void checkElementCreationArguments(
MethodElement containingElement, String name)
throws LibraryServiceException {
if (containingElement == null) {
throw new IllegalArgumentException();
}
if (name == null || name.length() == 0) {
throw new InvalidMethodElementNameException();
}
// TODO: Check for illegal characters.
}
/**
* Handles a persistence refresh event.
*
* @param event
* a refresh event
*/
protected void handleRefreshEvent(IRefreshEvent event) {
if (debug) {
DebugTrace.print(this, "handleRefreshEvent", "refreshedResources=" //$NON-NLS-1$ //$NON-NLS-2$
+ event.getRefreshedResources());
}
if (!event.getUnloadedObjects().isEmpty()) {
TngAdapterFactory.INSTANCE.cleanUp();
}
}
/**
* Notifies all library changed listeners attached to the managed library.
*
* @param type
* the type of change that has occurred
* @param changedElements
* a collection of method elements that have changed
*/
protected synchronized void notifyListeners(final int option,
final Collection collection) {
if (debug) {
DebugTrace.print(this, "notifyListeners", "option=" + option); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
// Remove the changed listeners that have been dettached.
if (detachedLibraryChangedListeners.size() > 0) {
for (Iterator it = detachedLibraryChangedListeners.iterator(); it
.hasNext();) {
Object l = it.next();
if (libraryChangedListeners.contains(l)) {
libraryChangedListeners.remove(l);
}
}
detachedLibraryChangedListeners.clear();
}
// Notify the changed listeners.
// Note: more changed listeners may be added while each listener is
// being notified. However,
// they will be added to the end of the list which does no harm.
int i = 0;
while (i < libraryChangedListeners.size()) {
final ILibraryChangeListener listener = (ILibraryChangeListener) libraryChangedListeners
.get(i);
if (listener != null) {
// Since this may trigger an update to the UI, the
// notification must be executed in the UI thread to avoid
// getting an Invalid Thread Access exception. The
// notification must also be executed in sync mode to
// gurantee delivery of the event before a listener is
// disposed.
SafeUpdateController.syncExec(new Runnable() {
public void run() {
if (debug) {
DebugTrace
.print(
this,
"notifyListeners", "listener=" + listener); //$NON-NLS-1$ //$NON-NLS-2$
}
listener.libraryChanged(option, collection);
}
});
}
i++;
}
} catch (Exception e) {
if (debug) {
DebugTrace.print(this, "notifyListeners", e); //$NON-NLS-1$
}
}
}
/**
* Fires a property changed event.
*
* @param propertyId
* the id of the changed property
*/
protected void firePropertyChange(final Object source, final int propertyId) {
if (debug) {
DebugTrace.print(this, "firePropertyChange", "source=" + source); //$NON-NLS-1$ //$NON-NLS-2$
}
Object[] array = resourceChangeListeners.getListeners();
for (int i = 0; i < array.length; i++) {
final IPropertyListener listener = (IPropertyListener) array[i];
// This operation will cause an UI update. It must be executed in
// the main UI to aoid an Invalid Thread Access exception.
SafeUpdateController.asyncExec(new Runnable() {
public void run() {
if (debug) {
DebugTrace.print(this,
"firePropertyChange", "listener=" + listener); //$NON-NLS-1$ //$NON-NLS-2$
}
listener.propertyChanged(source, propertyId);
}
});
}
}
/**
* Adds a resource changed listener to the managed method library resources.
*/
protected void addResourceChangedListeners() {
if (library == null || library.eResource() == null) {
return;
}
if (!library.eResource().eAdapters().contains(resourceChangedListener)) {
library.eResource().eAdapters().add(resourceChangedListener);
}
for (Iterator it = library.getMethodPlugins().iterator(); it.hasNext();) {
MethodPlugin plugin = (MethodPlugin) it.next();
if (!plugin.eResource().eAdapters().contains(
resourceChangedListener)) {
plugin.eResource().eAdapters().add(resourceChangedListener);
}
}
for (Iterator it = library.getPredefinedConfigurations().iterator(); it
.hasNext();) {
MethodConfiguration config = (MethodConfiguration) it.next();
if (!config.eResource().eAdapters().contains(
resourceChangedListener)) {
config.eResource().eAdapters().add(resourceChangedListener);
}
}
}
/**
* Removes the resource changed listener to the managed method library
* resource and method plug-ins.
*/
protected void removeResourceChangedListeners() {
if (library == null || library.eResource() == null) {
return;
}
library.eResource().eAdapters().remove(resourceChangedListener);
for (Iterator iter = library.getMethodPlugins().iterator(); iter
.hasNext();) {
MethodPlugin plugin = (MethodPlugin) iter.next();
plugin.eResource().eAdapters().remove(resourceChangedListener);
}
for (Iterator it = library.getPredefinedConfigurations().iterator(); it
.hasNext();) {
MethodConfiguration config = (MethodConfiguration) it.next();
config.eResource().eAdapters().remove(resourceChangedListener);
}
}
/**
* Gets the managed method library resource.
*
* @return a method library resource.
*/
protected Resource getMethodLibraryResource() {
List res = getEditingDomain().getResourceSet().getResources();
if (res.size() > 0) {
return (Resource) res.get(0);
}
return null;
}
/**
* Gets the URI of the managed method library.
*
* @return a <code>java.net.URI</code>
*/
public java.net.URI getMethodLibraryURI() {
Resource savedResource = getMethodLibraryResource();
if (savedResource != null) {
URI resourceURI = savedResource.getURI();
try {
File file = new File(resourceURI.toFileString());
return file.getParentFile().toURI();
} catch (Exception e) {
LibraryPlugin.getDefault().getLogger().logError(e);
}
}
return null;
}
/**
* Adds the new packages into the configurations if the parent is in the
* configuration.
*/
private void addNewPackagesToConfiguration(Collection newobjs) {
if (newobjs == null || newobjs.size() == 0) {
return;
}
LibraryModificationHelper helper = new LibraryModificationHelper();
try {
EObject e, parent;
for (Iterator it = newobjs.iterator(); it.hasNext();) {
e = (EObject) it.next();
if ((e instanceof MethodPackage)
&& ((parent = e.eContainer()) != null)
&& (parent instanceof MethodPackage)) {
Object configs = ((MultiResourceEObject) parent)
.getOppositeFeatureValue(AssociationHelper.MethodPackage_MethodConfigurations);
if (configs instanceof List) {
for (Iterator itconfig = ((List) configs).iterator(); itconfig
.hasNext();) {
MethodConfiguration config = (MethodConfiguration) itconfig
.next();
List pkgs = config.getMethodPackageSelection();
if (!pkgs.contains(e)) {
// pkgs.add(e);
helper
.getActionManager()
.doAction(
IActionManager.ADD,
config,
UmaPackage.eINSTANCE
.getMethodConfiguration_MethodPackageSelection(),
e, -1);
}
}
}
}
}
helper.save();
} catch (RuntimeException e) {
LibraryPlugin.getDefault().getLogger().logError(e);
} finally {
helper.dispose();
}
}
protected abstract void unlockMethodLibrary();
/**
* Gets the type of library persister to be used in this library manager
*
* @return the library persister type
* @see Services#XMI_PERSISTENCE_TYPE
*/
protected abstract String getLibraryPersisterType();
protected abstract ILibraryResourceSet createResourceSet();
}