/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jface.text;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.PatternSyntaxException;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SafeRunner;


/**
 * Abstract default implementation of <code>IDocument</code> and its extension
 * interfaces {@link org.eclipse.jface.text.IDocumentExtension},
 * {@link org.eclipse.jface.text.IDocumentExtension2},
 * {@link org.eclipse.jface.text.IDocumentExtension3},
 * {@link org.eclipse.jface.text.IDocumentExtension4}, as well as
 * {@link org.eclipse.jface.text.IRepairableDocument}.
 * <p>
 *
 * An <code>AbstractDocument</code> supports the following implementation
 * plug-ins:
 * <ul>
 * <li>a text store implementing {@link org.eclipse.jface.text.ITextStore} for
 *     storing and managing the document's content,</li>
 * <li>a line tracker implementing {@link org.eclipse.jface.text.ILineTracker}
 *     to map character positions to line numbers and vice versa</li>
 * </ul>
 * The document can dynamically change the text store when switching between
 * sequential rewrite mode and normal mode.
 * <p>
 *
 * This class must be subclassed. Subclasses must configure which implementation
 * plug-ins the document instance should use. Subclasses are not intended to
 * overwrite existing methods.
 *
 * @see org.eclipse.jface.text.ITextStore
 * @see org.eclipse.jface.text.ILineTracker
 */
public abstract class AbstractDocument implements IDocument, IDocumentExtension, IDocumentExtension2, IDocumentExtension3, IDocumentExtension4, IRepairableDocument, IRepairableDocumentExtension {

	/**
	 * Tells whether this class is in debug mode.
	 * @since 3.1
	 */
	private static final boolean DEBUG= false;


	/**
	 * Inner class to bundle a registered post notification replace operation together with its
	 * owner.
	 *
	 * @since 2.0
	 */
	static private class RegisteredReplace {
		/** The owner of this replace operation. */
		IDocumentListener fOwner;
		/** The replace operation */
		IDocumentExtension.IReplace fReplace;

