/*******************************************************************************
 * Copyright (c) 2001, 2010 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
 *  *     Frank Zigler/Web Performance, Inc. - 288196 - Deadlock in ModelManagerImpl after IOException
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.core.internal.model;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.NullMemento;
import org.eclipse.wst.sse.core.internal.SSECoreMessages;
import org.eclipse.wst.sse.core.internal.SSECorePlugin;
import org.eclipse.wst.sse.core.internal.document.DocumentReader;
import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
import org.eclipse.wst.sse.core.internal.encoding.CodedStreamCreator;
import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
import org.eclipse.wst.sse.core.internal.encoding.ContentBasedPreferenceGateway;
import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
import org.eclipse.wst.sse.core.internal.exceptions.MalformedOutputExceptionWithDetail;
import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.util.Assert;
import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
import org.eclipse.wst.sse.core.internal.util.URIResolver;
import org.eclipse.wst.sse.core.internal.util.Utilities;

/**
 * <p>Not intended to be subclassed, referenced or instantiated by clients.
 * Clients should obtain an instance of the IModelManager interface through
 * {@link StructuredModelManager#getModelManager()}.</p>
 * 
 * <p>This class is responsible for creating, retrieving, and caching
 * StructuredModels It retrieves the cached objects by an id which is
 * typically a String representing the resources URI. Note: Its important that
 * all clients that share a resource do so using <b>identical </b>
 * identifiers, or else different instances will be created and retrieved,
 * even if they all technically point to the same resource on the file system.
 * This class also provides a convenient place to register Model Loaders and
 * Dumpers based on 'type'.</p>
 */
public class ModelManagerImpl implements IModelManager {

	
	
	static class ReadEditType {
		ReadEditType(String type) {
		}
	}

	class SharedObject {
		int referenceCountForEdit;
		int referenceCountForRead;
		volatile IStructuredModel theSharedModel;
		final ILock LOAD_LOCK = Job.getJobManager().newLock();
		volatile boolean initializing = true;
		volatile boolean doWait = true;
		// The field 'id' is only meant for debug
		final String id;

		SharedObject(String id) {
			this.id=id;
			// be aware, this lock will leak and cause the deadlock detector to be horrible if we never release it
			LOAD_LOCK.acquire();
		}

		/**
		 * Waits until this shared object has been attempted to be loaded. The
		 * load is "attempted" because not all loads result in a model. However,
		 * upon leaving this method, theShareModel variable is up-to-date.
		 */
		public void waitForLoadAttempt() {
			final boolean allowInterrupt = PrefUtil.ALLOW_INTERRUPT_WAITING_THREAD;
			final long timeLimit = (PrefUtil.WAIT_DELAY==0) ? Long.MAX_VALUE : PrefUtil.now() + PrefUtil.WAIT_DELAY;
			final Job current = Job.getJobManager().currentJob();
			boolean interrupted = false;
			try {
				while (initializing) {
					if (current!=null) {
						current.yieldRule(null);
					}
					try {
						loop();
					} catch (InterruptedException e) {
						if (allowInterrupt) {
							throw new OperationCanceledException("Waiting thread interrupted while waiting for model id: "+id + " to load");
						} else {
							interrupted=true;
						}
					}
					if (PrefUtil.now() >= timeLimit	)
						throw new OperationCanceledException("Waiting thread timeout exceeded while waiting for model id: "+id + " to load");
				}
			}
			finally {
				if (interrupted) {
					Thread.currentThread().interrupt();
				}
			}
		}

		private void loop() throws InterruptedException {	
			if (initializing) {
				if (LOAD_LOCK.acquire(PrefUtil.WAIT_INTERVAL_MS)) {
					// if we got the lock, but initializing is still not true the deadlock detector gave us
					// the lock and caused reentrancy into this critical section. This is invalid and the 
					// sign of a cyclical load attempt. In this case, we through an 
					// OperationCanceledException in lew of entering a spin-loop. 
					if (initializing) {
						LOAD_LOCK.release();
						throw new OperationCanceledException("Aborted cyclic load attempt for model with id: "+ id );
					} else {
						LOAD_LOCK.release();
					}
				}
			}
		}

		/**
		 * Flags this model as loaded. All waiting methods on
		 * {@link #waitForLoadAttempt()} will proceed after this method returns.
		 */
		public void setLoaded() {
			initializing = false;
			LOAD_LOCK.release();
		}
	}

	private Exception debugException = null;

	/**
	 * Our singleton instance
	 */
	private static ModelManagerImpl instance;
	private final static int READ_BUFFER_SIZE = 4096;

	/**
	 * Not to be called by clients, will be made restricted access.
	 * 
	 * @return
	 */
	public synchronized static IModelManager getInstance() {

		if (instance == null) {
			instance = new ModelManagerImpl();
		}
		return instance;
	}

	/**
	 * Our cache of managed objects
	 */
	private Map fManagedObjects;

	private ModelHandlerRegistry fModelHandlerRegistry;
	private final ReadEditType READ = new ReadEditType("read"); //$NON-NLS-1$
	private final ReadEditType EDIT = new ReadEditType("edit"); //$NON-NLS-1$
	
	private final ILock SYNC = Job.getJobManager().newLock();
	/**
	 * Intentionally default access only.
	 * 
	 */
	ModelManagerImpl() {
		super();
		fManagedObjects = new HashMap();
		// To prevent deadlocks:  always acquire multiple locks in this order: SYNC, sharedObject. 
		// DO NOT acquire a SYNC within a sharedObject lock, unless you already own the SYNC lock
		// Tip: Try to hold the smallest number of locks you can
	}

	private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException {
		SharedObject sharedObject = null;
		
		SYNC.acquire();
		sharedObject = (SharedObject) fManagedObjects.get(id);
		SYNC.release();
		
		while(true) {
			if (sharedObject!=null) {
				sharedObject.waitForLoadAttempt();
			}
			SYNC.acquire();
			// we know this object's model has passed the load, however, we don't know 
			// it's reference count status. It might have already been disposed. Or it could have 
			// been disposed and a concurrent thread has already begun loading it, in which case
			// we should use the sharedobject they are loading. 
			// NOTE: This pattern is applied 3 times in this class, but only doc'd once. The logic is 
			// exactly the same. 
			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
			if (testObject==null) {
				// null means it's been disposed, we need to do the work to reload it.
				sharedObject = new SharedObject(id);
				fManagedObjects.put(id, sharedObject);
				SYNC.release();
				_doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule,
						sharedObject);
				break;
			} else if (sharedObject == testObject) {
				// if nothing happened, just increment the could and return the shared model
				synchronized(sharedObject) {
					if (sharedObject.theSharedModel!=null) {
						_incrCount(sharedObject, rwType);
					}
				}
				SYNC.release();
				break;
			} else {
				// sharedObject != testObject which means the object we were waiting on has been disposed
				// a replacement has already been placed in the managedObjects table. Through away our
				// stale sharedObject and continue on with the one we got from the queue. Note: We don't know its
				// state, so continue the waitForLoad-check loop. 
				SYNC.release();
				sharedObject = testObject;
			}
		}
		
		// we expect to always return something
		if (sharedObject == null) {
			debugException = new Exception("instance only for stack trace"); //$NON-NLS-1$
			Logger.logException("Program Error: no model recorded for id " + id, debugException); //$NON-NLS-1$
		}
		
