/*******************************************************************************
 * 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;
import org.osgi.framework.Bundle;


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 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) {
			Bundle mmBundle = Platform.getBundle(SSECorePlugin.ID);
			int state = mmBundle.getState();
			if (!(state == Bundle.STOPPING || state == Bundle.UNINSTALLED)) {
				fModelManager = StructuredModelManager.getInstance().getModelManager();
			} else {
				fModelManager = new NullModelManager();
			}

		}

		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() {

		return getModelHandler().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 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);
	}
}
