| /*************************************************************************************************** |
| * Copyright (c) 2003, 2004 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 API and implementation |
| **************************************************************************************************/ |
| |
| package org.eclipse.jst.j2ee.internal.webservice.editmodel; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.EventObject; |
| import java.util.Hashtable; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.emf.common.command.BasicCommandStack; |
| import org.eclipse.emf.common.command.CommandStackListener; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jst.j2ee.internal.webservice.plugin.WebServicePlugin; |
| import org.eclipse.wst.common.internal.emf.resource.ReferencedResource; |
| |
| |
| public abstract class CompositeEditModel extends EditModel implements CommandStackListener { |
| |
| protected int fReferenceCount; |
| |
| protected Hashtable fEditModels; |
| protected Hashtable fResources; |
| protected Hashtable fRootObjects; |
| protected List fDescriptors; |
| |
| protected EditModelEvent dirtyModelEvent; |
| private List fListeners; |
| protected boolean isNotifing = false; |
| |
| public int getReferenceCount() { |
| return fReferenceCount; |
| } |
| |
| public boolean access() { |
| fReferenceCount++; |
| if (fReferenceCount == 1) { |
| //get all the registered edit models |
| IConfigurationElement[] elements = getExtensions(); |
| |
| //get a command stack |
| createCommandStack(); |
| |
| for (int i = 0; i < elements.length; i++) { |
| try { |
| Object editModelObject = elements[i].createExecutableExtension("class"); //$NON-NLS-1$ |
| if (editModelObject instanceof EditModel) { |
| //Setup the edit model and add it to the Hashtable |
| EditModel editModel = (EditModel) editModelObject; |
| String descriptorName = elements[i].getAttribute("descriptorName"); //$NON-NLS-1$ |
| editModel.setResourceSet(fResourceSet); |
| editModel.setProject(fProject); |
| editModel.setInputFile(fInputFile); |
| editModel.setCommandStack(fCommandStack); |
| editModel.setParent(this); |
| fEditModels.put(descriptorName, editModel); |
| //Get the resource from the editmodel and add it to the resource Hashtable |
| Resource res = editModel.getModelResource(descriptorName); |
| if (res == null) { |
| //Exit access() |
| return false; |
| } |
| //The webservices.xml and webservicesclient.xml do not load as |
| // ReferencedResources |
| //so, for the time being, we only do proper accessing on the xmi resources |
| // we load. |
| if (res instanceof ReferencedResource) |
| ((ReferencedResource) res).accessForWrite(); |
| //todo: process the resource upon load (i.e. accessForWrite(), etc) |
| fResources.put(descriptorName, res); |
| //Get the root object from the resource and add it to the Hashtable |
| EObject rootObject = editModel.getRootModelObject(descriptorName); |
| fRootObjects.put(descriptorName, rootObject); |
| fDescriptors.add(descriptorName); |
| |
| } |
| } catch (CoreException e) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| public abstract IConfigurationElement[] getExtensions(); |
| |
| public void release() { |
| fReferenceCount--; |
| if (fReferenceCount == 0) { |
| //release resources and dispose the edit model. |
| Resource resource; |
| int listsize = fDescriptors.size(); |
| for (int i = 0; i < listsize; i++) { |
| String descriptorName = (String) fDescriptors.get(i); |
| //release the resource |
| resource = getModelResource(descriptorName); |
| |
| //The webservices.xml and webservicesclient.xml do not load as ReferencedResources |
| //so, for the time being, we only do proper accessing on the xmi resources we load. |
| if (resource instanceof ReferencedResource) |
| ((ReferencedResource) resource).releaseFromWrite(); |
| else { |
| //this is a really bad but until we load ReferencedResources for |
| // webservices.xml and |
| //webservicesclient.xml we need to explicitly unload |
| //resource.unload(); |
| } |
| |
| //remove stored resources, root objects and edit models from Hashtables |
| fResources.remove(descriptorName); |
| fRootObjects.remove(descriptorName); |
| fEditModels.remove(descriptorName); |
| } |
| |
| fDescriptors = null; |
| fCommandStack = null; |
| dirtyModelEvent = null; |
| dispose(); |
| } |
| } |
| |
| protected abstract void dispose(); |
| |
| /** *************Getting resources and objects ******************* */ |
| public EditModel getEditModel(String descriptorName) { |
| EditModel em = (EditModel) fEditModels.get(descriptorName); |
| return em; |
| } |
| |
| public Resource getModelResource(String descriptorName) { |
| Resource res = (Resource) fResources.get(descriptorName); |
| return res; |
| } |
| |
| public EObject getRootModelObject(String descriptorName) { |
| EObject res = (EObject) fRootObjects.get(descriptorName); |
| return res; |
| } |
| |
| public abstract EObject getRootModelObject(); |
| |
| public abstract Resource getRootModelResource(); |
| |
| |
| /** *********Command Stack related methods*************************** */ |
| public BasicCommandStack createCommandStack() { |
| if (fCommandStack == null) { |
| fCommandStack = new BasicCommandStack(); |
| fCommandStack.addCommandStackListener(this); |
| } |
| return fCommandStack; |
| } |
| |
| public void commandStackChanged(EventObject event) { |
| if (dirtyModelEvent == null) |
| dirtyModelEvent = new EditModelEvent(EditModelEvent.DIRTY, this); |
| if (hasListeners()) |
| notifyListeners(dirtyModelEvent); |
| } |
| |
| protected List getListeners() { |
| if (fListeners == null) |
| fListeners = new ArrayList(); |
| return fListeners; |
| } |
| |
| /** |
| * Add |
| * |
| * @aListener to the list of listeners. |
| */ |
| public void addListener(EditModelListener aListener) { |
| if (aListener != null && !getListeners().contains(aListener)) |
| getListeners().add(aListener); |
| } |
| |
| /** |
| * Returns true if there are any listeners |
| */ |
| public boolean hasListeners() { |
| return !getListeners().isEmpty(); |
| } |
| |
| /** |
| * Notify listeners of |
| * |
| * @anEvent. |
| */ |
| protected void notifyListeners(EditModelEvent anEvent) { |
| if (fListeners == null) |
| return; |
| synchronized (this) { |
| isNotifing = true; |
| } |
| try { |
| List list = getListeners(); |
| for (int i = 0; i < list.size(); i++) |
| ((EditModelListener) list.get(i)).editModelChanged(anEvent); |
| } finally { |
| synchronized (this) { |
| isNotifing = false; |
| } |
| } |
| } |
| |
| /** *********Save related methods*************************** */ |
| public final void save(IProgressMonitor monitor) { |
| //getSaveHandler().access(); |
| try { |
| IWorkspaceRunnable runnable = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor aMonitor) { |
| primSave(aMonitor); |
| } |
| }; |
| runSaveOperation(runnable, monitor); |
| } catch (CoreException ex) { |
| //Pop up a dialog indicating that problems occurred during the save |
| MessageDialog.openError(null, WebServicePlugin.getMessage("%TITLE_SAVE_ERROR"), WebServicePlugin.getMessage("%MSG_SAVE_ERROR")); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| } |
| |
| private void runSaveOperation(IWorkspaceRunnable runnable, IProgressMonitor monitor) throws CoreException { |
| ResourcesPlugin.getWorkspace().run(runnable, monitor); |
| } |
| |
| |
| /** |
| * This will force all of the referenced Resources to be saved. |
| */ |
| public void primSave(IProgressMonitor monitor) { |
| Resource resource; |
| int listsize = fDescriptors.size(); |
| for (int i = 0; i < listsize; i++) { |
| String descriptorName = (String) fDescriptors.get(i); |
| resource = getModelResource(descriptorName); |
| if (resource.isModified()) { |
| try { |
| resource.save(Collections.EMPTY_MAP); |
| resource.setModified(false); |
| } catch (Exception e) { |
| //Ignore |
| } |
| } |
| } |
| |
| getCommandStack().saveIsDone(); |
| if (hasListeners()) { |
| EditModelEvent event = new EditModelEvent(EditModelEvent.SAVE, this); |
| notifyListeners(event); |
| } |
| } |
| |
| public boolean isDirty() { |
| Resource resource; |
| int listsize = fDescriptors.size(); |
| for (int i = 0; i < listsize; i++) { |
| String descriptorName = (String) fDescriptors.get(i); |
| resource = getModelResource(descriptorName); |
| if (resource.isModified()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| public void resourceChanged(EditModelEvent anEvent) { |
| if (hasListeners()) { |
| anEvent.setEditModel(this); |
| notifyListeners(anEvent); |
| } |
| } |
| |
| |
| protected void resourceIsLoadedChanged(Resource aResource, boolean oldValue, boolean newValue) { |
| //Do nothing for now |
| } |
| |
| |
| protected class ResourceAdapter extends AdapterImpl { |
| public void notifyChanged(Notification notification) { |
| if (notification.getEventType() == Notification.SET && notification.getFeatureID(null) == Resource.RESOURCE__IS_LOADED) { |
| resourceIsLoadedChanged((Resource) notification.getNotifier(), notification.getOldBooleanValue(), notification.getNewBooleanValue()); |
| } |
| } |
| } |
| |
| } |