		// note: clients must call release for each time they call get.
		return sharedObject==null ? null : sharedObject.theSharedModel;
	}

	private void _decrCount(SharedObject sharedObject, ReadEditType type) {
		if (type == READ) {
			sharedObject.referenceCountForRead--;
			FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument());
		}
		else if (type == EDIT) {
			sharedObject.referenceCountForEdit--;
			FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument());
		}
		else
			throw new IllegalArgumentException();
	}

	private void _doCommonCreateModel(IFile file, String id, IModelHandler handler,
			URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule,
			SharedObject sharedObject) throws CoreException, IOException {
		// XXX: Does not integrate with FileBuffers
		boolean doRemove = true;
		try {
		synchronized(sharedObject) {
			InputStream inputStream = null;
			IStructuredModel model = null;
			try {
				model = _commonCreateModel(id, handler, resolver);
				IModelLoader loader = handler.getModelLoader();
				inputStream = Utilities.getMarkSupportedStream(file.getContents(true));
				loader.load(Utilities.getMarkSupportedStream(inputStream), model, encodingRule);
			}
			catch (ResourceInUse e) {
				// impossible, since we've already found
				handleProgramError(e);
			} finally {
				if (inputStream!=null) {
					try { 
						inputStream.close();
					} catch(IOException e) {
					}
				}
			}
			if (model != null) {
				// add to our cache
				sharedObject.theSharedModel=model;
				_initCount(sharedObject, rwType);
				doRemove = false;
			}
		}
		}
		finally{
		if (doRemove) {
			SYNC.acquire();	
			fManagedObjects.remove(id);	
			SYNC.release();
		}
		sharedObject.setLoaded();
		}
	}

	private IStructuredModel _commonCreateModel(InputStream inputStream, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException {
		
		if (id == null) {
			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$
		}
		SharedObject sharedObject = null;
	
		SYNC.acquire();
		sharedObject = (SharedObject) fManagedObjects.get(id);
		SYNC.release();
		
		while(true) {
			if (sharedObject!=null) {
				sharedObject.waitForLoadAttempt();
			}
			SYNC.acquire();
			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
			if (testObject==null) {
				// it was removed ,so lets create it
				sharedObject = new SharedObject(id);
				fManagedObjects.put(id, sharedObject);
				SYNC.release();
				_doCommonCreateModel(inputStream, id, handler, resolver, rwType,
						encoding, lineDelimiter, sharedObject);
				break;
			} else if (sharedObject == testObject) {
				synchronized(sharedObject) {
					if (sharedObject.theSharedModel!=null) {
						_incrCount(sharedObject, rwType);
					}
				}
				SYNC.release();
				break;
			} else {
				SYNC.release();
				sharedObject = testObject;
			}
		}
		
		// we expect to always return something
		Assert.isNotNull(sharedObject, "Program Error: no model recorded for id " + id); //$NON-NLS-1$
		// note: clients must call release for each time they call get.
		return sharedObject.theSharedModel;
	
	}

	private void _doCommonCreateModel(InputStream inputStream, String id, IModelHandler handler,
			URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter,
			SharedObject sharedObject) throws IOException {
		boolean doRemove = true;
		try {
		synchronized(sharedObject) {
			IStructuredModel model = null;
			try {
				model = _commonCreateModel(id, handler, resolver);
				IModelLoader loader = handler.getModelLoader();
				if (inputStream == null) {
					Logger.log(Logger.WARNING, "model was requested for id " + id + " without a content InputStream"); //$NON-NLS-1$ //$NON-NLS-2$
				}
				loader.load(id, Utilities.getMarkSupportedStream(inputStream), model, encoding, lineDelimiter);
			}
			catch (ResourceInUse e) {
				// impossible, since we've already found
				handleProgramError(e);
			}
			if (model != null) {
				/**
				 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=264228
				 * 
				 * Ensure that the content type identifier field of the model
				 * is properly set. This is normally handled by the
				 * FileBufferModelManager when working with files as it knows
				 * the content type in advance; here is where we handle it for
				 * streams.
				 */
				if (model instanceof AbstractStructuredModel) {
					DocumentReader reader = new DocumentReader(model.getStructuredDocument());
					IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(reader, id, new QualifiedName[0]);
					reader.close();
					if (description != null && description.getContentType() != null) {
						((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId());
					}
				}

				sharedObject.theSharedModel = model;
				_initCount(sharedObject, rwType);
				doRemove = false;
			}
		}
		}
		finally {
		if (doRemove) {
			SYNC.acquire();
			// remove it if we didn't get one back
			fManagedObjects.remove(id);
			SYNC.release();
		}
		sharedObject.setLoaded();
		}
	}

	private IStructuredModel _commonCreateModel(String id, IModelHandler handler, URIResolver resolver) throws ResourceInUse {

		IModelLoader loader = handler.getModelLoader();
		IStructuredModel result = loader.createModel();
		// in the past, id was null for "unmanaged" case, so we won't
		// try and set it
		if (id != null) {
			result.setId(id);
		}
		result.setModelHandler(handler);
		result.setResolver(resolver);
		// some obvious redunancy here that maybe could be improved
		// in future, but is necessary for now
		result.setBaseLocation(id);
		if (resolver != null) {
			resolver.setFileBaseLocation(id);
		}
		addFactories(result, handler);
		return result;
	}

	private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
		IStructuredModel model = null;

		if (iFile != null && iFile.exists()) {
			String id = calculateId(iFile);
			IModelHandler handler = calculateType(iFile);
			URIResolver resolver = calculateURIResolver(iFile);
			model = _commonCreateModel(iFile, id, handler, resolver, rwType, encodingRule);
		}

		return model;
	}

	private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, String encoding, String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException {
		String id = calculateId(iFile);
		IStructuredModel model = _commonGetModel(iFile, id, rwType, encoding, lineDelimiter);

		return model;
	}

	private IStructuredModel _commonGetModel(IFile file, String id, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException, CoreException {
		if (id == null)
			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$

		SharedObject sharedObject = null;
		if (file != null && file.exists()) {
			SYNC.acquire();
			sharedObject = (SharedObject) fManagedObjects.get(id);
			SYNC.release();
			
			while(true) {
				if (sharedObject!=null) {
					sharedObject.waitForLoadAttempt();
				}
				SYNC.acquire();
				SharedObject testObject = (SharedObject) fManagedObjects.get(id);
				if (testObject==null) {
					// it was removed ,so lets create it
					sharedObject = new SharedObject(id);
					fManagedObjects.put(id, sharedObject);
					
					SYNC.release();
					_doCommonGetModel(file, id, sharedObject,rwType);
					break;
				} else if (sharedObject == testObject) {
					synchronized(sharedObject) {
						if (sharedObject.theSharedModel!=null) {
							_incrCount(sharedObject, rwType);
						}
					}
					SYNC.release();
					break;
				} else {
					// we got a different object than what we were expecting
					SYNC.release();
					// two threads were interested in models for the same id. 
					// The other thread one, so lets back off and try again. 
					sharedObject = testObject; 
				}
			}
		}
		
		// if we don't know how to create a model
		// for this type of file, return null
	
		// note: clients must call release for each time they call
		// get.
			
		return sharedObject==null ? null : sharedObject.theSharedModel;
	}

	private void _doCommonGetModel(IFile file, String id, SharedObject sharedObject,ReadEditType rwType) {
		boolean doRemove = true;
		try {
			synchronized(sharedObject) {
				sharedObject.doWait=false;
				IStructuredModel model = null;
				try {
					model = FileBufferModelManager.getInstance().getModel(file);
				}
				finally {
					sharedObject.doWait=true;
				}
				if (model != null) {
					sharedObject.theSharedModel=model;
					_initCount(sharedObject, rwType);
					doRemove = false;
				}
			}
		}
		finally {
			if (doRemove) {
				SYNC.acquire();
				fManagedObjects.remove(id);
				SYNC.release();
			}
			sharedObject.setLoaded();
		}
	}

	private SharedObject _commonNewModel(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {
		IStructuredModel aSharedModel = null;
		// First, check if resource already exists on file system.
		// if is does, then throw Resource in Use iff force==false

		if (iFile.exists() && !force) {
			throw new ResourceAlreadyExists();
		}
		
		SharedObject sharedObject = null;
		String id = calculateId(iFile);
		try {
			SYNC.acquire();
		
			 sharedObject = (SharedObject) fManagedObjects.get(id);
	
			if (sharedObject != null && !force) {
				// if in cache already, and force is not true, then this is an
				// error
				// in call
				throw new ResourceInUse();
			}
			
			sharedObject = new SharedObject(id);
			fManagedObjects.put(id, sharedObject);
			
		} finally {
			SYNC.release();
		}
		
		// if we get to here without above exceptions, then all is ok
		// to get model like normal, but set 'new' attribute (where the
		// 'new' attribute means this is a model without a corresponding
		// underlying resource.
		aSharedModel = FileBufferModelManager.getInstance().getModel(iFile);
		aSharedModel.setNewState(true);
		
		sharedObject.theSharedModel=aSharedModel;
		// when resource is provided, we can set
		// synchronization stamp ... otherwise client should
		// Note: one client which does this is FileModelProvider.
		aSharedModel.resetSynchronizationStamp(iFile);
		return sharedObject;
	}

	public IStructuredModel _getModelFor(IStructuredDocument document, ReadEditType accessType) {

		String id = FileBufferModelManager.getInstance().calculateId(document);
		if (id == null) {
			if (READ == accessType)
				return getExistingModelForRead(document);
			if (EDIT == accessType)
				return getExistingModelForEdit(document);
			Assert.isNotNull(id, "unknown IStructuredDocument " + document); //$NON-NLS-1$
		}
		
		SharedObject sharedObject = null;
		SYNC.acquire();
		sharedObject = (SharedObject) fManagedObjects.get(id);
		SYNC.release();
		
		while(true) {
			if (sharedObject!=null) {
				sharedObject.waitForLoadAttempt();
			}
			SYNC.acquire();
			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
			if (testObject==null) {
				sharedObject = new SharedObject(id);
				fManagedObjects.put(id, sharedObject);
				SYNC.release();
				synchronized(sharedObject) {
					sharedObject.theSharedModel = FileBufferModelManager.getInstance().getModel(document);
					_initCount(sharedObject, accessType);
					sharedObject.setLoaded();
				}
				break;
			} else if (sharedObject == testObject) {
				synchronized(sharedObject) {
					Assert.isTrue(sharedObject.referenceCountForEdit + sharedObject.referenceCountForRead > 0, "reference count was less than zero");
					if (sharedObject.theSharedModel!=null) {
						_incrCount(sharedObject, accessType);
					}
				}
				SYNC.release();
				break;
			} else {
				SYNC.release();
				sharedObject = testObject;
			}
		}
		
		return sharedObject==null ? null : sharedObject.theSharedModel;
	}

	private void _incrCount(SharedObject sharedObject, ReadEditType type) {
		synchronized(sharedObject) {
			if (type == READ) {
				sharedObject.referenceCountForRead++;
				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
			}
			else if (type == EDIT) {
				sharedObject.referenceCountForEdit++;
				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
			}
			else
				throw new IllegalArgumentException();
		}
	}

	private void _initCount(SharedObject sharedObject, ReadEditType type) {
		synchronized(sharedObject) {
			if (type == READ) {
				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
				sharedObject.referenceCountForRead = 1;
			}
			else if (type == EDIT) {
				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
				sharedObject.referenceCountForEdit = 1;
			}
			else
				throw new IllegalArgumentException();
		}
	}

	private void addFactories(IStructuredModel model, IModelHandler handler) {
		Assert.isNotNull(model, "model can not be null"); //$NON-NLS-1$
		FactoryRegistry registry = model.getFactoryRegistry();
		Assert.isNotNull(registry, "model's Factory Registry can not be null"); //$NON-NLS-1$
		List factoryList = handler.getAdapterFactories();
		addFactories(model, factoryList);
	}

	private void addFactories(IStructuredModel model, List factoryList) {
		Assert.isNotNull(model, "model can not be null"); //$NON-NLS-1$
		FactoryRegistry registry = model.getFactoryRegistry();
		Assert.isNotNull(registry, "model's Factory Registry can not be null"); //$NON-NLS-1$
		// Note: we add all of them from handler, even if
		// already exists. May need to reconsider this.
		if (factoryList != null) {
			Iterator iterator = factoryList.iterator();
			while (iterator.hasNext()) {
				INodeAdapterFactory factory = (INodeAdapterFactory) iterator.next();
				registry.addFactory(factory);
			}
		}
	}


	/**
	 * Calculate id provides a common way to determine the id from the input
	 * ... needed to get and save the model. It is a simple class utility, but
	 * is an instance method so can be accessed via interface.
	 */
	public String calculateId(IFile file) {
		return FileBufferModelManager.getInstance().calculateId(file);
	}

	private IModelHandler calculateType(IFile iFile) throws CoreException {
		// IModelManager mm = ((ModelManagerPlugin)
		// Platform.getPlugin(ModelManagerPlugin.ID)).getModelManager();
		ModelHandlerRegistry cr = getModelHandlerRegistry();
		IModelHandler cd = cr.getHandlerFor(iFile);
		return cd;
	}

	private IModelHandler calculateType(String filename, InputStream inputStream) throws IOException {
		ModelHandlerRegistry cr = getModelHandlerRegistry();
		IModelHandler cd = cr.getHandlerFor(filename, inputStream);
		return cd;
	}

	/**
	 * 
	 */
	private URIResolver calculateURIResolver(IFile file) {
		// Note: see comment in plugin.xml for potentially
		// breaking change in behavior.

		IProject project = file.getProject();
		URIResolver resolver = (URIResolver) project.getAdapter(URIResolver.class);
		if (resolver == null)
			resolver = new ProjectResolver(project);
		Object location = file.getLocation();
		if (location == null)
			location = file.getLocationURI();
		if (location != null)
			resolver.setFileBaseLocation(location.toString());
		return resolver;
	}

	/*
	 * Note: This method appears in both ModelManagerImpl and JSEditor (with
	 * just a minor difference). They should be kept the same.
	 * 
	 * @deprecated - handled by platform
	 */
	private void convertLineDelimiters(IDocument document, IFile iFile) throws CoreException {
		// Note: calculateType(iFile) returns a default xml model handler if
		// content type is null.
		String contentTypeId = calculateType(iFile).getAssociatedContentTypeId();
		String endOfLineCode = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.END_OF_LINE_CODE);
		// endOfLineCode == null means the content type does not support this
		// function (e.g. DTD)
		// endOfLineCode == "" means no translation
		if (endOfLineCode != null && endOfLineCode.length() > 0) {
			String lineDelimiterToUse = System.getProperty("line.separator"); //$NON-NLS-1$
			if (endOfLineCode.equals(CommonEncodingPreferenceNames.CR))
				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_CR;
			else if (endOfLineCode.equals(CommonEncodingPreferenceNames.LF))
				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_LF;
			else if (endOfLineCode.equals(CommonEncodingPreferenceNames.CRLF))
				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_CRLF;

			TextEdit multiTextEdit = new MultiTextEdit();
			int lineCount = document.getNumberOfLines();
			try {
				for (int i = 0; i < lineCount; i++) {
					IRegion lineInfo = document.getLineInformation(i);
					int lineStartOffset = lineInfo.getOffset();
					int lineLength = lineInfo.getLength();
					int lineEndOffset = lineStartOffset + lineLength;

					if (i < lineCount - 1) {
						String currentLineDelimiter = document.getLineDelimiter(i);
						if (currentLineDelimiter != null && currentLineDelimiter.compareTo(lineDelimiterToUse) != 0)
							multiTextEdit.addChild(new ReplaceEdit(lineEndOffset, currentLineDelimiter.length(), lineDelimiterToUse));
					}
				}

				if (multiTextEdit.getChildrenSize() > 0)
					multiTextEdit.apply(document);
			}
			catch (BadLocationException exception) {
				// just adding generic runtime here, until whole method
				// deleted.
				throw new RuntimeException(exception.getMessage());
			}
		}
	}

	/**
	 * this used to be in loader, but has been moved here
	 */
	private IStructuredModel copy(IStructuredModel model, String newId) throws ResourceInUse {
		IStructuredModel newModel = null;
		IStructuredModel oldModel = model;
		IModelHandler modelHandler = oldModel.getModelHandler();
		IModelLoader loader = modelHandler.getModelLoader();
		// newModel = loader.newModel();
		newModel = loader.createModel(oldModel);
		// newId, oldModel.getResolver(), oldModel.getModelManager());
		newModel.setModelHandler(modelHandler);
		// IStructuredDocument oldStructuredDocument =
		// oldModel.getStructuredDocument();
		// IStructuredDocument newStructuredDocument =
		// oldStructuredDocument.newInstance();
		// newModel.setStructuredDocument(newStructuredDocument);
		newModel.setResolver(oldModel.getResolver());
		newModel.setModelManager(oldModel.getModelManager());
		// duplicateFactoryRegistry(newModel, oldModel);
		newModel.setId(newId);
		// set text of new one after all initialization is done
		String contents = oldModel.getStructuredDocument().getText();
		newModel.getStructuredDocument().setText(this, contents);
		return newModel;
	}

	/**
	 */
	public IStructuredModel copyModelForEdit(String oldId, String newId) throws ResourceInUse {
		IStructuredModel newModel = null;
		// get the existing model associated with this id
		IStructuredModel model = getExistingModel(oldId);
		// if it doesn't exist, ignore request (though this would normally
		// be a programming error.
		if (model == null)
			return null;
		SharedObject sharedObject = null;
		try {
			SYNC.acquire();
			// now be sure newModel does not exist
			sharedObject = (SharedObject) fManagedObjects.get(newId);
			if (sharedObject != null) {
				throw new ResourceInUse();
			}
			sharedObject = new SharedObject(newId);
			fManagedObjects.put(newId,sharedObject);
		} finally {
			SYNC.release();
		}
		// get loader based on existing type (note the type assumption)
		// Object type = ((IStructuredModel) model).getType();
		// IModelHandler type = model.getModelHandler();
		// IModelLoader loader = (IModelLoader) getModelLoaders().get(type);
		// IModelLoader loader = (IModelLoader) getModelLoaders().get(type);
		// ask the loader to copy
		synchronized(sharedObject) {
			sharedObject.doWait = false;
			newModel = copy(model, newId);
			sharedObject.doWait = true;
		}
		if (newModel != null) {
			// add to our cache
			synchronized(sharedObject) {
				sharedObject.theSharedModel=newModel;
				sharedObject.referenceCountForEdit = 1;
				trace("copied model", newId, sharedObject.referenceCountForEdit); //$NON-NLS-1$
			}
		} else {
			SYNC.acquire();
			fManagedObjects.remove(newId);
			SYNC.release();
		}
		sharedObject.setLoaded();
		return newModel;
	}

	/**
	 * Similar to clone, except the new instance has no content. Note: this
	 * produces an unmanaged model, for temporary use. If a true shared model
	 * is desired, use "copy".
	 */
	public IStructuredModel createNewInstance(IStructuredModel oldModel) throws IOException {
		IModelHandler handler = oldModel.getModelHandler();
		IModelLoader loader = handler.getModelLoader();
		IStructuredModel newModel = loader.createModel(oldModel);
		newModel.setModelHandler(handler);
		if (newModel instanceof AbstractStructuredModel) {
			((AbstractStructuredModel) newModel).setContentTypeIdentifier(oldModel.getContentTypeIdentifier());
		}
		URIResolver oldResolver = oldModel.getResolver();
		newModel.setResolver(oldResolver);
		try {
			newModel.setId(DUPLICATED_MODEL);
		}
		catch (ResourceInUse e) {
			// impossible, since this is an unmanaged model
		}
		// base location should be null, but we'll set to
		// null to be sure.
		newModel.setBaseLocation(null);
		return newModel;
	}

	/**
	 * Factory method, since a proper IStructuredDocument must have a proper
	 * parser assigned. Note: its assume that IFile does not actually exist as
	 * a resource yet. If it does, ResourceAlreadyExists exception is thrown.
	 * If the resource does already exist, then createStructuredDocumentFor is
	 * the right API to use.
	 * 
	 * @throws ResourceInUse
	 * 
	 */
	public  IStructuredDocument createNewStructuredDocumentFor(IFile iFile) throws ResourceAlreadyExists, IOException, CoreException {
		if (iFile.exists()) {
			throw new ResourceAlreadyExists(iFile.getFullPath().toOSString());
		}
		// Will reconsider in future version
		// String id = calculateId(iFile);
		// if (isResourceInUse(id)) {
		// throw new ResourceInUse(iFile.getFullPath().toOSString());
		// }
		IDocumentLoader loader = null;
		IModelHandler handler = calculateType(iFile);
		loader = handler.getDocumentLoader();
		// for this API, "createNew" we assume the IFile does not exist yet
		// as checked above, so just create empty document.
		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
		return result;
	}

	/**
	 * Factory method, since a proper IStructuredDocument must have a proper
	 * parser assigned. Note: clients should verify IFile exists before using
	 * this method. If this IFile does not exist, then
	 * createNewStructuredDocument is the correct API to use.
	 * 
	 * @throws ResourceInUse
	 */
	public  IStructuredDocument createStructuredDocumentFor(IFile iFile) throws IOException, CoreException {
		if (!iFile.exists()) {
			throw new FileNotFoundException(iFile.getFullPath().toOSString());
		}
		// Will reconsider in future version
		// String id = calculateId(iFile);
		// if (isResourceInUse(id)) {
		// throw new ResourceInUse(iFile.getFullPath().toOSString());
		// }
		IDocumentLoader loader = null;
		IModelHandler handler = calculateType(iFile);
		loader = handler.getDocumentLoader();
		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument(iFile);
		return result;
	}

	/**
	 * Conveience method, since a proper IStructuredDocument must have a
	 * proper parser assigned. It should only be used when an empty
	 * structuredDocument is needed. Otherwise, use IFile form.
	 * 
	 * @deprecated - TODO: to be removed by C4 do we really need this? I
	 *             recommend to - use createStructuredDocumentFor(filename,
	 *             null, null) - the filename does not need to represent a
	 *             real - file, but can take for form of dummy.jsp, test.xml,
	 *             etc. - That way we don't hard code the handler, but specify
	 *             we - want the handler that "goes with" a certain type of -
	 *             file.
	 */
	public  IStructuredDocument createStructuredDocumentFor(String contentTypeId) {
		IDocumentLoader loader = null;
		ModelHandlerRegistry cr = getModelHandlerRegistry();
		IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId);
		if (handler == null)
			Logger.log(Logger.ERROR, "Program error: no model handler found for " + contentTypeId); //$NON-NLS-1$
		loader = handler.getDocumentLoader();
		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
		return result;
	}

	/**
	 * Conveience method, since a proper IStructuredDocument must have a
	 * proper parser assigned.
	 * 
	 * @deprecated -- - TODO: to be removed by C4 I marked as deprecated to
	 *             discouage use of this method. It does not really work for
	 *             JSP fragments, since JSP Fragments need an IFile to
	 *             correctly look up the content settings. Use IFile form
	 *             instead.
	 */
	public IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver) throws IOException {
		IDocumentLoader loader = null;
		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
		if (istream != null) {
			istream.reset();
		}
		IModelHandler handler = calculateType(filename, istream);
		loader = handler.getDocumentLoader();
		IStructuredDocument result = null;
		if (inputStream == null) {
			result = (IStructuredDocument) loader.createNewStructuredDocument();
		}
		else {
			result = (IStructuredDocument) loader.createNewStructuredDocument(filename, istream);
		}
		return result;
	}

	/**
	 * Special case method. This method was created for the special case where
	 * there is an encoding for input stream that should override all the
	 * normal rules for encoding. For example, if there is an encoding
	 * (charset) specified in HTTP response header, then that encoding is used
	 * to translate the input stream to a string, but then the normal encoding
	 * rules are ignored, so that the string is not translated twice (for
	 * example, if its an HTML "file", then even if it contains a charset in
	 * meta tag, its ignored since its assumed its all correctly decoded by
	 * the HTTP charset.
	 */
	public  IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver, String encoding) throws IOException {
		String content = readInputStream(inputStream, encoding);
		IStructuredDocument result = createStructuredDocumentFor(filename, content, resolver);
		return result;
	}

	/**
	 * Convenience method. This method can be used when the resource does not
	 * really exist (e.g. when content is being created, but hasn't been
	 * written to disk yet). Note that since the content is being provided as
	 * a String, it is assumed to already be decoded correctly so no
	 * transformation is done.
	 */
	public  IStructuredDocument createStructuredDocumentFor(String filename, String content, URIResolver resolver) throws IOException {
		// TODO: avoid all these String instances
		StringBuffer contentBuffer = new StringBuffer(content);
		IDocumentLoader loader = null;
		IModelHandler handler = calculateType(filename, null);
		loader = handler.getDocumentLoader();
		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
		StringBuffer convertedContent = loader.handleLineDelimiter(contentBuffer, result);
		result.setEncodingMemento(new NullMemento());
		result.setText(this, convertedContent.toString());
		return result;
	}

	/**
	 * @param iFile
	 * @param result
	 * @return
	 * @throws CoreException
	 */
	private IStructuredModel createUnManagedEmptyModelFor(IFile iFile) throws CoreException {
		IStructuredModel result = null;
		IModelHandler handler = calculateType(iFile);
		String id = calculateId(iFile);
		URIResolver resolver = calculateURIResolver(iFile);

		try {
			result = _commonCreateModel(id, handler, resolver);
		}
		catch (ResourceInUse e) {
			// impossible, since we're not sharing
			// (even if it really is in use ... we don't care)
			// this may need to be re-examined.
			if (Logger.DEBUG_MODELMANAGER)
				Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$
		}

		return result;
	}

	/**
	 * Conveience method. It depends on the loaders newModel method to return
	 * an appropriate StrucuturedModel appropriately initialized.
	 */
	public IStructuredModel createUnManagedStructuredModelFor(IFile iFile) throws IOException, CoreException {
		IStructuredModel result = null;
		result = createUnManagedEmptyModelFor(iFile);

		IDocumentLoader loader = result.getModelHandler().getDocumentLoader();
		IEncodedDocument document = loader.createNewStructuredDocument(iFile);

		result.getStructuredDocument().setText(this, document.get());

		return result;
	}

	/**
	 * Conveience method. It depends on the loaders newModel method to return
	 * an appropriate StrucuturedModel appropriately initialized.
	 */
	public  IStructuredModel createUnManagedStructuredModelFor(String contentTypeId) {
		return createUnManagedStructuredModelFor(contentTypeId, null);
	}

	/**
	 * Conveience method. It depends on the loaders newModel method to return
	 * an appropriate StrucuturedModel appropriately initialized.
	 */
	public  IStructuredModel createUnManagedStructuredModelFor(String contentTypeId, URIResolver resolver) {
		IStructuredModel result = null;
		ModelHandlerRegistry cr = getModelHandlerRegistry();
		IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId);
		try {
			result = _commonCreateModel(UNMANAGED_MODEL, handler, resolver); //$NON-NLS-1$
		}
		catch (ResourceInUse e) {
			// impossible, since we're not sharing
			// (even if it really is in use ... we don't care)
			// this may need to be re-examined.
			if (Logger.DEBUG_MODELMANAGER)
				Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return result;
	}

	private IStructuredModel getExistingModel(Object id) {
		IStructuredModel result = null;
		
		SYNC.acquire();
		/**
		 * While a good check in theory, it's possible for an event fired to
		 * cause a listener to access a method that calls this one.
		 */
		//Assert.isTrue(SYNC.getDepth()==1, "depth not equal to 1");
		// let's see if we already have it in our cache
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		// if not, then we'll simply return null
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			result = sharedObject.theSharedModel;
		} else {
			SYNC.release();
		}
		
		return result;
	}

	/**
	 * Note: users of this 'model' must still release it when finished.
	 * Returns null if there's not a model corresponding to document.
	 */
	public IStructuredModel getExistingModelForEdit(IDocument document) {
		IStructuredModel result = null;
		
		SYNC.acquire();		
		// create a snapshot
		Set ids = new HashSet(fManagedObjects.keySet());
		SYNC.release();
		for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
			Object potentialId = iterator.next();
			SYNC.acquire();	
			if (fManagedObjects.containsKey(potentialId)) {
				// check to see if still valid
				SYNC.release();
				IStructuredModel tempResult = getExistingModel(potentialId);
				if (tempResult!=null && document == tempResult.getStructuredDocument()) {
					result = getExistingModelForEdit(potentialId);
					break;
				}
			} else {
				SYNC.release();
			}
		}
		
		return result;
	}

	/**
	 * This is similar to the getModel method, except this method does not
	 * create a model. This method does increment the reference count (if it
	 * exists). If the model does not already exist in the cache of models,
	 * null is returned.
	 */
	public  IStructuredModel getExistingModelForEdit(IFile iFile) {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		Object id = calculateId(iFile);
		IStructuredModel result = getExistingModelForEdit(id);
		return result;
	}

	/**
	 * This is similar to the getModel method, except this method does not
	 * create a model. This method does increment the reference count (if it
	 * exists). If the model does not already exist in the cache of models,
	 * null is returned.
	 * 
	 * @deprecated use IFile form - this one will become protected or private
	 */
	public IStructuredModel getExistingModelForEdit(Object id) {

		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		IStructuredModel result = null;
		boolean doRelease = true;
		// let's see if we already have it in our cache
		try {
			SYNC.acquire();
			SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
			// if not, then we'll simply return null
			if (sharedObject != null) {
				// if shared object is in our cache, then simply increment its ref
				// count,
				// and return the object.
				SYNC.release();
				doRelease=false;
				synchronized(sharedObject) {
					if (sharedObject.doWait) {
						sharedObject.waitForLoadAttempt();
					}
					if (sharedObject.theSharedModel!=null) {
						_incrCount(sharedObject, EDIT);
					}
					result = sharedObject.theSharedModel;
				}
				trace("got existing model for Edit: ", id); //$NON-NLS-1$
				trace("   incremented referenceCountForEdit ", id, sharedObject.referenceCountForEdit); //$NON-NLS-1$
			}
		} finally {
			if (doRelease) {
				SYNC.release();
			}
		}
		
		return result;
	}

	/**
	 * Note: users of this 'model' must still release it when finished.
	 * Returns null if there's not a model corresponding to document.
	 */
	public IStructuredModel getExistingModelForRead(IDocument document) {
		IStructuredModel result = null;
		
		SYNC.acquire();		
		// create a snapshot
		Set ids = new HashSet(fManagedObjects.keySet());
		SYNC.release();
		for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
			Object potentialId = iterator.next();
			SYNC.acquire();	
			if (fManagedObjects.containsKey(potentialId)) {
				// check to see if still valid
				SYNC.release();
				IStructuredModel tempResult = getExistingModel(potentialId);
				if (tempResult!=null && document == tempResult.getStructuredDocument()) {
					result = getExistingModelForRead(potentialId);
					break;
				}
			} else {
				SYNC.release();
			}
		}
		
		return result;
	}

	public IStructuredModel getExistingModelForRead(IFile iFile) {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		Object id = calculateId(iFile);
		IStructuredModel result = getExistingModelForRead(id);
		return result;
	}

	/**
	 * This is similar to the getModel method, except this method does not
	 * create a model. This method does increment the reference count (if it
	 * exists). If the model does not already exist in the cache of models,
	 * null is returned.
	 * 
	 * @deprecated use IFile form - this one will become protected or private
	 */
	public  IStructuredModel getExistingModelForRead(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		IStructuredModel result = null;
		boolean doRelease = true;
		// let's see if we already have it in our cache
		try {
			SYNC.acquire();
			SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
			// if not, then we'll simply return null
			if (sharedObject != null) {
				// if shared object is in our cache, then simply increment its ref
				// count,
				// and return the object.
				SYNC.release();
				doRelease=false;

				synchronized(sharedObject) {
					if (sharedObject.doWait) {
						sharedObject.waitForLoadAttempt();
					}
					if (sharedObject.theSharedModel!=null) {
						_incrCount(sharedObject, READ);
					}
					result = sharedObject.theSharedModel;
				}
			}
		} finally {
			if (doRelease)
				SYNC.release();
		}
		return result;
	}

	/**
	 * @deprecated DMW: Tom, this is "special" for links builder Assuming its
	 *             still needed, wouldn't it be better to change to
	 *             getExistingModels()? -- will be removed. Its not thread
	 *             safe for one thread to get the Enumeration, when underlying
	 *             data could be changed in another thread.
	 */
	public  Enumeration getExistingModelIds() {
		try {
			SYNC.acquire();
			// create a copy
			Vector keys = new Vector( fManagedObjects.keySet() );
			return keys.elements();
		} finally {
			SYNC.release();
		}
	}

	// TODO: replace (or supplement) this is a "model info" association to the
	// IFile that created the model
	private IFile getFileFor(IStructuredModel model) {
		if (model == null)
			return null;
		String path = model.getBaseLocation();
		if (path == null || path.length() == 0) {
			Object id = model.getId();
			if (id == null)
				return null;
			path = id.toString();
		}
		// TOODO needs rework for linked resources
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IFile file = root.getFileForLocation(new Path(path));
		return file;
	}

	/**
	 * One of the primary forms to get a managed model
	 */
	public  IStructuredModel getModelForEdit(IFile iFile) throws IOException, CoreException {
		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, EDIT, null, null);
	}

	public  IStructuredModel getModelForEdit(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, EDIT, encodingRule);
	}

	public  IStructuredModel getModelForEdit(IFile iFile, String encoding, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, EDIT, encoding, lineDelimiter);
	}

	public  IStructuredModel getModelForEdit(IStructuredDocument document) {
		return _getModelFor(document, EDIT);
	}

	/**
	 * @see IModelManager
	 * @deprecated use IFile or String form
	 */
	public  IStructuredModel getModelForEdit(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {

		Assert.isNotNull(id, "requested model id can not be null"); //$NON-NLS-1$
		String stringId = id.toString();
		return getModelForEdit(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
	}

	/**
	 * @see IModelManager
	 * @deprecated - use IFile or String form
	 */
	public  IStructuredModel getModelForEdit(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {

		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		String stringId = id.toString();
		return getModelForEdit(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
	}

	public  IStructuredModel getModelForEdit(String id, InputStream inputStream, URIResolver resolver) throws IOException {
		if (id == null) {
			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$
		}
		IStructuredModel result = null;

		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
		IModelHandler handler = calculateType(id, istream);
		if (handler != null) {
			result = _commonCreateModel(istream, id, handler, resolver, EDIT, null, null);
		}
		else {
			Logger.log(Logger.INFO, "no model handler found for id"); //$NON-NLS-1$
		}
		return result;
	}

	/**
	 * One of the primary forms to get a managed model
	 */
	public  IStructuredModel getModelForRead(IFile iFile) throws IOException, CoreException {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, READ, null, null);
	}

	public  IStructuredModel getModelForRead(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, READ, encodingRule);
	}

	public  IStructuredModel getModelForRead(IFile iFile, String encodingName, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException {
		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		return _commonGetModel(iFile, READ, encodingName, lineDelimiter);
	}

	public  IStructuredModel getModelForRead(IStructuredDocument document) {
		return _getModelFor(document, READ);
	}

	/**
	 * @see IModelManager
	 * @deprecated use IFile or String form
	 */
	public  IStructuredModel getModelForRead(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		String stringId = id.toString();
		return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
	}

	/**
	 * @see IModelManager
	 * @deprecated use IFile form
	 */
	public  IStructuredModel getModelForRead(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		String stringId = id.toString();
		return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
	}

	public  IStructuredModel getModelForRead(String id, InputStream inputStream, URIResolver resolver) throws IOException {
		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
		IModelHandler handler = calculateType(id, istream);
		IStructuredModel result = null;
		result = _commonCreateModel(istream, id, handler, resolver, READ, null, null);
		return result;
	}

	/**
	 * @deprecated - only temporarily visible
	 */
	public ModelHandlerRegistry getModelHandlerRegistry() {
		if (fModelHandlerRegistry == null) {
			fModelHandlerRegistry = ModelHandlerRegistry.getInstance();
		}
		return fModelHandlerRegistry;
	}

	/**
	 * @see IModelManager#getNewModelForEdit(IFile, boolean)
	 */
	public  IStructuredModel getNewModelForEdit(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {
		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		SharedObject sharedObject = _commonNewModel(iFile, force);
		synchronized(sharedObject) {
			sharedObject.referenceCountForEdit = 1;
		}
		sharedObject.setLoaded();
		return sharedObject.theSharedModel;
	}

	/**
	 * @see IModelManager#getNewModelForRead(IFile, boolean)
	 */
	public  IStructuredModel getNewModelForRead(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {

		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
		SharedObject sharedObject = _commonNewModel(iFile, force);
		SYNC.acquire();
		synchronized(sharedObject) {
			if (sharedObject.theSharedModel!=null) {
				sharedObject.referenceCountForRead = 1;
			}
		}
		SYNC.release();
		sharedObject.setLoaded();
		return sharedObject.theSharedModel;
	}

	/**
	 * This function returns the reference count of underlying model.
	 * 
	 * @param id
	 *            Object The id of the model TODO: try to refine the design
	 *            not to use this function
	 */
	public  int getReferenceCount(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
	
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized (sharedObject) {
				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
			}
		} else {
			SYNC.release();
		}
		return count;
	}

	/**
	 * This function returns the reference count of underlying model.
	 * 
	 * @param id
	 *            Object The id of the model TODO: try to refine the design
	 *            not to use this function
	 */
	public int getReferenceCountForEdit(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForEdit;
			}
		} else {
			SYNC.release();
		}
		return count;
	}

	/**
	 * This function returns the reference count of underlying model.
	 * 
	 * @param id
	 *            Object The id of the model TODO: try to refine the design
	 *            not to use this function
	 */
	public int getReferenceCountForRead(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead;
			}
		} else {
			SYNC.release();
		}
		return count;
	}

	private void handleConvertLineDelimiters(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule, EncodingMemento encodingMemento) throws CoreException, MalformedOutputExceptionWithDetail, UnsupportedEncodingException {
		if (structuredDocument.getNumberOfLines() > 1) {
			convertLineDelimiters(structuredDocument, iFile);
		}
	}

	private void handleProgramError(Throwable t) {

		Logger.logException("Impossible Program Error", t); //$NON-NLS-1$
	}

	/**
	 * This function returns true if there are other references to the
	 * underlying model.
	 */
	public  boolean isShared(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
		boolean result = false;
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
			}
		} else {
			SYNC.release();
		}
		result = count > 1;
		return result;
	}

	/**
	 * This function returns true if there are other references to the
	 * underlying model.
	 * 
	 * @param id
	 *            Object The id of the model
	 */
	public  boolean isSharedForEdit(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
		boolean result = false;
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForEdit;
			}
		} else {
			SYNC.release();
		}
		result = count > 1;
		return result;
	}

	/**
	 * This function returns true if there are other references to the
	 * underlying model.
	 * 
	 * @param id
	 *            Object The id of the model
	 */
	public  boolean isSharedForRead(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		int count = 0;
		boolean result = false;
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject != null) {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead;
			}
		} else {
			SYNC.release();
		}
		result = count > 1;
		return result;
	}

	/**
	 * This method can be called to determine if the model manager is within a
	 * "aboutToChange" and "changed" sequence.
	 * 
	 * @deprecated the manager does not otherwise interact with these states
	 * @return false
	 */
	public boolean isStateChanging() {
		// doesn't seem to be used anymore
		return false;
	}

	/**
	 * This method changes the id of the model. TODO: try to refine the design
	 * not to use this function
	 */
	public void moveModel(Object oldId, Object newId) {
		Assert.isNotNull(oldId, "old id parameter can not be null"); //$NON-NLS-1$
		Assert.isNotNull(newId, "new id parameter can not be null"); //$NON-NLS-1$
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(oldId);
		// if not found in cache, ignore request.
		// this would normally be a program error
		if (sharedObject != null) {
			fManagedObjects.remove(oldId);
			fManagedObjects.put(newId, sharedObject);
		}
		SYNC.release();
	}

	private String readInputStream(InputStream inputStream, String ianaEncodingName) throws UnsupportedEncodingException, IOException {

		String allText = null;
		if ((ianaEncodingName != null) && (ianaEncodingName.length() != 0)) {
			String enc = CodedIO.getAppropriateJavaCharset(ianaEncodingName);
			if (enc == null) {
				// if no conversion was possible, let's assume that
				// the encoding is already a java encoding name, so we'll
				// proceed with that assumption. This is the case, for
				// example,
				// for the reload() procedure.
				// If in fact it is not a valid java encoding, then
				// the "allText=" line will cause an
				// UnsupportedEncodingException
				enc = ianaEncodingName;
			}
			allText = readInputStream(new InputStreamReader(inputStream, enc));
		}
		else {
			// we normally assume encoding is provided for this method, but if
			// not,
			// we'll use platform default
			allText = readInputStream(new InputStreamReader(inputStream));
		}
		return allText;
	}

	private String readInputStream(InputStreamReader inputStream) throws IOException {

		int numRead = 0;
		StringBuffer buffer = new StringBuffer();
		char tBuff[] = new char[READ_BUFFER_SIZE];
		while ((numRead = inputStream.read(tBuff, 0, tBuff.length)) != -1) {
			buffer.append(tBuff, 0, numRead);
		}
		// remember -- we didn't open stream ... so we don't close it
		return buffer.toString();
	}

	/*
	 * @see IModelManager#reinitialize(IStructuredModel)
	 */
	public IStructuredModel reinitialize(IStructuredModel model) {

		// getHandler (assume its the "new one")
		IModelHandler handler = model.getModelHandler();
		// getLoader for that new one
		IModelLoader loader = handler.getModelLoader();
		// ask it to reinitialize
		model = loader.reinitialize(model);
		// the loader should check to see if the one it received
		// is the same type it would normally create.
		// if not, it must "start from scratch" and create a whole
		// new one.
		// if it is of the same type, it should just 'replace text'
		// replacing all the existing text with the new text.
		// the important one is the JSP loader ... it should go through
		// its embedded content checking and initialization
		return model;
	}

	 void releaseFromEdit(IStructuredModel structuredModel) {
		Object id = structuredModel.getId();
		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
			cleanupDiscardedModel(structuredModel);
		}
		else {
			releaseFromEdit(id);
		}

	}
	
	 void releaseFromRead(IStructuredModel structuredModel) {
		Object id = structuredModel.getId();
		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
			cleanupDiscardedModel(structuredModel);
		}
		else {
			releaseFromRead(id);
		}

	}
	/**
	 * default for use in same package, not subclasses
	 * 
	 */
	 private void releaseFromEdit(Object id) {
		// ISSUE: many of these asserts should be changed to "logs"
		// and continue to limp along?

		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		SharedObject sharedObject = null;

		// ISSUE: here we need better "spec" what to do with
		// unmanaged or duplicated models. Release still needs
		// to be called on them, for now, but the model manager
		// doesn't need to do anything.
		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
			throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here");
		}
		else {
			SYNC.acquire();
			sharedObject = (SharedObject) fManagedObjects.get(id);
			SYNC.release();
			
			Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$
			sharedObject.waitForLoadAttempt();
			SYNC.acquire();
			synchronized(sharedObject) {
				_decrCount(sharedObject, EDIT);
				if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) {
					discardModel(id, sharedObject);
				}
			}
			SYNC.release();
			// if edit goes to zero, but still open for read,
			// then we should reload here, so we are in synch with
			// contents on disk.
			// ISSUE: should we check isDirty here?
			// ANSWER: here, for now now. model still has its own dirty
			// flag for some reason.
			// we need to address * that * too.

			synchronized(sharedObject) {
				if ((sharedObject.referenceCountForRead > 0) && (sharedObject.referenceCountForEdit == 0) && sharedObject.theSharedModel.isDirty()) {
					signalPreLifeCycleListenerRevert(sharedObject.theSharedModel);
					revertModel(id, sharedObject);
					/*
					 * Because model events are fired to notify about the
					 * revert's changes, and listeners can still get/release
					 * the model from this thread (locking prevents it being
					 * done from other threads), the reference counts could
					 * have changed since we entered this if block, and the
					 * model could have been discarded.  Check the counts again.
					 */
					if (sharedObject.referenceCountForRead > 0 && sharedObject.referenceCountForEdit == 0) {
						sharedObject.theSharedModel.setDirtyState(false);
					}
					signalPostLifeCycleListenerRevert(sharedObject.theSharedModel);
				}
			}
			
		}
	}

	// private for now, though public forms have been requested, in past.
	private void revertModel(Object id, SharedObject sharedObject) {
		IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument();
		FileBufferModelManager.getInstance().revert(structuredDocument);
	}

	private void signalPreLifeCycleListenerRevert(IStructuredModel structuredModel) {
		int type = ModelLifecycleEvent.MODEL_REVERT | 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);
	}

	private void signalPostLifeCycleListenerRevert(IStructuredModel structuredModel) {
		int type = ModelLifecycleEvent.MODEL_REVERT | 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 discardModel(Object id, SharedObject sharedObject) {
		SYNC.acquire();
		fManagedObjects.remove(id);
		SYNC.release();
		IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument();

		if (structuredDocument == null) {
			Platform.getLog(SSECorePlugin.getDefault().getBundle()).log(new Status(IStatus.ERROR, SSECorePlugin.ID, IStatus.ERROR, "Attempted to discard a structured model but the underlying document has already been set to null: " + sharedObject.theSharedModel.getBaseLocation(), null));
		}

		cleanupDiscardedModel(sharedObject.theSharedModel);
	}

	private void cleanupDiscardedModel(IStructuredModel structuredModel) {
		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
		/*
		 * This call (and setting the StructuredDocument to null) were
		 * previously done within the model itself, but for concurrency it
		 * must be done here during a synchronized release.
		 */
		structuredModel.getFactoryRegistry().release();

		/*
		 * For structured documents originating from file buffers, disconnect
		 * us from the file buffer, now.
		 */
		FileBufferModelManager.getInstance().releaseModel(structuredDocument);

		/*
		 * Setting the document to null is required since some subclasses of
		 * model might have "cleanup" of listeners, etc., to remove, which
		 * were initialized during the initial setStructuredDocument.
		 * 
		 * The model itself in particular may have internal listeners used to
		 * coordinate the document with its own "structure".
		 */
		structuredModel.setStructuredDocument(null);
	}

	
	/**
	 * default for use in same package, not subclasses
	 * 
	 */
	 private void releaseFromRead(Object id) {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
		SharedObject sharedObject = null;

		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
			throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here");
		}
		else {
			SYNC.acquire();
			sharedObject = (SharedObject) fManagedObjects.get(id);
			SYNC.release();
			Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$
			sharedObject.waitForLoadAttempt();
		}
		SYNC.acquire();
		synchronized(sharedObject) {
			_decrCount(sharedObject, READ);
			if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) {
				discardModel(id, sharedObject);
			}
		}
		SYNC.release();
	}

	/**
	 * This is similar to the getModel method, except this method does not use
	 * the cached version, but forces the cached version to be replaced with a
	 * fresh, unchanged version. Note: this method does not change any
	 * reference counts. Also, if there is not already a cached version of the
	 * model, then this call is essentially ignored (that is, it does not put
	 * a model in the cache) and returns null.
	 * 
	 * @deprecated - will become protected, use reload directly on model
	 */
	public  IStructuredModel reloadModel(Object id, java.io.InputStream inputStream) throws java.io.UnsupportedEncodingException {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$

		// get the existing model associated with this id
		IStructuredModel structuredModel = getExistingModel(id);
		// for the model to be null is probably an error (that is,
		// reload should not have been called, but we'll guard against
		// a null pointer example and return null if we are no longer managing
		// that model.
		if (structuredModel != null) {
			// get loader based on existing type
			// dmwTODO evaluate when reload should occur
			// with potentially new type (e.g. html 'save as' jsp).
			IModelHandler handler = structuredModel.getModelHandler();
			IModelLoader loader = handler.getModelLoader();
			// ask the loader to re-load
			loader.reload(Utilities.getMarkSupportedStream(inputStream), structuredModel);
			trace("re-loading model", id); //$NON-NLS-1$
		}
		return structuredModel;
	}

	public void saveModel(IFile iFile, String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
		Assert.isNotNull(iFile, "file parameter can not be null"); //$NON-NLS-1$
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$

		// let's see if we already have it in our cache
	
		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject == null || sharedObject.theSharedModel == null) {
			SYNC.release();
			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
		} 
		else {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			
			/**
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610
			 * 
			 * Sync removed from here to prevent deadlock. Although the model
			 * instance may disappear or be made invalid while the save is
			 * happening, the document itself still has the contents we're
			 * trying to save. Simultaneous saves should be throttled by
			 * resource locking without our intervention.
			 */
			boolean saved = false;
			// if this model was based on a File Buffer and we're writing back
			// to the same location, use the buffer to do the writing
			if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) {
				ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument());
				IPath fileLocation = FileBuffers.normalizeLocation(iFile.getFullPath());
				if (fileLocation.equals(buffer.getLocation())) {
					buffer.commit(new NullProgressMonitor(), true);
					saved = true;
				}
			}
			if (!saved) {
				IStructuredModel model = sharedObject.theSharedModel;
				IStructuredDocument document = model.getStructuredDocument();
				saveStructuredDocument(document, iFile, encodingRule);
				trace("saving model", id); //$NON-NLS-1$
			}
			sharedObject.theSharedModel.setDirtyState(false);
			sharedObject.theSharedModel.setNewState(false);
		}	
	}

	/**
	 * Saving the model really just means to save it's structured document.
	 * 
	 * @param id
	 * @param outputStream
	 * @param encodingRule
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 * @throws CoreException
	 */
	public void saveModel(String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$

		// let's see if we already have it in our cache

		SYNC.acquire();
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject == null) {
			SYNC.release();
			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
		}
		else {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			/**
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610
			 * 
			 * Sync removed from here to prevent deadlock. Although the model
			 * instance may disappear or be made invalid while the save is
			 * happening, the document itself still has the contents we're
			 * trying to save. Simultaneous saves should be throttled by
			 * resource locking without our intervention.
			 */
			/*
			 * if this model was based on a File Buffer and we're writing back
			 * to the same location, use the buffer to do the writing
			 */
			if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) {
				ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument());
				buffer.commit(new NullProgressMonitor(), true);
			}
			else {
				IFile iFile = getFileFor(sharedObject.theSharedModel);
				IStructuredModel model = sharedObject.theSharedModel;
				IStructuredDocument document = model.getStructuredDocument();
				saveStructuredDocument(document, iFile);
				trace("saving model", id); //$NON-NLS-1$
			}
			sharedObject.theSharedModel.setDirtyState(false);
			sharedObject.theSharedModel.setNewState(false);
		}
	}

	/**
	 * @deprecated - this method is less efficient than IFile form, since it
	 *             requires an extra "copy" of byte array, and should be avoid
	 *             in favor of the IFile form.
	 */
	public void saveModel(String id, OutputStream outputStream, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException {
		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$

		SYNC.acquire();
		// let's see if we already have it in our cache
		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
		if (sharedObject == null) {
			SYNC.release();
			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
		}
		else {
			SYNC.release();
			sharedObject.waitForLoadAttempt();
			synchronized(sharedObject) {
				CodedStreamCreator codedStreamCreator = new CodedStreamCreator();
				codedStreamCreator.set(sharedObject.theSharedModel.getId(), new DocumentReader(sharedObject.theSharedModel.getStructuredDocument()));
				codedStreamCreator.setPreviousEncodingMemento(sharedObject.theSharedModel.getStructuredDocument().getEncodingMemento());
				ByteArrayOutputStream byteArrayOutputStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule);
				byte[] outputBytes = byteArrayOutputStream.toByteArray();
				outputStream.write(outputBytes);
				trace("saving model", id); //$NON-NLS-1$
				sharedObject.theSharedModel.setDirtyState(false);
				sharedObject.theSharedModel.setNewState(false);
			}
		}
	}

	public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile) throws UnsupportedEncodingException, CoreException, IOException {
		saveStructuredDocument(structuredDocument, iFile, EncodingRule.CONTENT_BASED);
	}

	public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException {
		Assert.isNotNull(iFile, "file parameter can not be null"); //$NON-NLS-1$
		if (FileBufferModelManager.getInstance().isExistingBuffer(structuredDocument)) {
			ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(structuredDocument);
			if (buffer.getLocation().equals(iFile.getFullPath()) || buffer.getLocation().equals(iFile.getLocation())) {
				buffer.commit(new NullProgressMonitor(), true);
			}
		}
		else {
			// IModelHandler handler = calculateType(iFile);
			// IDocumentDumper dumper = handler.getDocumentDumper();
			CodedStreamCreator codedStreamCreator = new CodedStreamCreator();
			Reader reader = new DocumentReader(structuredDocument);
			codedStreamCreator.set(iFile, reader);
			codedStreamCreator.setPreviousEncodingMemento(structuredDocument.getEncodingMemento());
			EncodingMemento encodingMemento = codedStreamCreator.getCurrentEncodingMemento();

			// be sure document's is updated, in case exception is thrown in
			// getCodedByteArrayOutputStream
			structuredDocument.setEncodingMemento(encodingMemento);

			// Convert line delimiters after encoding memento is figured out,
			// but
			// before writing to output stream.
			handleConvertLineDelimiters(structuredDocument, iFile, encodingRule, encodingMemento);

			ByteArrayOutputStream codedByteStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule);
			InputStream codedStream = new ByteArrayInputStream(codedByteStream.toByteArray());
			if (iFile.exists())
				iFile.setContents(codedStream, true, true, null);
			else
				iFile.create(codedStream, false, null);
			codedByteStream.close();
			codedStream.close();
		}
	}

	/**
	 * Common trace method
	 */
	private void trace(String msg, Object id) {
		if (Logger.DEBUG_MODELMANAGER) {
			Logger.log(Logger.INFO, msg + " " + Utilities.makeShortId(id)); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Common trace method
	 */
	private void trace(String msg, Object id, int value) {
		if (Logger.DEBUG_MODELMANAGER) {
			Logger.log(Logger.INFO, msg + Utilities.makeShortId(id) + " (" + value + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
	}

	 boolean isIdInUse(String newId) {
			boolean inUse = false;
			SYNC.acquire();
			SharedObject object =(SharedObject) fManagedObjects.get(newId);
			if (object!=null) {
				inUse = object.theSharedModel!=null;
			}
			SYNC.release();
			return inUse;
		}
}
