/*******************************************************************************
 * Copyright (c) 2001, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.core.internal.model;

import java.io.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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
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;

/**
 * Not intended to be subclassed, referenced or instantiated by clients.
 * 
 * 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'.
 */
public class ModelManagerImpl implements IModelManager {

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

	/**
	 * A Data class to track our shared objects
	 */
	 static class SharedObject {
		int referenceCountForEdit;
		int referenceCountForRead;
		IStructuredModel theSharedModel;
		boolean initializing = true;
		boolean doWait = true;
		
		SharedObject(IStructuredModel sharedModel) {
			theSharedModel = sharedModel;
			referenceCountForRead = 0;
			referenceCountForEdit = 0;
		}
		
		/**
		 * 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 synchronized void waitForLoadAttempt() {
			while(initializing) {
				try {
					wait();
				}
				catch (InterruptedException e) {
					// ignore interruption!
				}
			}
		}
		
		/**
		 * Flags this model as loaded. All waiting methods on 
		 * {@link #waitForLoadAttempt()} will proceed after this 
		 * method returns. 
		 */
		public synchronized void setLoaded() {
			initializing = false;
			notifyAll();
		}
	}

	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(null);
				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 {
		boolean doRemove = false;
		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);
			} else {
				doRemove = true;
			}
		}
		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(null);
				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 = false;
		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) {
				sharedObject.theSharedModel = model;
				_initCount(sharedObject, rwType);
			} else {
				doRemove = true;
			}
		}
		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);
		IModelHandler handler = calculateType(iFile);
		URIResolver resolver = calculateURIResolver(iFile);
		IStructuredModel model = _commonGetModel(iFile, id, handler, resolver, rwType, encoding, lineDelimiter);

		return model;
	}

	private IStructuredModel _commonGetModel(IFile file, String id, IModelHandler handler, URIResolver resolver, 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(null);
					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 = false;
		synchronized(sharedObject) {
			sharedObject.doWait=false;
			IStructuredModel model = FileBufferModelManager.getInstance().getModel(file);
			sharedObject.doWait=true;
			if (model != null) {
				sharedObject.theSharedModel=model;
				_initCount(sharedObject, rwType);
			} else {
				doRemove = true;
			}
		}
		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(null);
			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);
		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(null);
				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);
					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, "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, "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);
		resolver.setFileBaseLocation(file.getLocation().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(null);
			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();
		//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, "IFile parameter 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();
			SYNC.acquire();
			synchronized (sharedObject) {
				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
			}
		}
		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();
			SYNC.acquire();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead;
			}
		}
		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();
			SYNC.acquire();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
			}
		}
		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();
			SYNC.acquire();
			synchronized(sharedObject) {
				count = sharedObject.referenceCountForRead;
			}
		}
		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) {
		org.eclipse.wst.sse.core.internal.util.Assert.isNotNull(oldId, "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);
					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 {

		// 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 {

		// 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();
			
			synchronized(sharedObject) {
				// sync here on to prevent a dispose from yanking the model from us!
				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 {

		// 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();
			synchronized(sharedObject) {
				// 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 {
		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 {
		if (FileBufferModelManager.getInstance().isExistingBuffer(structuredDocument)) {
			ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(structuredDocument);
			if (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;
		}
}
