/*******************************************************************************
 * 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;

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.common.encoding.EncodingRule;
import org.eclipse.wst.sse.core.document.ILockable;
import org.eclipse.wst.sse.core.events.AboutToBeChangeEvent;
import org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener;
import org.eclipse.wst.sse.core.events.IStructuredDocumentListener;
import org.eclipse.wst.sse.core.events.NewDocumentEvent;
import org.eclipse.wst.sse.core.events.NoChangeEvent;
import org.eclipse.wst.sse.core.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
import org.eclipse.wst.sse.core.exceptions.ResourceInUse;
import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.SSECorePlugin;
import org.eclipse.wst.sse.core.modelhandler.IModelHandler;
import org.eclipse.wst.sse.core.text.IStructuredDocument;
import org.eclipse.wst.sse.core.undo.IStructuredTextUndoManager;
import org.eclipse.wst.sse.core.util.URIResolver;
import org.eclipse.wst.sse.core.util.Utilities;


public abstract class AbstractStructuredModel implements IStructuredModel {

	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.AboutToBeChangeEvent)
		 */
		public void modelAboutToBeChanged(AboutToBeChangeEvent 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.getOriginalSource() != 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.getOriginalSource() != 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.getOriginalSource() != 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.getOriginalSource() != 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.getOriginalSource() != 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.getOriginalSource() != this) {
				changedModel();
			}
		}

	}

	static final String DEBUG_STATE_TRACE_CATEGORY = "org.eclipse.wst.sse.core/structuredmodel/state";
	static final boolean DEBUG_STATE = "true".equalsIgnoreCase(Platform.getDebugOption(DEBUG_STATE_TRACE_CATEGORY));

	private IFactoryRegistry 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];
	private 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;
	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() {

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

	/**
	 * 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;
			}
		}
	}

	/**
	 *  
	 */
	private void beginLock() {
		fLockObject = getLockObject();
		if (fLockObject != null)
			fLockObject.acquire();
	}

	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();
		}
		// fLock being null is used as an indicator that
		// we are not locked (and used in logic to decide
		// acquire/release.
		fLockObject = null;

	}

	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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelAboutToBeReinitialized");
			}
			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];
				if (listener instanceof IModelStateListenerExtended) {
					IModelStateListenerExtended extendedListner = (IModelStateListenerExtended) listener;
					extendedListner.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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelDirtyStateChanged");
			}
			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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelReinitialized");
			}
			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];
				if (listener instanceof IModelStateListenerExtended) {
					IModelStateListenerExtended extendedListner = (IModelStateListenerExtended) listener;
					extendedListner.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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelResourceDeleted");
			}
			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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelResourceMoved");
			}
			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.IStructuredModel#getContentTypeIdentifier()
	 */
	public String getContentTypeIdentifier() {
		if (fExplicitContentTypeIdentifier != null)
			return fExplicitContentTypeIdentifier;
		return fModelHandler.getAssociatedContentTypeId();
	}

	/**
	 *  
	 */
	public IFactoryRegistry 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 getLockObject() {

		// we always "get afresh" the lock object from our document,
		// just in case the instance of the document changes.
		ILock result = null;
		IStructuredDocument doc = getStructuredDocument();
		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;
	}


	/**
	 * This method returns a mememto that can later be used to restore the
	 * state at this point. A model's state, in this sense, does not relate to
	 * its content, or Ids, etc., just its dirty state, and its
	 * synchronization state with its underlying resource. The 'resource'
	 * argument must be the resource that underlies the instance of the model
	 * this method is sent to. Note: this parameter will not be required in
	 * future versions of 'strucutured model'.
	 */
	public IStateMemento getMemento(IResource resource) {

		ModelStateMemento memento = new ModelStateMemento();
		memento.setUnderlyingResource(resource);
		memento.setDirtyState(isDirty());
		long modDate = computeModificationStamp(resource);
		memento.setDatesInSync(fSynchronizationStamp == modDate);
		return memento;
	}

	/**
	 * Gets the contentTypeDescription.
	 * 
	 * @return Returns a ContentTypeDescription
	 */
	public IModelHandler getModelHandler() {

		return fModelHandler;
	}

	/**
	 * @return com.ibm.sed.model.IModelManager
	 */
	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;
	}


	/**
	 * @return com.ibm.sed.util.URIResolver
	 */
	public URIResolver getResolver() {

		return fResolver;
	}

	/**
	 * @return com.ibm.sed.structuredDocument.IStructuredDocument
	 */
	public IStructuredDocument getStructuredDocument() {

		return fStructuredDocument;
	}

	/**
	 * 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;
	}

	protected void internalAboutToBeChanged() {

		// notice we only fire this event if we are not
		// already in a model state changing sequence
		if (fModelStateChanging == 0) {

			if (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelAboutToBeChanged"); //$NON-NLS-1$
			}

			fireModelAboutToBeChanged();
			// 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.
	 */
	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;
			Logger.log(Logger.ERROR, "Program Error: modelStateChanging was less than zero");
		}


		// 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 (DEBUG_STATE) {
				System.out.println("IModelStateListener event for " + getId() + " : modelChanged"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			endLock();
			// notifify listeners outline 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 {
			System.out.println("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 SourceEditingRuntimeException("Warning: AbstractStructuredModel::close:  model manager was null during a close of a model (which should be impossible)"); //$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
			// an 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 SourceEditingRuntimeException("Warning: AbstractStructuredModel::close:  model manager was null during a close of a model (which should be impossible)"); //$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) {
			// its a very serious error to get an unsupported encoding
			// exception,
			// since we've presumable loaded it once already, so won't
			// bother
			// with a checked exception.
			throw new SourceEditingRuntimeException(e);
		} 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 restoreState(IStateMemento memento) {


		ModelStateMemento mMemento = (ModelStateMemento) memento;
		// be sure to use setter, so side effects take place.
		setDirtyState(mMemento.isDirtyState());
		if (mMemento.isDatesInSync()) {
			IResource resource = mMemento.getUnderlyingResource();
			setSynchronizationStamp(computeModificationStamp(resource));
		}
	}


	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(IFactoryRegistry 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(SSECorePlugin.getResourceString("%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();
		}
	}



	/**
	 * @param newModelManager
	 *            com.ibm.sed.model.IModelManager
	 */
	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;
	}

	/**
	 * @param newResolver
	 *            com.ibm.sed.util.URIResolver
	 */
	public void setResolver(URIResolver newResolver) {

		fResolver = newResolver;
	}

	/**
	 * @param newStructuredDocument
	 *            com.ibm.sed.structuredDocument.IStructuredDocument
	 */
	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);
	}
}
