| //------------------------------------------------------------------------------ |
| // 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(); |
| } |