		/**
		 * Creates a new bundle object.
		 * @param owner the document listener owning the replace operation
		 * @param replace the replace operation
		 */
		RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
			fOwner= owner;
			fReplace= replace;
		}
	}


	/** The document's text store */
	private ITextStore   fStore;
	/** The document's line tracker */
	private ILineTracker fTracker;
	/** The registered document listeners */
	private ListenerList<IDocumentListener> fDocumentListeners;
	/** The registered pre-notified document listeners */
	private ListenerList<IDocumentListener> fPrenotifiedDocumentListeners;
	/** The registered document partitioning listeners */
	private ListenerList<IDocumentPartitioningListener> fDocumentPartitioningListeners;
	/** All positions managed by the document ordered by their start positions. */
	private Map<String, List<Position>> fPositions;
	/**
	 * All positions managed by the document ordered by their end positions.
	 * @since 3.4
	 */
	private Map<String, List<Position>> fEndPositions;
	/** All registered document position updaters */
	private List<IPositionUpdater> fPositionUpdaters;
	/**
	 * The list of post notification changes
	 * @since 2.0
	 */
	private List<RegisteredReplace> fPostNotificationChanges;
	/**
	 * The reentrance count for post notification changes.
	 * @since 2.0
	 */
	private int fReentranceCount= 0;
	/**
	 * Indicates whether post notification change processing has been stopped.
	 * @since 2.0
	 */
	private int fStoppedCount= 0;
	/**
	 * Indicates whether the registration of post notification changes should be ignored.
	 * @since 2.1
	 */
	private boolean fAcceptPostNotificationReplaces= true;
	/**
	 * Indicates whether the notification of listeners has been stopped.
	 * @since 2.1
	 */
	private int fStoppedListenerNotification= 0;
	/**
	 * The document event to be sent after listener notification has been resumed.
	 * @since 2.1
	 */
	private DocumentEvent fDeferredDocumentEvent;
	/**
	 * The registered document partitioners.
	 * @since 3.0
	 */
	private Map<String, IDocumentPartitioner> fDocumentPartitioners;
	/**
	 * The partitioning changed event.
	 * @since 3.0
	 */
	private DocumentPartitioningChangedEvent fDocumentPartitioningChangedEvent;
	/**
	 * The find/replace document adapter.
	 * @since 3.0
	 */
	private FindReplaceDocumentAdapter fFindReplaceDocumentAdapter;
	/**
	 * The active document rewrite session.
	 * @since 3.1
	 */
	private DocumentRewriteSession fDocumentRewriteSession;
	/**
	 * The registered document rewrite session listeners.
	 * @since 3.1
	 */
	private List<IDocumentRewriteSessionListener> fDocumentRewriteSessionListeners;
	/**
	 * The current modification stamp.
	 * @since 3.1
	 */
	private long fModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
	/**
	 * Keeps track of next modification stamp.
	 * @since 3.1.1
	 */
	private long fNextModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
	/**
	 * This document's default line delimiter.
	 * @since 3.1
	 */
	private String fInitialLineDelimiter;


	/**
	 * The default constructor does not perform any configuration
	 * but leaves it to the clients who must first initialize the
	 * implementation plug-ins and then call <code>completeInitialization</code>.
	 * Results in the construction of an empty document.
	 */
	protected AbstractDocument() {
		fModificationStamp= getNextModificationStamp();
	}


	/**
	 * Returns the document's text store. Assumes that the
	 * document has been initialized with a text store.
	 *
	 * @return the document's text store
	 */
	protected ITextStore getStore() {
		Assert.isNotNull(fStore);
		return fStore;
	}

	/**
	 * Returns the document's line tracker. Assumes that the
	 * document has been initialized with a line tracker.
	 *
	 * @return the document's line tracker
	 */
	protected ILineTracker getTracker() {
		Assert.isNotNull(fTracker);
		return fTracker;
	}

	private static <T> List<T> asList(ListenerList<T> listenerList) {
		List<?> list= Arrays.asList(listenerList.getListeners());
		@SuppressWarnings("unchecked")
		List<T> castList= (List<T>) list;
		return castList;
	}


	/**
	 * Returns the document's document listeners.
	 *
	 * @return the document's document listeners
	 */
	protected List<IDocumentListener> getDocumentListeners() {
		return asList(fDocumentListeners);
	}

	/**
	 * Returns the document's partitioning listeners.
	 *
	 * @return the document's partitioning listeners
	 */
	protected List<IDocumentPartitioningListener> getDocumentPartitioningListeners() {
		return asList(fDocumentPartitioningListeners);
	}

	/**
	 * Returns all positions managed by the document grouped by category.
	 *
	 * @return the document's positions
	 */
	protected Map<String, List<Position>> getDocumentManagedPositions() {
		return fPositions;
	}

	@Override
	public IDocumentPartitioner getDocumentPartitioner() {
		return getDocumentPartitioner(DEFAULT_PARTITIONING);
	}



	//--- implementation configuration interface ------------

	/**
	 * Sets the document's text store.
	 * Must be called at the beginning of the constructor.
	 *
	 * @param store the document's text store
	 */
	protected void setTextStore(ITextStore store) {
		fStore= store;
	}

	/**
	 * Sets the document's line tracker.
	 * Must be called at the beginning of the constructor.
	 *
	 * @param tracker the document's line tracker
	 */
	protected void setLineTracker(ILineTracker tracker) {
		fTracker= tracker;
	}

	@Override
	public void setDocumentPartitioner(IDocumentPartitioner partitioner) {
		setDocumentPartitioner(DEFAULT_PARTITIONING, partitioner);
	}

	/**
	 * Initializes document listeners, positions, and position updaters.
	 * Must be called inside the constructor after the implementation plug-ins
	 * have been set.
	 */
	protected void completeInitialization() {

		fPositions= new HashMap<>();
		fEndPositions= new HashMap<>();
		fPositionUpdaters= new ArrayList<>();
		fDocumentListeners= new ListenerList<>(ListenerList.IDENTITY);
		fPrenotifiedDocumentListeners= new ListenerList<>(ListenerList.IDENTITY);
		fDocumentPartitioningListeners= new ListenerList<>(ListenerList.IDENTITY);
		fDocumentRewriteSessionListeners= new ArrayList<>();

		addPositionCategory(DEFAULT_CATEGORY);
		addPositionUpdater(new DefaultPositionUpdater(DEFAULT_CATEGORY));
	}


	//-------------------------------------------------------

	@Override
	public void addDocumentListener(IDocumentListener listener) {
		Assert.isNotNull(listener);
		fDocumentListeners.add(listener);
	}

	@Override
	public void removeDocumentListener(IDocumentListener listener) {
		Assert.isNotNull(listener);
		fDocumentListeners.remove(listener);
	}

	@Override
	public void addPrenotifiedDocumentListener(IDocumentListener listener) {
		Assert.isNotNull(listener);
		fPrenotifiedDocumentListeners.add(listener);
	}

	@Override
	public void removePrenotifiedDocumentListener(IDocumentListener listener) {
		Assert.isNotNull(listener);
		fPrenotifiedDocumentListeners.remove(listener);
	}

	@Override
	public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) {
		Assert.isNotNull(listener);
		fDocumentPartitioningListeners.add(listener);
	}

	@Override
	public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) {
		Assert.isNotNull(listener);
		fDocumentPartitioningListeners.remove(listener);
	}

	@Override
	public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException  {

		if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getLength()))
			throw new BadLocationException();

		if (category == null)
			throw new BadPositionCategoryException();

		List<Position> list= fPositions.get(category);
		if (list == null)
			throw new BadPositionCategoryException();
		list.add(computeIndexInPositionList(list, position.offset), position);

		List<Position> endPositions= fEndPositions.get(category);
		if (endPositions == null)
			throw new BadPositionCategoryException();
		endPositions.add(computeIndexInPositionList(endPositions, position.offset + position.length - 1, false), position);
	}

	@Override
	public void addPosition(Position position) throws BadLocationException {
		try {
			addPosition(DEFAULT_CATEGORY, position);
		} catch (BadPositionCategoryException e) {
		}
	}

	@Override
	public void addPositionCategory(String category) {

		if (category == null)
			return;

		if (!containsPositionCategory(category)) {
			fPositions.put(category, new ArrayList<>());
			fEndPositions.put(category, new ArrayList<>());
		}
	}

	@Override
	public void addPositionUpdater(IPositionUpdater updater) {
		insertPositionUpdater(updater, fPositionUpdaters.size());
	}

	@Override
	public boolean containsPosition(String category, int offset, int length) {

		if (category == null)
			return false;

		List<Position> list= fPositions.get(category);
		if (list == null)
			return false;

		int size= list.size();
		if (size == 0)
			return false;

		int index= computeIndexInPositionList(list, offset);
		if (index < size) {
			Position p= list.get(index);
			while (p != null && p.offset == offset) {
				if (p.length == length)
					return true;
				++ index;
				p= (index < size) ? list.get(index) : null;
			}
		}

		return false;
	}

	@Override
	public boolean containsPositionCategory(String category) {
		if (category != null)
			return fPositions.containsKey(category);
		return false;
	}


	/**
	 * Computes the index in the list of positions at which a position with the given
	 * offset would be inserted. The position is supposed to become the first in this list
	 * of all positions with the same offset.
	 *
	 * @param positions the list in which the index is computed
	 * @param offset the offset for which the index is computed
	 * @return the computed index
	 *
	 * @see IDocument#computeIndexInCategory(String, int)
	 * @deprecated As of 3.4, replaced by {@link #computeIndexInPositionList(List, int, boolean)}
	 */
	@Deprecated
	protected int computeIndexInPositionList(List<? extends Position> positions, int offset) {
		return computeIndexInPositionList(positions, offset, true);
	}

	/**
	 * Computes the index in the list of positions at which a position with the given
	 * position would be inserted. The position to insert is supposed to become the first
	 * in this list of all positions with the same position.
	 *
	 * @param positions the list in which the index is computed
	 * @param offset the offset for which the index is computed
	 * @param orderedByOffset <code>true</code> if ordered by offset, false if ordered by end position
	 * @return the computed index
	 * @since 3.4
	 */
	protected int computeIndexInPositionList(List<? extends Position> positions, int offset, boolean orderedByOffset) {
		if (positions.size() == 0)
			return 0;

		int left= 0;
		int right= positions.size() -1;
		int mid= 0;
		Position p= null;

		while (left < right) {

			mid= (left + right) / 2;

			p= positions.get(mid);
			int pOffset= getOffset(orderedByOffset, p);
			if (offset < pOffset) {
				if (left == mid)
					right= left;
				else
					right= mid -1;
			} else if (offset > pOffset) {
				if (right == mid)
					left= right;
				else
					left= mid  +1;
			} else if (offset == pOffset) {
				left= right= mid;
			}

		}

		int pos= left;
		p= positions.get(pos);
		int pPosition= getOffset(orderedByOffset, p);
		if (offset > pPosition) {
			// append to the end
			pos++;
		} else {
			// entry will become the first of all entries with the same offset
			do {
				--pos;
				if (pos < 0)
					break;
				p= positions.get(pos);
				pPosition= getOffset(orderedByOffset, p);
			} while (offset == pPosition);
			++pos;
		}

		Assert.isTrue(0 <= pos && pos <= positions.size());

		return pos;
	}

	/*
	 * @since 3.4
	 */
	private int getOffset(boolean orderedByOffset, Position position) {
		if (orderedByOffset || position.getLength() == 0)
			return position.getOffset();
		return position.getOffset() + position.getLength() - 1;
	}

	@Override
	public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException {

		if (0 > offset || offset > getLength())
			throw new BadLocationException();

		List<Position> c= fPositions.get(category);
		if (c == null)
			throw new BadPositionCategoryException();

		return computeIndexInPositionList(c, offset);
	}

	/**
	 * Fires the document partitioning changed notification to all registered
	 * document partitioning listeners. Uses a robust iterator.
	 *
	 * @deprecated as of 2.0. Use <code>fireDocumentPartitioningChanged(IRegion)</code> instead.
	 */
	@Deprecated
	protected void fireDocumentPartitioningChanged() {
		if (fDocumentPartitioningListeners == null)
			return;

		for (IDocumentPartitioningListener listener : fDocumentPartitioningListeners) {
			listener.documentPartitioningChanged(this);
		}
	}

	/**
	 * Fires the document partitioning changed notification to all registered
	 * document partitioning listeners. Uses a robust iterator.
	 *
	 * @param region the region in which partitioning has changed
	 *
	 * @see IDocumentPartitioningListenerExtension
	 * @since 2.0
	 * @deprecated as of 3.0. Use
	 *             <code>fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent)</code>
	 *             instead.
	 */
	@Deprecated
	protected void fireDocumentPartitioningChanged(IRegion region) {
		if (fDocumentPartitioningListeners == null)
			return;

		for (IDocumentPartitioningListener l : fDocumentPartitioningListeners) {
			try {
				if (l instanceof IDocumentPartitioningListenerExtension)
					((IDocumentPartitioningListenerExtension)l).documentPartitioningChanged(this, region);
				else
					l.documentPartitioningChanged(this);
			} catch (Exception ex) {
				log(ex);
			}
		}
	}

	/**
	 * Fires the document partitioning changed notification to all registered
	 * document partitioning listeners. Uses a robust iterator.
	 *
	 * @param event the document partitioning changed event
	 *
	 * @see IDocumentPartitioningListenerExtension2
	 * @since 3.0
	 */
	protected void fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent event) {
		if (fDocumentPartitioningListeners == null)
			return;

		for (IDocumentPartitioningListener l : fDocumentPartitioningListeners) {
			try {
				if (l instanceof IDocumentPartitioningListenerExtension2) {
					IDocumentPartitioningListenerExtension2 extension2= (IDocumentPartitioningListenerExtension2)l;
					extension2.documentPartitioningChanged(event);
				} else if (l instanceof IDocumentPartitioningListenerExtension) {
					IDocumentPartitioningListenerExtension extension= (IDocumentPartitioningListenerExtension)l;
					extension.documentPartitioningChanged(this, event.getCoverage());
				} else {
					l.documentPartitioningChanged(this);
				}
			} catch (Exception ex) {
				log(ex);
			}
		}
	}

	/**
	 * Fires the given document event to all registers document listeners informing them
	 * about the forthcoming document manipulation. Uses a robust iterator.
	 *
	 * @param event the event to be sent out
	 */
	protected void fireDocumentAboutToBeChanged(DocumentEvent event) {

		// IDocumentExtension
		if (fReentranceCount == 0)
			flushPostNotificationChanges();

		if (fDocumentPartitioners != null) {
			Iterator<IDocumentPartitioner> e= fDocumentPartitioners.values().iterator();
			while (e.hasNext()) {
				IDocumentPartitioner p= e.next();
				if (p instanceof IDocumentPartitionerExtension3) {
					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) p;
					if (extension.getActiveRewriteSession() != null)
						continue;
				}
				try {
					p.documentAboutToBeChanged(event);
				} catch (Exception ex) {
					log(ex);
				}
			}
		}

		for (IDocumentListener listener : fPrenotifiedDocumentListeners) {
			try {
				listener.documentAboutToBeChanged(event);
			} catch (Exception ex) {
				log(ex);
			}
		}

		for (IDocumentListener listener : fDocumentListeners) {
			try {
				listener.documentAboutToBeChanged(event);
			} catch (Exception ex) {
				log(ex);
			}
		}

	}

	/**
	 * Updates document partitioning and document positions according to the
	 * specification given by the document event.
	 *
	 * @param event the document event describing the change to which structures must be adapted
	 */
	protected void updateDocumentStructures(DocumentEvent event) {

		if (fDocumentPartitioners != null) {
			fDocumentPartitioningChangedEvent= new DocumentPartitioningChangedEvent(this);
			for (Entry<String, IDocumentPartitioner> entry : fDocumentPartitioners.entrySet()) {

				String partitioning= entry.getKey();
				IDocumentPartitioner partitioner= entry.getValue();

				if (partitioner instanceof IDocumentPartitionerExtension3) {
					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
					if (extension.getActiveRewriteSession() != null)
						continue;
				}

				if (partitioner instanceof IDocumentPartitionerExtension) {
					IDocumentPartitionerExtension extension= (IDocumentPartitionerExtension) partitioner;
					IRegion r= extension.documentChanged2(event);
					if (r != null)
						fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, r.getOffset(), r.getLength());
				} else {
					if (partitioner.documentChanged(event))
						fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, 0, event.getDocument().getLength());
				}
			}
		}

		if (fPositions.size() > 0)
			updatePositions(event);
	}

	/**
	 * Notifies all listeners about the given document change. Uses a robust
	 * iterator.
	 * <p>
	 * Executes all registered post notification replace operation.
	 *
	 * @param event the event to be sent out.
	 */
	protected void doFireDocumentChanged(DocumentEvent event) {
		boolean changed= fDocumentPartitioningChangedEvent != null && !fDocumentPartitioningChangedEvent.isEmpty();
		IRegion change= changed ? fDocumentPartitioningChangedEvent.getCoverage() : null;
		doFireDocumentChanged(event, changed, change);
	}

	/**
	 * Notifies all listeners about the given document change.
	 * Uses a robust iterator. <p>
	 * Executes all registered post notification replace operation.
	 *
	 * @param event the event to be sent out
	 * @param firePartitionChange <code>true</code> if a partition change notification should be sent
	 * @param partitionChange the region whose partitioning changed
	 * @since 2.0
	 * @deprecated as of 3.0. Use <code>doFireDocumentChanged2(DocumentEvent)</code> instead; this method will be removed.
	 */
	@Deprecated
	protected void doFireDocumentChanged(DocumentEvent event, boolean firePartitionChange, IRegion partitionChange) {
		doFireDocumentChanged2(event);
	}

	/**
	 * Notifies all listeners about the given document change. Uses a robust
	 * iterator.
	 * <p>
	 * Executes all registered post notification replace operation.
	 * <p>
	 * This method will be renamed to <code>doFireDocumentChanged</code>.
	 *
	 * @param event the event to be sent out
	 * @since 3.0
	 */
	protected void doFireDocumentChanged2(DocumentEvent event) {

		DocumentPartitioningChangedEvent p= fDocumentPartitioningChangedEvent;
		fDocumentPartitioningChangedEvent= null;
		if (p != null && !p.isEmpty())
			fireDocumentPartitioningChanged(p);

		for (IDocumentListener listener : fPrenotifiedDocumentListeners) {
			try {
				listener.documentChanged(event);
			} catch (Exception ex) {
				log(ex);
			}
		}

		for (IDocumentListener listener : fDocumentListeners) {
			try {
				listener.documentChanged(event);
			} catch (Exception ex) {
				log(ex);
			}
		}

		// IDocumentExtension
		++ fReentranceCount;
		try {
			if (fReentranceCount == 1)
				executePostNotificationChanges();
		} finally {
			-- fReentranceCount;
		}
	}

	/**
	 * Updates the internal document structures and informs all document listeners
	 * if listener notification has been enabled. Otherwise it remembers the event
	 * to be sent to the listeners on resume.
	 *
	 * @param event the document event to be sent out
	 */
	protected void fireDocumentChanged(DocumentEvent event) {
		updateDocumentStructures(event);

		if (fStoppedListenerNotification == 0)
			doFireDocumentChanged(event);
		else
			fDeferredDocumentEvent= event;
	}

	@Override
	public char getChar(int pos) throws BadLocationException {
		if ((0 > pos) || (pos >= getLength()))
			throw new BadLocationException();
		return getStore().get(pos);
	}

	@Override
	public String getContentType(int offset) throws BadLocationException {
		String contentType= null;
		try {
			contentType= getContentType(DEFAULT_PARTITIONING, offset, false);
			Assert.isNotNull(contentType);
		} catch (BadPartitioningException e) {
			Assert.isTrue(false);
		}
		return contentType;
	}

	@Override
	public String[] getLegalContentTypes() {
		String[] contentTypes= null;
		try {
			contentTypes= getLegalContentTypes(DEFAULT_PARTITIONING);
			Assert.isNotNull(contentTypes);
		} catch (BadPartitioningException e) {
			Assert.isTrue(false);
		}
		return contentTypes;
	}

	@Override
	public int getLength() {
		return getStore().getLength();
	}

	@Override
	public String getLineDelimiter(int line) throws BadLocationException {
		return getTracker().getLineDelimiter(line);
	}

	@Override
	public String[] getLegalLineDelimiters() {
		return getTracker().getLegalLineDelimiters();
	}

	@Override
	public String getDefaultLineDelimiter() {

		String lineDelimiter= null;

		try {
			lineDelimiter= getLineDelimiter(0);
		} catch (BadLocationException x) {
		}

		if (lineDelimiter != null)
			return lineDelimiter;

		if (fInitialLineDelimiter != null)
			return fInitialLineDelimiter;

		String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
		String[] delimiters= getLegalLineDelimiters();
		Assert.isTrue(delimiters.length > 0);
		for (String delimiter : delimiters) {
			if (delimiter.equals(sysLineDelimiter)) {
				lineDelimiter= sysLineDelimiter;
				break;
			}
		}

		if (lineDelimiter == null)
			lineDelimiter= delimiters[0];

		return lineDelimiter;

	}

	@Override
	public void setInitialLineDelimiter(String lineDelimiter) {
		Assert.isNotNull(lineDelimiter);
		fInitialLineDelimiter= lineDelimiter;
	}

	@Override
	public int getLineLength(int line) throws BadLocationException {
		return getTracker().getLineLength(line);
	}

	@Override
	public int getLineOfOffset(int pos) throws BadLocationException {
		return getTracker().getLineNumberOfOffset(pos);
	}

	@Override
	public int getLineOffset(int line) throws BadLocationException {
		return getTracker().getLineOffset(line);
	}

	@Override
	public IRegion getLineInformation(int line) throws BadLocationException {
		return getTracker().getLineInformation(line);
	}

	@Override
	public IRegion getLineInformationOfOffset(int offset) throws BadLocationException {
		return getTracker().getLineInformationOfOffset(offset);
	}

	@Override
	public int getNumberOfLines() {
		return getTracker().getNumberOfLines();
	}

	@Override
	public int getNumberOfLines(int offset, int length) throws BadLocationException {
		return getTracker().getNumberOfLines(offset, length);
	}

	@Override
	public int computeNumberOfLines(String text) {
		return getTracker().computeNumberOfLines(text);
	}

	@Override
	public ITypedRegion getPartition(int offset) throws BadLocationException {
		ITypedRegion partition= null;
		try {
			partition= getPartition(DEFAULT_PARTITIONING, offset, false);
			Assert.isNotNull(partition);
		} catch (BadPartitioningException e) {
			Assert.isTrue(false);
		}
		return  partition;
	}

	@Override
	public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException {
		ITypedRegion[] partitioning= null;
		try {
			partitioning= computePartitioning(DEFAULT_PARTITIONING, offset, length, false);
			Assert.isNotNull(partitioning);
		} catch (BadPartitioningException e) {
			Assert.isTrue(false);
		}
		return partitioning;
	}

	@Override
	public Position[] getPositions(String category) throws BadPositionCategoryException {

		if (category == null)
			throw new BadPositionCategoryException();

		List<Position> c= fPositions.get(category);
		if (c == null)
			throw new BadPositionCategoryException();

		Position[] positions= new Position[c.size()];
		c.toArray(positions);
		return positions;
	}

	@Override
	public String[] getPositionCategories() {
		String[] categories= new String[fPositions.size()];
		Iterator<String> keys= fPositions.keySet().iterator();
		for (int i= 0; i < categories.length; i++)
			categories[i]= keys.next();
		return categories;
	}

	@Override
	public IPositionUpdater[] getPositionUpdaters() {
		IPositionUpdater[] updaters= new IPositionUpdater[fPositionUpdaters.size()];
		fPositionUpdaters.toArray(updaters);
		return updaters;
	}

	@Override
	public String get() {
		return getStore().get(0, getLength());
	}

	@Override
	public String get(int pos, int length) throws BadLocationException {
		int myLength= getLength();
		if ((0 > pos) || (0 > length) || (pos + length > myLength))
			throw new BadLocationException();
		return getStore().get(pos, length);
	}

	@Override
	public void insertPositionUpdater(IPositionUpdater updater, int index) {

		for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) {
			if (fPositionUpdaters.get(i) == updater)
				return;
		}

		if (index == fPositionUpdaters.size())
			fPositionUpdaters.add(updater);
		else
			fPositionUpdaters.add(index, updater);
	}

	@Override
	public void removePosition(String category, Position position) throws BadPositionCategoryException {

		if (position == null)
			return;

		if (category == null)
			throw new BadPositionCategoryException();

		List<Position> c= fPositions.get(category);
		if (c == null)
			throw new BadPositionCategoryException();
		removeFromPositionsList(c, position, true);

		List<Position> endPositions= fEndPositions.get(category);
		if (endPositions == null)
			throw new BadPositionCategoryException();
		removeFromPositionsList(endPositions, position, false);
	}

	/**
	 * Remove the given position form the given list of positions based on identity not equality.
	 *
	 * @param positions a list of positions
	 * @param position the position to remove
	 * @param orderedByOffset true if <code>positions</code> is ordered by offset, false if ordered by end position
	 * @since 3.4
	 */
	private void removeFromPositionsList(List<Position> positions, Position position, boolean orderedByOffset) {
		int size= positions.size();

		//Assume position is somewhere near it was before
		int index= computeIndexInPositionList(positions, orderedByOffset ? position.offset : position.offset + position.length - 1, orderedByOffset);
		if (index < size && positions.get(index) == position) {
			positions.remove(index);
			return;
		}

		int back= index - 1;
		int forth= index + 1;
		while (back >= 0 || forth < size) {
			if (back >= 0) {
				if (position == positions.get(back)) {
					positions.remove(back);
					return;
				}
				back--;
			}

			if (forth < size) {
				if (position == positions.get(forth)) {
					positions.remove(forth);
					return;
				}
				forth++;
			}
		}
	}

	@Override
	public void removePosition(Position position) {
		try {
			removePosition(DEFAULT_CATEGORY, position);
		} catch (BadPositionCategoryException e) {
		}
	}

	@Override
	public void removePositionCategory(String category) throws BadPositionCategoryException {

		if (category == null)
			return;

		if ( !containsPositionCategory(category))
			throw new BadPositionCategoryException();

		fPositions.remove(category);
		fEndPositions.remove(category);
	}

	@Override
	public void removePositionUpdater(IPositionUpdater updater) {
		for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) {
			if (fPositionUpdaters.get(i) == updater) {
				fPositionUpdaters.remove(i);
				return;
			}
		}
	}

	private long getNextModificationStamp() {
		if (fNextModificationStamp == Long.MAX_VALUE || fNextModificationStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP)
			fNextModificationStamp= 0;
		else
			fNextModificationStamp= fNextModificationStamp + 1;

		return fNextModificationStamp;
	}

	@Override
	public long getModificationStamp() {
		return fModificationStamp;
	}

	@Override
	public void replace(int pos, int length, String text, long modificationStamp) throws BadLocationException {
		if ((0 > pos) || (0 > length) || (pos + length > getLength()))
			throw new BadLocationException();

		DocumentEvent e= new DocumentEvent(this, pos, length, text);
		fireDocumentAboutToBeChanged(e);

		getStore().replace(pos, length, text);
		getTracker().replace(pos, length, text);

		fModificationStamp= modificationStamp;
		fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
		e.fModificationStamp= fModificationStamp;

		fireDocumentChanged(e);
	}

	/**
	 * {@inheritDoc}
	 *
	 * @since 3.4
	 */
	@Override
	public boolean isLineInformationRepairNeeded(int offset, int length, String text) throws BadLocationException {
		return false;
	}

	@Override
	public void replace(int pos, int length, String text) throws BadLocationException {
		if (length == 0 && (text == null || text.length() == 0))
			replace(pos, length, text, getModificationStamp());
		else
			replace(pos, length, text, getNextModificationStamp());
	}

	@Override
	public void set(String text) {
		set(text, getNextModificationStamp());
	}

	@Override
	public void set(String text, long modificationStamp) {
		int length= getStore().getLength();

		DocumentEvent e= new DocumentEvent(this, 0, length, text);
		fireDocumentAboutToBeChanged(e);

		getStore().set(text);
		getTracker().set(text);

		fModificationStamp= modificationStamp;
		fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
		e.fModificationStamp= fModificationStamp;

		fireDocumentChanged(e);
	}

	/**
	 * Updates all positions of all categories to the change described by the
	 * document event. All registered document updaters are called in the
	 * sequence they have been arranged. Uses a robust iterator.
	 *
	 * @param event the document event describing the change to which to adapt
	 *            the positions
	 */
	protected void updatePositions(DocumentEvent event) {
		List<IPositionUpdater> list= new ArrayList<>(fPositionUpdaters);
		Iterator<IPositionUpdater> e= list.iterator();
		while (e.hasNext()) {
			IPositionUpdater u= e.next();
			u.update(event);
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @deprecated as of 3.0 search is provided by {@link FindReplaceDocumentAdapter}
	 */
	@Deprecated
	@Override
	public int search(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException {
		try {
			IRegion region= getFindReplaceDocumentAdapter().find(startPosition, findString, forwardSearch, caseSensitive, wholeWord, false);
			return region == null ?  -1 : region.getOffset();
		} catch (IllegalStateException ex) {
			return -1;
		} catch (PatternSyntaxException ex) {
			return -1;
		}
	}

	/**
	 * Returns the find/replace adapter for this document.
	 *
	 * @return this document's find/replace document adapter
	 * @since 3.0
	 */
	private FindReplaceDocumentAdapter getFindReplaceDocumentAdapter() {
		if (fFindReplaceDocumentAdapter == null)
			fFindReplaceDocumentAdapter= new FindReplaceDocumentAdapter(this);

		return fFindReplaceDocumentAdapter;
	}

	/**
	 * Flushes all registered post notification changes.
	 *
	 * @since 2.0
	 */
	private void flushPostNotificationChanges() {
		if (fPostNotificationChanges != null)
			fPostNotificationChanges.clear();
	}

	/**
	 * Executes all registered post notification changes. The process is
	 * repeated until no new post notification changes are added.
	 *
	 * @since 2.0
	 */
	private void executePostNotificationChanges() {

		if (fStoppedCount > 0)
			return;

		while (fPostNotificationChanges != null) {
			List<RegisteredReplace> changes= fPostNotificationChanges;
			fPostNotificationChanges= null;

			Iterator<RegisteredReplace> e= changes.iterator();
			while (e.hasNext()) {
				RegisteredReplace replace= e.next();
				replace.fReplace.perform(this, replace.fOwner);
			}
		}
	}

	@Override
	public void acceptPostNotificationReplaces() {
		fAcceptPostNotificationReplaces= true;
	}

	@Override
	public void ignorePostNotificationReplaces() {
		fAcceptPostNotificationReplaces= false;
	}

	@Override
	public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
		if (fAcceptPostNotificationReplaces) {
			if (fPostNotificationChanges == null)
				fPostNotificationChanges= new ArrayList<>(1);
			fPostNotificationChanges.add(new RegisteredReplace(owner, replace));
		}
	}

	@Override
	public void stopPostNotificationProcessing() {
		++ fStoppedCount;
	}

	@Override
	public void resumePostNotificationProcessing() {
		-- fStoppedCount;
		if (fStoppedCount == 0 && fReentranceCount == 0)
			executePostNotificationChanges();
	}

	/**
	 * {@inheritDoc}
	 *
	 * @since 2.0
	 * @deprecated since 3.1. Use
	 *             {@link IDocumentExtension4#startRewriteSession(DocumentRewriteSessionType)}
	 *             instead.
	 */
	@Deprecated
	@Override
	public void startSequentialRewrite(boolean normalized) {
	}

	/**
	 * {@inheritDoc}
	 *
	 * @since 2.0
	 * @deprecated As of 3.1, replaced by {@link IDocumentExtension4#stopRewriteSession(DocumentRewriteSession)}
	 */
	@Deprecated
	@Override
	public void stopSequentialRewrite() {
	}

	@Override
	public void resumeListenerNotification() {
		-- fStoppedListenerNotification;
		if (fStoppedListenerNotification == 0) {
			resumeDocumentListenerNotification();
		}
	}

	@Override
	public void stopListenerNotification() {
		++ fStoppedListenerNotification;
	}

	/**
	 * Resumes the document listener notification by sending out the remembered
	 * partition changed and document event.
	 *
	 * @since 2.1
	 */
	private void resumeDocumentListenerNotification() {
		if (fDeferredDocumentEvent != null) {
			DocumentEvent event= fDeferredDocumentEvent;
			fDeferredDocumentEvent= null;
			doFireDocumentChanged(event);
		}
	}

	/*
	 * @see org.eclipse.jface.text.IDocumentExtension3#computeZeroLengthPartitioning(java.lang.String, int, int)
	 * @since 3.0
	 */
	@Override
	public ITypedRegion[] computePartitioning(String partitioning, int offset, int length, boolean includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException {
		if ((0 > offset) || (0 > length) || (offset + length > getLength()))
			throw new BadLocationException();

		IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);

		if (partitioner instanceof IDocumentPartitionerExtension2) {
			checkStateOfPartitioner(partitioner, partitioning);
			return ((IDocumentPartitionerExtension2) partitioner).computePartitioning(offset, length, includeZeroLengthPartitions);
		} else if (partitioner != null) {
			checkStateOfPartitioner(partitioner, partitioning);
			return partitioner.computePartitioning(offset, length);
		} else if (DEFAULT_PARTITIONING.equals(partitioning))
			return new TypedRegion[] { new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE) };
		else
			throw new BadPartitioningException();
	}

	/*
	 * @see org.eclipse.jface.text.IDocumentExtension3#getZeroLengthContentType(java.lang.String, int)
	 * @since 3.0
	 */
	@Override
	public String getContentType(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
		if ((0 > offset) || (offset > getLength()))
			throw new BadLocationException();

		IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);

		if (partitioner instanceof IDocumentPartitionerExtension2) {
			checkStateOfPartitioner(partitioner, partitioning);
			return ((IDocumentPartitionerExtension2) partitioner).getContentType(offset, preferOpenPartitions);
		} else if (partitioner != null) {
			checkStateOfPartitioner(partitioner, partitioning);
			return partitioner.getContentType(offset);
		} else if (DEFAULT_PARTITIONING.equals(partitioning))
			return DEFAULT_CONTENT_TYPE;
		else
			throw new BadPartitioningException();
	}

	@Override
	public IDocumentPartitioner getDocumentPartitioner(String partitioning)  {
		return fDocumentPartitioners != null ? fDocumentPartitioners.get(partitioning) : null;
	}

	@Override
	public String[] getLegalContentTypes(String partitioning) throws BadPartitioningException {
		IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);
		if (partitioner != null)
			return partitioner.getLegalContentTypes();
		if (DEFAULT_PARTITIONING.equals(partitioning))
			return new String[] { DEFAULT_CONTENT_TYPE };
		throw new BadPartitioningException();
	}

	/*
	 * @see org.eclipse.jface.text.IDocumentExtension3#getZeroLengthPartition(java.lang.String, int)
	 * @since 3.0
	 */
	@Override
	public ITypedRegion getPartition(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
		if ((0 > offset) || (offset > getLength()))
			throw new BadLocationException();

		IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);

		if (partitioner instanceof IDocumentPartitionerExtension2) {
			checkStateOfPartitioner(partitioner, partitioning);
			return ((IDocumentPartitionerExtension2) partitioner).getPartition(offset, preferOpenPartitions);
		} else if (partitioner != null) {
			checkStateOfPartitioner(partitioner, partitioning);
			return partitioner.getPartition(offset);
		} else if (DEFAULT_PARTITIONING.equals(partitioning))
			return new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE);
		else
			throw new BadPartitioningException();
	}

	@Override
	public String[] getPartitionings() {
		if (fDocumentPartitioners == null)
			return new String[0];
		String[] partitionings= new String[fDocumentPartitioners.size()];
		fDocumentPartitioners.keySet().toArray(partitionings);
		return partitionings;
	}

	@Override
	public void setDocumentPartitioner(String partitioning, IDocumentPartitioner partitioner) {
		if (partitioner == null) {
			if (fDocumentPartitioners != null) {
				fDocumentPartitioners.remove(partitioning);
				if (fDocumentPartitioners.size() == 0)
					fDocumentPartitioners= null;
			}
		} else {
			if (fDocumentPartitioners == null)
				fDocumentPartitioners= new HashMap<>();
			fDocumentPartitioners.put(partitioning, partitioner);
		}
		DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
		event.setPartitionChange(partitioning, 0, getLength());
		fireDocumentPartitioningChanged(event);
	}

	@Override
	public void repairLineInformation() {
		getTracker().set(get());
	}

	/**
	 * Fires the given event to all registered rewrite session listeners. Uses robust iterators.
	 *
	 * @param event the event to be fired
	 * @since 3.1
	 */
	protected void fireRewriteSessionChanged(DocumentRewriteSessionEvent event) {
		if (fDocumentRewriteSessionListeners.size() > 0) {
			List<IDocumentRewriteSessionListener> list= new ArrayList<>(fDocumentRewriteSessionListeners);
			Iterator<IDocumentRewriteSessionListener> e= list.iterator();
			while (e.hasNext()) {
				try {
					IDocumentRewriteSessionListener l= e.next();
					l.documentRewriteSessionChanged(event);
				} catch (Exception ex) {
					log(ex);
				}
			}
		}
	}

	@Override
	public final DocumentRewriteSession getActiveRewriteSession() {
		return fDocumentRewriteSession;
	}

	@Override
	public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) {

		if (getActiveRewriteSession() != null)
			throw new IllegalStateException();


		fDocumentRewriteSession= new DocumentRewriteSession(sessionType);
		if (DEBUG)
			System.out.println("AbstractDocument: Starting rewrite session: " + fDocumentRewriteSession); //$NON-NLS-1$

		fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, fDocumentRewriteSession, DocumentRewriteSessionEvent.SESSION_START));

		startRewriteSessionOnPartitioners(fDocumentRewriteSession);

		ILineTracker tracker= getTracker();
		if (tracker instanceof ILineTrackerExtension) {
			ILineTrackerExtension extension= (ILineTrackerExtension) tracker;
			extension.startRewriteSession(fDocumentRewriteSession);
		}

		if (DocumentRewriteSessionType.SEQUENTIAL == sessionType)
			startSequentialRewrite(false);
		else if (DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
			startSequentialRewrite(true);

		return fDocumentRewriteSession;
	}

	/**
	 * Starts the given rewrite session.
	 *
	 * @param session the rewrite session
	 * @since 3.1
	 */
	protected final void startRewriteSessionOnPartitioners(DocumentRewriteSession session) {
		if (fDocumentPartitioners != null) {
			Iterator<IDocumentPartitioner> e= fDocumentPartitioners.values().iterator();
			while (e.hasNext()) {
				Object partitioner= e.next();
				if (partitioner instanceof IDocumentPartitionerExtension3) {
					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
					extension.startRewriteSession(session);
				}
			}
		}
	}

	@Override
	public void stopRewriteSession(DocumentRewriteSession session) {
		if (fDocumentRewriteSession != null && fDocumentRewriteSession == session) {

			if (DEBUG)
				System.out.println("AbstractDocument: Stopping rewrite session: " + session); //$NON-NLS-1$

			DocumentRewriteSessionType sessionType= session.getSessionType();
			if (DocumentRewriteSessionType.SEQUENTIAL == sessionType || DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
				stopSequentialRewrite();

			ILineTracker tracker= getTracker();
			if (tracker instanceof ILineTrackerExtension) {
				ILineTrackerExtension extension= (ILineTrackerExtension) tracker;
				extension.stopRewriteSession(session, get());
			}

			stopRewriteSessionOnPartitioners(fDocumentRewriteSession);

			fDocumentRewriteSession= null;
			fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_STOP));
		}
	}

	/**
	 * Stops the given rewrite session.
	 *
	 * @param session the rewrite session
	 * @since 3.1
	 */
	protected final void stopRewriteSessionOnPartitioners(DocumentRewriteSession session) {
		if (fDocumentPartitioners != null) {
			DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
			for (Entry<String, IDocumentPartitioner> entry : fDocumentPartitioners.entrySet()) {
				String partitioning = entry.getKey();
				IDocumentPartitioner partitioner= entry.getValue();
				if (partitioner instanceof IDocumentPartitionerExtension3) {
					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
					extension.stopRewriteSession(session);
					event.setPartitionChange(partitioning, 0, getLength());
				}
			}
			if (!event.isEmpty())
				fireDocumentPartitioningChanged(event);
		}
	}

	@Override
	public void addDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
		Assert.isNotNull(listener);
		if (! fDocumentRewriteSessionListeners.contains(listener))
			fDocumentRewriteSessionListeners.add(listener);
	}

	@Override
	public void removeDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
		Assert.isNotNull(listener);
		fDocumentRewriteSessionListeners.remove(listener);
	}

	/**
	 * Checks the state for the given partitioner and stops the
	 * active rewrite session.
	 *
	 * @param partitioner the document partitioner to be checked
	 * @param partitioning the document partitioning the partitioner is registered for
	 * @since 3.1
	 */
	protected final void checkStateOfPartitioner(IDocumentPartitioner partitioner, String partitioning) {
		if (!(partitioner instanceof IDocumentPartitionerExtension3))
			return;

		IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
		DocumentRewriteSession session= extension.getActiveRewriteSession();
		if (session != null) {
			extension.stopRewriteSession(session);

			if (DEBUG)
				System.out.println("AbstractDocument: Flushing rewrite session for partition type: " + partitioning); //$NON-NLS-1$

			DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
			event.setPartitionChange(partitioning, 0, getLength());
			fireDocumentPartitioningChanged(event);
		}
	}

	/**
	 * Returns all positions of the given category that are inside the given region.
	 *
	 * @param category the position category
	 * @param offset the start position of the region, must be &gt;= 0
	 * @param length the length of the region, must be &gt;= 0
	 * @param canStartBefore if <code>true</code> then positions are included
	 *            which start before the region if they end at or after the regions start
	 * @param canEndAfter if <code>true</code> then positions are included
	 *            which end after the region if they start at or before the regions end
	 * @return all positions inside the region of the given category
	 * @throws BadPositionCategoryException if category is undefined in this document
	 * @since 3.4
	 */
	public Position[] getPositions(String category, int offset, int length, boolean canStartBefore, boolean canEndAfter) throws BadPositionCategoryException {
		if (canStartBefore && canEndAfter || (!canStartBefore && !canEndAfter)) {
			List<Position> documentPositions;
			if (canStartBefore && canEndAfter) {
				if (offset < getLength() / 2) {
					documentPositions= getStartingPositions(category, 0, offset + length);
				} else {
					documentPositions= getEndingPositions(category, offset, getLength() - offset + 1);
				}
			} else {
				documentPositions= getStartingPositions(category, offset, length);
			}

			ArrayList<Position> list= new ArrayList<>(documentPositions.size());

			Position region= new Position(offset, length);

			for (Position position : documentPositions) {
				if (isWithinRegion(region, position, canStartBefore, canEndAfter)) {
					list.add(position);
				}
			}

			Position[] positions= new Position[list.size()];
			list.toArray(positions);
			return positions;
		} else if (canStartBefore) {
			List<Position> list= getEndingPositions(category, offset, length);
			Position[] positions= new Position[list.size()];
			list.toArray(positions);
			return positions;
		} else {
			Assert.isLegal(canEndAfter && !canStartBefore);

			List<Position> list= getStartingPositions(category, offset, length);
			Position[] positions= new Position[list.size()];
			list.toArray(positions);
			return positions;
		}
	}

	/*
	 * @since 3.4
	 */
	private boolean isWithinRegion(Position region, Position position, boolean canStartBefore, boolean canEndAfter) {
		if (canStartBefore && canEndAfter) {
			return region.overlapsWith(position.getOffset(), position.getLength());
		} else if (canStartBefore) {
			return region.includes(position.getOffset() + position.getLength() - 1);
		} else if (canEndAfter) {
			return region.includes(position.getOffset());
		} else {
			int start= position.getOffset();
			return region.includes(start) && region.includes(start + position.getLength() - 1);
		}
	}

	/**
	 * A list of positions in the given category with an offset inside the given
	 * region. The order of the positions is arbitrary.
	 *
	 * @param category the position category
	 * @param offset the offset of the region
	 * @param length the length of the region
	 * @return a list of the positions in the region
	 * @throws BadPositionCategoryException if category is undefined in this document
	 * @since 3.4
	 */
	private List<Position> getStartingPositions(String category, int offset, int length) throws BadPositionCategoryException {
		List<Position> positions= fPositions.get(category);
		if (positions == null)
			throw new BadPositionCategoryException();

		int indexStart= computeIndexInPositionList(positions, offset, true);
		int indexEnd= computeIndexInPositionList(positions, offset + length, true);

		return positions.subList(indexStart, indexEnd);
	}

	/**
	 * A list of positions in the given category with an end position inside
	 * the given region. The order of the positions is arbitrary.
	 *
	 * @param category the position category
	 * @param offset the offset of the region
	 * @param length the length of the region
	 * @return a list of the positions in the region
	 * @throws BadPositionCategoryException if category is undefined in this document
	 * @since 3.4
	 */
	private List<Position> getEndingPositions(String category, int offset, int length) throws BadPositionCategoryException {
		List<Position> positions= fEndPositions.get(category);
		if (positions == null)
			throw new BadPositionCategoryException();

		int indexStart= computeIndexInPositionList(positions, offset, false);
		int indexEnd= computeIndexInPositionList(positions, offset + length, false);

		return positions.subList(indexStart, indexEnd);
	}

	/**
	 * Logs the given exception by reusing the code in {@link SafeRunner}.
	 *
	 * @param ex the exception
	 * @since 3.6
	 */
	private static void log(final Exception ex) {
		SafeRunner.run(new ISafeRunnable() {
			@Override
			public void run() throws Exception {
				throw ex;
			}

			@Override
			public void handleException(Throwable exception) {
				// NOTE: Logging is done by SafeRunner
			}
		});
	}

}
