diff options
author | nitind | 2005-12-07 15:48:05 +0000 |
---|---|---|
committer | nitind | 2005-12-07 15:48:05 +0000 |
commit | 6c927f34b0ac0f4df3deba4a0bfce999ff0ffa98 (patch) | |
tree | c9c0f8abd45f04685431f8f395ee85e8d7457707 /bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java | |
parent | 5160d934b842281b43e7cd8b8fa237dc606d22f8 (diff) | |
download | webtools.sourceediting-20051207_1050.tar.gz webtools.sourceediting-20051207_1050.tar.xz webtools.sourceediting-20051207_1050.zip |
This commit was manufactured by cvs2svn to create tag 'v20051207_1050'.v20051207_1050
Diffstat (limited to 'bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java')
-rw-r--r-- | bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java | 1591 |
1 files changed, 0 insertions, 1591 deletions
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java deleted file mode 100644 index 99afd4fdce..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java +++ /dev/null @@ -1,1591 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.model; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.jobs.ILock; -import org.eclipse.wst.sse.core.internal.ILockable; -import org.eclipse.wst.sse.core.internal.Logger; -import org.eclipse.wst.sse.core.internal.SSECoreMessages; -import org.eclipse.wst.sse.core.internal.encoding.EncodingRule; -import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler; -import org.eclipse.wst.sse.core.internal.provisional.DocumentChanged; -import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.events.AboutToBeChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener; -import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener; -import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager; -import org.eclipse.wst.sse.core.internal.util.URIResolver; -import org.eclipse.wst.sse.core.internal.util.Utilities; - - -public abstract class AbstractStructuredModel implements IStructuredModel { - - private static final String MODEL_MANAGER_NULL = "Warning: AbstractStructuredModel::close: model manager was null during a close of a model (which should be impossible)"; //$NON-NLS-1$ - - class DirtyStateWatcher implements IStructuredDocumentListener { - - public void newModel(NewDocumentEvent structuredDocumentEvent) { - - // I don't think its safe to assume a new model - // is always "fresh", so we'll leave dirty state - // unchanged; - // but we'll tell everyone about it. - setDirtyState(fDirtyState); - } - - public void noChange(NoChangeEvent structuredDocumentEvent) { - - // don't change dirty state - } - - public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) { - - setDirtyState(true); - // no need to listen any more - if (fStructuredDocument != null) { - fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher); - } - } - - public void regionChanged(RegionChangedEvent structuredDocumentEvent) { - - setDirtyState(true); - // no need to listen any more - if (fStructuredDocument != null) { - fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher); - } - } - - public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) { - - setDirtyState(true); - // no need to listen any more - if (fStructuredDocument != null) { - fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher); - } - } - } - - class DocumentToModelNotifier implements IStructuredDocumentListener, IModelAboutToBeChangedListener { - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.events.AboutToBeChangedEvent) - */ - public void modelAboutToBeChanged(AboutToBeChangedEvent structuredDocumentEvent) { - // If we didn't originate the change, take note we are about to - // change based on our underlying document changing. - // If we did originate the change, we, or client, should have - // already called aboutToChangeModel. - if (structuredDocumentEvent.getOriginalRequester() != this) { - aboutToChangeModel(); - } - - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#newModel(org.eclipse.wst.sse.core.events.NewDocumentEvent) - */ - public void newModel(NewDocumentEvent structuredDocumentEvent) { - // if we didn't originate the change, take note we have changed - if (structuredDocumentEvent.getOriginalRequester() != this) { - changedModel(); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#noChange(org.eclipse.wst.sse.core.events.NoChangeEvent) - */ - public void noChange(NoChangeEvent structuredDocumentEvent) { - // if we didn't originate the change, take note we have changed - if (structuredDocumentEvent.getOriginalRequester() != this) { - changedModel(); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#nodesReplaced(org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent) - */ - public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) { - // if we didn't originate the change, take note we have changed - if (structuredDocumentEvent.getOriginalRequester() != this) { - changedModel(); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionChanged(org.eclipse.wst.sse.core.events.RegionChangedEvent) - */ - public void regionChanged(RegionChangedEvent structuredDocumentEvent) { - // if we didn't originate the change, take note we have changed - if (structuredDocumentEvent.getOriginalRequester() != this) { - changedModel(); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionsReplaced(org.eclipse.wst.sse.core.events.RegionsReplacedEvent) - */ - public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) { - // if we didn't originate the change, take note we have changed - if (structuredDocumentEvent.getOriginalRequester() != this) { - changedModel(); - } - } - - } - - private FactoryRegistry factoryRegistry; - private String fBaseLocation; - boolean fDirtyState; - DirtyStateWatcher fDirtyStateWatcher; - DocumentToModelNotifier fDocumentToModelNotifier; - private String fExplicitContentTypeIdentifier; - private String fId; - - private LifecycleNotificationManager fLifecycleNotificationManager; - - private final Object fListenerLock = new byte[0]; - protected ILock fLockObject; - // private String fLineDelimiter; - // private Object fType; - private IModelHandler fModelHandler; - private IModelManager fModelManager; - private int fModelStateChanging; - private Object[] fModelStateListeners; - private boolean fNewState = false; - private URIResolver fResolver; - protected IStructuredDocument fStructuredDocument; - /** - * The time stamp of the underlying resource's modification date, at the - * time this model was created, or the last time it was saved. Note: for - * this version, this variable is not set automatically, be needs to be - * managed by client. The FileModelProvider does this for most cases, but - * if client do not use FileModelProvider, they must set this variable - */ - public long fSynchronizationStamp = IResource.NULL_STAMP; - private boolean reinitializationNeeded; - private Object reinitializeStateData; - - /** - * AbstractStructuredModel constructor comment. - */ - public AbstractStructuredModel() { - - super(); - fDirtyStateWatcher = new DirtyStateWatcher(); - fDocumentToModelNotifier = new DocumentToModelNotifier(); - } - - - private void _commonRelease() { - - // TODO_future: I suspect ALL this type of logic should be - // on manager side. - - if (factoryRegistry != null) { - factoryRegistry.release(); - } - // if document as not been changed, we'll still be listening for - // first change. This is not a critical clean up, since presumanly - // whole model and document are "going away", but can make - // other memory leaks harder to find if we stay attached. - // (Note: my first thought was to set fStructuredDocument to null - // also, - // but there's others in shutdown process that still need to - // get it, in order to disconnect from it.) - if (fStructuredDocument != null) { - fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher); - fStructuredDocument.removeDocumentAboutToChangeListener(fDocumentToModelNotifier); - fStructuredDocument.removeDocumentChangedListener(fDocumentToModelNotifier); - } - - // we set document to null, mostly so - // any initiatilation done there can be undone. - // (likely needs some restructured to not need?) - setStructuredDocument(null); - } - - /** - * This method is just for getting an instance of the model manager of the - * right Impl type, to be used "internally" for making protected calls - * directly to the impl class. - */ - private ModelManagerImpl _getModelManager() { - // TODO_future: redesign so we don't need this 'Impl' version - if (fModelManager == null) { - fModelManager = StructuredModelManager.getModelManager(); - } - - return (ModelManagerImpl) fModelManager; - } - - /** - * This API allows clients to declare that they are about to make a - * "large" change to the model. This change might be in terms of content - * or it might be in terms of the model id or base location. Note that in - * the case of embedded calls, notification to listners is sent only once. - * Note that the client who is making these changes has the responsibility - * to restore the models state once finished with the changes. See - * getMemento and restoreState. The method isModelStateChanging can be - * used by a client to determine if the model is already in a change - * sequence. - */ - public void aboutToChangeModel() { - - - // notice this is just a public avenue to our protected method - internalAboutToBeChanged(); - } - - - public void aboutToReinitializeModel() { - - - - // notice this is just a public avenue to our protected method - fireModelAboutToBeReinitialized(); - } - - - public void addModelLifecycleListener(IModelLifecycleListener listener) { - - synchronized (fListenerLock) { - - if (fLifecycleNotificationManager == null) { - fLifecycleNotificationManager = new LifecycleNotificationManager(); - } - fLifecycleNotificationManager.addListener(listener); - } - } - - public void addModelStateListener(IModelStateListener listener) { - - synchronized (fListenerLock) { - - if (!Utilities.contains(fModelStateListeners, listener)) { - int oldSize = 0; - if (fModelStateListeners != null) { - // normally won't be null, but we need to be sure, for - // first - // time through - oldSize = fModelStateListeners.length; - } - int newSize = oldSize + 1; - Object[] newListeners = new Object[newSize]; - if (fModelStateListeners != null) { - System.arraycopy(fModelStateListeners, 0, newListeners, 0, oldSize); - } - // add listener to last position - newListeners[newSize - 1] = listener; - // - // now switch new for old - fModelStateListeners = newListeners; - } - } - } - - /** - * This lock to lock the small bits of data and operations in the models - * themselfes. this lock is "shared" with document, so, eventually, - * changes can be made safefly from either side. - */ - protected final void beginLock() { - - // if we get a different lock object - // than we had before, besure to release - // old one first before losing it. - // ISSUE: this smells like an error condition, - // when would this happen? better to check in set document? - ILock documentLock = getLockObjectFromDocument(); - - if (fLockObject != null && fLockObject != documentLock) { - fLockObject.release(); - if (Logger.DEBUG) { - Logger.log(Logger.INFO, "Model lock released early" + fLockObject + " apparently document switched?"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - } - fLockObject = documentLock; - if (fLockObject != null) { - fLockObject.acquire(); - if (Logger.DEBUG) { - Logger.log(Logger.INFO, "Model lock acquired: " + fLockObject); //$NON-NLS-1$ - } - } - } - - public void beginRecording(Object requester) { - - beginRecording(requester, null, null); - } - - public void beginRecording(Object requester, int cursorPosition, int selectionLength) { - - beginRecording(requester, null, null, cursorPosition, selectionLength); - } - - public void beginRecording(Object requester, String label) { - - beginRecording(requester, label, null); - } - - public void beginRecording(Object requester, String label, int cursorPosition, int selectionLength) { - - beginRecording(requester, label, null, cursorPosition, selectionLength); - } - - public void beginRecording(Object requester, String label, String description) { - - if (getUndoManager() != null) - getUndoManager().beginRecording(requester, label, description); - } - - public void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength) { - - if (getUndoManager() != null) - getUndoManager().beginRecording(requester, label, description, cursorPosition, selectionLength); - } - - /** - * This API allows a client controlled way of notifying all ModelEvent - * listners that the model has been changed. This method is a matched pair - * to aboutToChangeModel, and *must* be called after aboutToChangeModel - * ... or some listeners could be left waiting indefinitely for the - * changed event. So, its suggested that changedModel always be in a - * finally clause. Likewise, a client should never call changedModel - * without calling aboutToChangeModel first. In the case of embedded - * calls, the notification is just sent once. - */ - public void changedModel() { - - - // notice this is just a public avenue to our protected method - internalModelChanged(); - // also note! - // if we've been "changed" by a client, we might still need - // to be re-initialized, so we'll check and handle that here. - // Note only does this provide a solution to some "missed" - // re-inits, in provides a built in way for clients to - // "force" the model to handle itself, by bracketing any - // changes with aboutToChange and changed, the model itself - // will check. But only call re-init if all other pending - // modelChanged states have been handled. - if (fModelStateChanging == 0 && isReinitializationNeeded()) { - reinit(); - } - } - - - /** - * Based on similar method in FileDocumentProvider. It will provide what - * the modificationStamp would be if resetSynchronzationStamp(resource) - * were used, although for this 'compute' API, no changes to the instance - * are made. - */ - public long computeModificationStamp(IResource resource) { - - - long modificationStamp = resource.getModificationStamp(); - IPath path = resource.getLocation(); - if (path == null) { - return modificationStamp; - } - // Note: checking existence of file is a little different than - // impl in - // the FileDocumentProvider. See defect number 223790. - File file = path.toFile(); - if (!file.exists()) { - return modificationStamp; - } - modificationStamp = file.lastModified(); - return modificationStamp; - } - - - /** - * Provides a copy of the model, but a new ID must be provided. The - * principle of this copy is not to copy fields, etc., as is typically - * done in a clone method, but to return a model with the same content in - * the structuredDocument. Note: It is the callers responsibility to - * setBaseLocation, listners, etc., as appropriate. Type and Encoding are - * the only fields set by this method. If the newId provided already exist - * in the model manager, a ResourceInUse exception is thrown. - */ - public IStructuredModel copy(String newId) throws ResourceInUse { - - - IStructuredModel newModel = null; - // this first one should fail, if not, its treated as an error - // If the caller wants to use an existing one, they can call - // getExisting - // after this failure - newModel = getModelManager().getExistingModelForEdit(newId); - if (newModel != null) { - // be sure to release the reference we got "by accident" (and - // no - // longer need) - newModel.releaseFromEdit(); - throw new ResourceInUse(); - } - newModel = getModelManager().copyModelForEdit(getId(), newId); - return newModel; - } - - - /** - * Disable undo management. - */ - public void disableUndoManagement() { - - if (getUndoManager() != null) - getUndoManager().disableUndoManagement(); - } - - /** - * Enable undo management. - */ - public void enableUndoManagement() { - - if (getUndoManager() != null) - getUndoManager().enableUndoManagement(); - } - - /** - * endLock is protected only for a very special purpose. So subclasses can - * call it to end the lock after updates have been made, but before - * notifications are sent - * - */ - protected final void endLock() { - if (fLockObject != null) { - fLockObject.release(); - if (Logger.DEBUG) { - Logger.log(Logger.INFO, "Model lock released: " + fLockObject); //$NON-NLS-1$ - } - - } - } - - public void endRecording(Object requester) { - - if (getUndoManager() != null) - getUndoManager().endRecording(requester); - } - - public void endRecording(Object requester, int cursorPosition, int selectionLength) { - - if (getUndoManager() != null) - getUndoManager().endRecording(requester, cursorPosition, selectionLength); - } - - /** - * Informs all registered model state listeners that the the model is - * about to under go a change. This change might be in terms of contents - * or might be in terms of the model's id or base location. - */ - private void fireModelAboutToBeChanged() { - - // we must assign listeners to local variable, since the add and - // remove listner - // methods can change the actual instance of the listener array - // from another thread - if (fModelStateListeners != null) { - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - ((IModelStateListener) holdListeners[i]).modelAboutToBeChanged(this); - } - } - - } - - protected void fireModelAboutToBeReinitialized() { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (fModelStateListeners != null) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelAboutToBeReinitialized"); //$NON-NLS-1$ //$NON-NLS-2$ - } - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - // NOTE: trick for transition. We actual use the same - // listeners - // as modelState, but only send this to those that have - // implemented ModelStateExtended. - IModelStateListener listener = (IModelStateListener) holdListeners[i]; - listener.modelAboutToBeReinitialized(this); - } - } - } - - private void fireModelChanged() { - // we must assign listeners - // to local variable, since the add - // and remove listner - // methods can change the actual instance of the listener - // array from another thread - if (fModelStateListeners != null) { - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - try { - ((IModelStateListener) holdListeners[i]).modelChanged(this); - } - // its so criticial that the begin/end arrive in - // pairs, - // if there happends to be an error in one of the - // modelChanged, - // they we want to be sure rest complete ok. - catch (Exception e) { - Logger.logException(e); - } - } - - } - } - - /** - * Informs all registered model state listeners about a change in the - * dirty state of the model. The dirty state is entirely about changes in - * the content of the model (not, for example, about changes to id, or - * base location -- see modelMoved). - */ - protected void fireModelDirtyStateChanged(IStructuredModel element, boolean isDirty) { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (fModelStateListeners != null) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelDirtyStateChanged"); //$NON-NLS-1$ //$NON-NLS-2$ - } - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - ((IModelStateListener) holdListeners[i]).modelDirtyStateChanged(element, isDirty); - } - } - } - - protected void fireModelReinitialized() { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (fModelStateListeners != null) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelReinitialized"); //$NON-NLS-1$ //$NON-NLS-2$ - } - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - IModelStateListener listener = (IModelStateListener) holdListeners[i]; - listener.modelReinitialized(this); - } - } - } - - /** - * Informs all registered model state listeners about the deletion of a - * model's underlying resource. - */ - protected void fireModelResourceDeleted(IStructuredModel element) { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (fModelStateListeners != null) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelResourceDeleted"); //$NON-NLS-1$ //$NON-NLS-2$ - } - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - ((IModelStateListener) holdListeners[i]).modelResourceDeleted(element); - } - } - } - - /** - * Informs all registered model state listeners that the resource - * underlying a model has been moved. This is typically reflected in a - * change to the id, baseLocation, or both. - */ - protected void fireModelResourceMoved(IStructuredModel originalElement, IStructuredModel movedElement) { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (fModelStateListeners != null) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelResourceMoved"); //$NON-NLS-1$ //$NON-NLS-2$ - } - Object[] holdListeners = fModelStateListeners; - for (int i = 0; i < holdListeners.length; i++) { - ((IModelStateListener) holdListeners[i]).modelResourceMoved(originalElement, movedElement); - } - } - } - - public Object getAdapter(Class adapter) { - - return Platform.getAdapterManager().getAdapter(this, adapter); - } - - /** - * @return java.lang.String - */ - public java.lang.String getBaseLocation() { - - return fBaseLocation; - } - - /** - * @see org.eclipse.wst.sse.core.internal.provisional.IStructuredModel#getContentTypeIdentifier() - */ - public String getContentTypeIdentifier() { - if (fExplicitContentTypeIdentifier != null) - return fExplicitContentTypeIdentifier; - return fModelHandler.getAssociatedContentTypeId(); - } - - /** - * - */ - public FactoryRegistry getFactoryRegistry() { - if (factoryRegistry == null) { - factoryRegistry = new FactoryRegistry(); - } - return factoryRegistry; - } - - /** - * The id is the id that the model manager uses to identify this model - */ - public String getId() { - - - return fId; - } - - public abstract IndexedRegion getIndexedRegion(int offset); - - /** - * @return - */ - private ILock getLockObjectFromDocument() { - - // we always "get afresh" the lock object from our document, - // just in case the instance of the document changes. - ILock result = null; - IStructuredDocument doc = fStructuredDocument; - if (doc != null) { - if (doc instanceof ILockable) { - // remember, more than one client can get the - // lock object, its during the aquire that the - // lock on the thread is obtained. - result = ((ILockable) doc).getLockObject(); - } - } - return result; - } - - /** - * Gets the contentTypeDescription. - * - * @return Returns a ContentTypeDescription - */ - public IModelHandler getModelHandler() { - - return fModelHandler; - } - - - public IModelManager getModelManager() { - - return _getModelManager(); - } - - /** - * This function returns the reference count of underlying model. - */ - // TODO: try to refine the design not to use this function - public int getReferenceCount() { - - - if (getModelManager() == null) - return 0; - return getModelManager().getReferenceCount(getId()); - } - - - /** - * This function returns the reference count of underlying model. - */ - // TODO: try to refine the design not to use this function - public int getReferenceCountForEdit() { - - - - if (getModelManager() == null) - return 0; - return getModelManager().getReferenceCountForEdit(getId()); - } - - - /** - * This function returns the reference count of underlying model. - */ - // TODO: try to refine the design not to use this function - public int getReferenceCountForRead() { - - - - if (getModelManager() == null) - return 0; - return getModelManager().getReferenceCountForRead(getId()); - } - - public Object getReinitializeStateData() { - - return reinitializeStateData; - } - - - - public URIResolver getResolver() { - - return fResolver; - } - - - public IStructuredDocument getStructuredDocument() { - - IStructuredDocument result = null; - result = fStructuredDocument; - return result; - } - - /** - * Insert the method's description here. Creation date: (9/7/2001 2:30:26 - * PM) - * - * @return long - */ - public long getSynchronizationStamp() { - - return fSynchronizationStamp; - } - - public IStructuredTextUndoManager getUndoManager() { - - IStructuredTextUndoManager structuredTextUndoManager = null; - IStructuredDocument structuredDocument = getStructuredDocument(); - if (structuredDocument == null) { - structuredTextUndoManager = null; - } - else { - structuredTextUndoManager = structuredDocument.getUndoManager(); - } - return structuredTextUndoManager; - } - - public void initId(String id) { - fId = id; - } - - final protected void internalAboutToBeChanged() { - - // notice we only fire this event if we are not - // already in a model state changing sequence - if (fModelStateChanging == 0) { - - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelAboutToBeChanged"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - try { - fireModelAboutToBeChanged(); - } - catch (Exception e) { - Logger.logException("Exception while notifying model state listers of about to change", e); //$NON-NLS-1$ - } - finally { - // begin lock after listeners notified, otherwise - // deadlock could occur if they call us back. - beginLock(); - } - - } - // we always increment counter, for every request (so *must* receive - // corresponding number of 'changedModel' requests) - fModelStateChanging++; - } - - /** - * Informs all registered model state listeners that an impending change - * is now complete. This method must only be called by 'modelChanged' - * since it keeps track of counts. - */ - final protected void internalModelChanged() { - - // always decrement - fModelStateChanging--; - - - // Check integrity - // to be less than zero is a programming error, - // but we'll reset to zero - // and try to continue - if (fModelStateChanging < 0) { - fModelStateChanging = 0; - // should not be locked, but just in case - endLock(); - throw new IllegalStateException("Program Error: modelStateChanging was less than zero"); //$NON-NLS-1$ - } - - - // We only fire this event if all pending requests are done. - // That is, if we've received the same number of modelChanged as - // we have aboutToChangeModel. - if (fModelStateChanging == 0) { - if (Logger.DEBUG_MODELSTATE) { - Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelChanged"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - endLock(); - // notifify listeners outside of locked state (or deadlock - // can occur if one of them calls us back. - fireModelChanged(); - } - } - - public boolean isDirty() { - - return fDirtyState; - } - - /** - * This method has very special purpose, its used in subclass - * 'changedModel' to know when to do "ending" sorts of things, right - * before a call to super.ChangedModel would in deed put the model in - * 'end' state. Put another way, at the beginning of the subclasses's - * changedModel, the isModelStateChanging is true, but at end, it will be - * false. So, this method allows a small "peek ahead". - */ - protected boolean isModelChangeStateOnVergeOfEnding() { - - - return fModelStateChanging == 1; - } - - /** - * This method can be called to determine if the model is within a - * "aboutToChange" and "changed" sequence. - */ - public boolean isModelStateChanging() { - - - return fModelStateChanging > 0; - } - - public boolean isNew() { - - return fNewState; - } - - public boolean isReinitializationNeeded() { - - return reinitializationNeeded; - } - - public boolean isSaveNeeded() { - - - if (!isSharedForEdit()) - return isDirty(); - else - return false; - } - - - /** - * This function returns true if there are other references to the - * underlying model. - */ - public boolean isShared() { - if (getModelManager() == null) - return false; - return getModelManager().isShared(getId()); - } - - - /** - * This function returns true if there are other references to the - * underlying model. - */ - public boolean isSharedForEdit() { - - - if (getModelManager() == null) - return false; - return getModelManager().isSharedForEdit(getId()); - } - - - /** - * This function returns true if there are other references to the - * underlying model. - */ - public boolean isSharedForRead() { - - - if (getModelManager() == null) - return false; - return getModelManager().isSharedForRead(getId()); - } - - - public void modelReinitialized() { - - - // notice this is just a public avenue to our protected method - fireModelReinitialized(); - } - - public IStructuredModel newInstance() throws IOException { - - IStructuredModel newModel = null; - // we delegate to the model manager, so loader, etc., can be - // used. - newModel = getModelManager().createNewInstance(this); - return newModel; - } - - public IStructuredModel reinit() { - - - IStructuredModel result = null; - if (fModelStateChanging == 0) { - try { - aboutToChangeModel(); - aboutToReinitializeModel(); - result = _getModelManager().reinitialize(this); - } - finally { - setReinitializeNeeded(false); - setReinitializeStateData(null); - modelReinitialized(); - changedModel(); - } - } - else { - if (Logger.DEBUG) { - Logger.log(Logger.INFO, "indeed!!!"); //$NON-NLS-1$ - } - } - return result; - } - - - /** - * This function allows the model to free up any resources it might be - * using. In particular, itself, as stored in the IModelManager. - */ - public void releaseFromEdit() { - - - if (getModelManager() == null) { - throw new IllegalStateException(MODEL_MANAGER_NULL); //$NON-NLS-1$ - } - else { - // be sure to check the shared state before releasing. (Since - // isShared assumes a count - // of 1 means not shared ... and we want our '1' to be that - // one.) - boolean isShared = isShared(); - - if (!isShared) { - signalPreLifeCycleEventRelease(this); - } - - _getModelManager().releaseFromEdit(getId()); - // if no one else is using us, free up - // our resources - if (!isShared) { - _commonRelease(); - signalPostLifeCycleListenerRelease(this); - } - } - - } - - /** - * This function allows the model to free up any resources it might be - * using. In particular, itself, as stored in the IModelManager. - */ - public void releaseFromRead() { - - if (getModelManager() == null) { - throw new IllegalStateException(MODEL_MANAGER_NULL); //$NON-NLS-1$ - } - else { - // be sure to check the shared state before - // releasing. (Since isShared assumes a count - // of 1 means not shared ... and we want - // our '1' to be that one.) - boolean isShared = isShared(); - - if (!isShared) { - signalPreLifeCycleEventRelease(this); - } - - _getModelManager().releaseFromRead(getId()); - // if no one else is using us, free up - // an resources - if (!isShared) { - // factoryRegistry.release(); - _commonRelease(); - signalPostLifeCycleListenerRelease(this); - } - } - } - - - /** - * This function replenishes the model with the resource without saving - * any possible changes. It is used when one editor may be closing, and - * specifially says not to save the model, but another "display" of the - * model still needs to hang on to some model, so needs a fresh copy. - */ - public IStructuredModel reload(InputStream inputStream) throws IOException { - IStructuredModel result = null; - try { - aboutToChangeModel(); - result = _getModelManager().reloadModel(getId(), inputStream); - } - catch (UnsupportedEncodingException e) { - // log for now, unless we find reason not to - Logger.log(Logger.INFO, e.getMessage()); - } - finally { - changedModel(); - } - return result; - } - - public void removeModelLifecycleListener(IModelLifecycleListener listener) { - - // if manager is null, then none have been added, so - // no need to remove it. - if (fLifecycleNotificationManager == null) - return; - synchronized (fListenerLock) { - fLifecycleNotificationManager.removeListener(listener); - } - } - - - public void removeModelStateListener(IModelStateListener listener) { - - if (listener == null) - return; - if (fModelStateListeners == null) - return; - // if its not in the listeners, we'll ignore the request - synchronized (fListenerLock) { - if (Utilities.contains(fModelStateListeners, listener)) { - int oldSize = fModelStateListeners.length; - int newSize = oldSize - 1; - Object[] newListeners = new Object[newSize]; - int index = 0; - for (int i = 0; i < oldSize; i++) { - if (fModelStateListeners[i] == listener) { // ignore - } - else { - // copy old to new if its not the one we are - // removing - newListeners[index++] = fModelStateListeners[i]; - } - } - // now that we have a new array, let's switch it for the - // old - // one - fModelStateListeners = newListeners; - } - } - } - - - /** - * A method that modififies the model's synchonization stamp to match the - * resource. Turns out there's several ways of doing it, so this ensures a - * common algorithm. - */ - public void resetSynchronizationStamp(IResource resource) { - - - setSynchronizationStamp(computeModificationStamp(resource)); - } - - - /** - * This API allows a client to initiate notification to all interested - * parties that a model's underlying resource has been deleted. - */ - public void resourceDeleted() { - - - // notice this is just a public avenue to our protected method - fireModelResourceDeleted(this); - } - - - /** - * This method allows a model client to initiate notification to all - * interested parties that a model's underlying resource location has - * changed. Note: we assume caller has already changed baseLocation, Id, - * etc., since its really up to the client to determine what's "new" about - * a moved model. Caution: 'this' and 'newModel' may be the same object. - * This is the case for current working with FileModelProvider, but have - * left the dual argument for future possiblities. - */ - public void resourceMoved(IStructuredModel newModel) { - - - // notice this is just a public avenue to our protected method - fireModelResourceMoved(this, newModel); - } - - - public void save() throws UnsupportedEncodingException, IOException, CoreException { - - int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - try { - String stringId = getId(); - _getModelManager().saveModel(stringId, EncodingRule.CONTENT_BASED); - } - - finally { - // we put end notificatin in finally block, so even if - // error occurs during save, listeners are still notified, - // since their code could depend on receiving, to clean up - // some state, or coordinate other resources. - type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - - public void save(EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { - - int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - try { - String stringId = getId(); - _getModelManager().saveModel(stringId, encodingRule); - } - finally { - // we put end notificatin in finally block, so even if - // error occurs during save, listeners are still notified, - // since their code could depend on receiving, to clean up - // some state, or coordinate other resources. - type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - - public void save(IFile iFile) throws UnsupportedEncodingException, IOException, CoreException { - - int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - try { - String stringId = getId(); - _getModelManager().saveModel(iFile, stringId, EncodingRule.CONTENT_BASED); - } - - finally { - // we put end notificatin in finally block, so even if - // error occurs during save, listeners are still notified, - // since their code could depend on receiving, to clean up - // some state, or coordinate other resources. - type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - - public void save(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { - - int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - try { - String stringId = getId(); - _getModelManager().saveModel(iFile, stringId, encodingRule); - } - finally { - // we put end notificatin in finally block, so even if - // error occurs during save, listeners are still notified, - // since their code could depend on receiving, to clean up - // some state, or coordinate other resources. - type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - - public void save(OutputStream outputStream) throws UnsupportedEncodingException, CoreException, IOException { - - int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - try { - String stringId = getId(); - _getModelManager().saveModel(stringId, outputStream, EncodingRule.CONTENT_BASED); - } - - finally { - // we put end notificatin in finally block, so even if - // error occurs during save, listeners are still notified, - // since their code could depend on receiving, to clean up - // some state, or coordinate other resources. - type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - - /** - * This attribute is typically used to denote the model's underlying - * resource. - */ - public void setBaseLocation(java.lang.String newBaseLocation) { - - fBaseLocation = newBaseLocation; - } - - public void setContentTypeIdentifier(String contentTypeIdentifier) { - fExplicitContentTypeIdentifier = contentTypeIdentifier; - } - - /** - * - */ - public void setDirtyState(boolean dirtyState) { - - // no need to process (set or fire event), if same value - if (fDirtyState != dirtyState) { - // prechange notificaiton - int type = ModelLifecycleEvent.MODEL_DIRTY_STATE | ModelLifecycleEvent.PRE_EVENT; - ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - - - // the actual change - fDirtyState = dirtyState; - - // old notification - // TODO: C3 remove old notification - if (fDirtyState == false) { - // if we are being set to not dirty (such as just been saved) - // then we need to start listening for changes - // again to know when to set state to true; - getStructuredDocument().addDocumentChangedListener(fDirtyStateWatcher); - } - fireModelDirtyStateChanged(this, dirtyState); - - - // post change notification - type = ModelLifecycleEvent.MODEL_DIRTY_STATE | ModelLifecycleEvent.POST_EVENT; - modelLifecycleEvent = new ModelLifecycleEvent(this, type); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - /** - * @deprecated - will likely be deprecated soon, in favor of direct 'adds' - * ... but takes some redesign. - */ - public void setFactoryRegistry(FactoryRegistry factoryRegistry) { - this.factoryRegistry = factoryRegistry; - } - - /** - * The id is the id that the model manager uses to identify this model. If - * it is being set here, it means the model manger is already managing the - * model with another id, so we have to keep it in sync. This method calls - * notifies listners, if they haven't been notified already, that a "model - * state change" is about to occur. - */ - public void setId(String newId) throws ResourceInUse { - - - // It makes no sense, I don't think, to have an id of null, so - // we'll throw an illegal argument exception if someone trys. Note: - // the IModelManager could not manage a model with an id of null, - // since it uses hashtables, and you can't have a null id for a - // hashtable. - if (newId == null) - throw new IllegalArgumentException(SSECoreMessages.A_model_s_id_can_not_be_nu_EXC_); //$NON-NLS-1$ = "A model's id can not be null" - // To gaurd againt throwing a spurious ResourceInUse exception, - // which can occur when two pieces of code both want to change the id, - // so the second request is spurious, we'll ignore any requests that - // attempt to change the id to what it already is ... note, we use - // 'equals', not identity ('==') so that things like - // strings can be used. This is the same criteria that ids are - // found in model manager -- well, actually, I just checked, and for - // the hashtable impl, the criteria uses .equals AND the condition - // that the hash values be identical (I'm assuming this is always - // true, if equals is true, for now, I'm not sure - // we can assume that hashtable will always be used, but in - // general, should match.) - // - if (newId.equals(fId)) - return; - // we must gaurd against reassigning an id to one that we already - // are managing. - if (getModelManager() != null) { - IStructuredModel newModel = getModelManager().getExistingModelForEdit(newId); - if (newModel != null) { - // be sure to release the reference we got unexepectantly - // (and no longer need) - newModel.releaseFromEdit(); - throw new ResourceInUse(); - } - } - try { - // normal code path - aboutToChangeModel(); - String oldId = fId; - fId = newId; - if (getModelManager() != null) { - // if managed and the id has changed, notify to - // IModelManager - // TODO: try to refine the design not to do that - if (oldId != null && newId != null && !newId.equals(oldId)) { - getModelManager().moveModel(oldId, newId); - } - } - } - finally { - // make sure this finally is only executed if 'about to Change - // model' has - // ben executed. - changedModel(); - } - } - - /** - * Sets the contentTypeDescription. - * - * @param contentTypeDescription - * The contentTypeDescription to set - */ - public void setModelHandler(IModelHandler modelHandler) { - - // no need to fire events if modelHandler has been null - // for this model -- - // this is an attempt at initialization optimization and may need - // to change in future. - boolean trueChange = false; - if (fModelHandler != null) - trueChange = true; - if (trueChange) { - internalAboutToBeChanged(); - } - fModelHandler = modelHandler; - if (trueChange) { - internalModelChanged(); - } - } - - - - public void setModelManager(IModelManager newModelManager) { - - fModelManager = newModelManager; - } - - /** - * - */ - public void setNewState(boolean newState) { - - fNewState = newState; - } - - /** - * Sets a "flag" that reinitialization is needed. - */ - public void setReinitializeNeeded(boolean needed) { - - reinitializationNeeded = needed; - } - - /** - * Holds any data that the reinit procedure might find useful in - * reinitializing the model. This is handy, since the reinitialization may - * not take place at once, and some "old" data may be needed to properly - * undo previous settings. Note: the parameter was intentially made to be - * of type 'Object' so different models can use in different ways. - */ - public void setReinitializeStateData(Object object) { - - reinitializeStateData = object; - } - - - public void setResolver(URIResolver newResolver) { - - fResolver = newResolver; - } - - - public void setStructuredDocument(IStructuredDocument newStructuredDocument) { - boolean lifeCycleNotification = false; - if (fStructuredDocument != null) { - fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher); - fStructuredDocument.removeDocumentAboutToChangeListener(fDocumentToModelNotifier); - fStructuredDocument.removeDocumentChangedListener(fDocumentToModelNotifier); - // prechange notificaiton - lifeCycleNotification = true; - ModelLifecycleEvent modelLifecycleEvent = new DocumentChanged(ModelLifecycleEvent.PRE_EVENT, this, fStructuredDocument, newStructuredDocument); - signalLifecycleEvent(modelLifecycleEvent); - } - - // hold for life cycle notification - IStructuredDocument previousDocument = fStructuredDocument; - // the actual change - fStructuredDocument = newStructuredDocument; - - - // at the super class level, we'll listen for structuredDocument - // changes - // so we can set our dirty state flag - if (fStructuredDocument != null) { - fStructuredDocument.addDocumentChangedListener(fDirtyStateWatcher); - fStructuredDocument.addDocumentAboutToChangeListener(fDocumentToModelNotifier); - fStructuredDocument.addDocumentChangedListener(fDocumentToModelNotifier); - } - - if (lifeCycleNotification) { - // post change notification - ModelLifecycleEvent modelLifecycleEvent = new DocumentChanged(ModelLifecycleEvent.POST_EVENT, this, previousDocument, newStructuredDocument); - signalLifecycleEvent(modelLifecycleEvent); - } - } - - /** - * Insert the method's description here. Creation date: (9/7/2001 2:30:26 - * PM) - * - * @param newSynchronizationStamp - * long - */ - protected void setSynchronizationStamp(long newSynchronizationStamp) { - - fSynchronizationStamp = newSynchronizationStamp; - } - - public void setUndoManager(IStructuredTextUndoManager undoManager) { - - IStructuredDocument structuredDocument = getStructuredDocument(); - if (structuredDocument == null) { - throw new IllegalStateException("document was null when undo manager set on model"); //$NON-NLS-1$ - } - structuredDocument.setUndoManager(undoManager); - } - - /** - * to be called only be "friendly" classes, such as ModelManger, and - * subclasses. - */ - protected void signalLifecycleEvent(ModelLifecycleEvent event) { - - if (fLifecycleNotificationManager == null) - return; - fLifecycleNotificationManager.signalLifecycleEvent(event); - } - - private void signalPostLifeCycleListenerRelease(IStructuredModel structuredModel) { - int type = ModelLifecycleEvent.MODEL_RELEASED | ModelLifecycleEvent.POST_EVENT; - // what's wrong with this design that a cast is needed here!? - ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type); - ((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event); - } - - private void signalPreLifeCycleEventRelease(IStructuredModel structuredModel) { - int type = ModelLifecycleEvent.MODEL_RELEASED | ModelLifecycleEvent.PRE_EVENT; - // what's wrong with this design that a cast is needed here!? - ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type); - ((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event); - } -} |