/*******************************************************************************
 * Copyright (c) 2014, 2018 1C-Soft LLC 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:
 *     Vladimir Piskarev (1C) - initial API and implementation
 *******************************************************************************/
package org.eclipse.handly.model.impl.support;

import static org.eclipse.handly.context.Contexts.of;
import static org.eclipse.handly.context.Contexts.with;
import static org.eclipse.handly.model.Elements.CREATE_BUFFER;
import static org.eclipse.handly.model.IElementDeltaConstants.CHANGED;
import static org.eclipse.handly.model.IElementDeltaConstants.F_WORKING_COPY;
import static org.eclipse.handly.util.ToStringOptions.FORMAT_STYLE;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.MEDIUM;

import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.handly.buffer.IBuffer;
import org.eclipse.handly.buffer.ICoreTextFileBufferProvider;
import org.eclipse.handly.buffer.TextFileBuffer;
import org.eclipse.handly.context.Context;
import org.eclipse.handly.context.IContext;
import org.eclipse.handly.internal.Activator;
import org.eclipse.handly.model.ElementDeltas;
import org.eclipse.handly.model.Elements;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.IElementDelta;
import org.eclipse.handly.model.impl.DefaultWorkingCopyCallback;
import org.eclipse.handly.model.impl.IReconcileStrategy;
import org.eclipse.handly.model.impl.ISourceFileImplExtension;
import org.eclipse.handly.model.impl.IWorkingCopyCallback;
import org.eclipse.handly.snapshot.ISnapshot;
import org.eclipse.handly.snapshot.ISnapshotProvider;
import org.eclipse.handly.snapshot.NonExpiringSnapshot;
import org.eclipse.handly.snapshot.TextFileSnapshot;
import org.eclipse.handly.util.Property;
import org.eclipse.handly.util.TextRange;

/**
 * This "trait-like" interface provides a skeletal implementation of {@link
 * ISourceFileImplExtension} to minimize the effort required to implement
 * that interface. Clients may "mix in" this interface directly or extend
 * the class {@link SourceFile} (or {@link WorkspaceSourceFile}).
 * <p>
 * In general, the members first defined in this interface are not intended
 * to be referenced outside the subtype hierarchy.
 * </p>
 * <p>
 * If a notification manager is registered in the model context,
 * this implementation will take advantage of it to send out working copy
 * notifications. See {@link #workingCopyModeChanged_()} and {@link
 * NotifyingReconcileOperation}.
 * </p>
 *
 * @noextend This interface is not intended to be extended by clients.
 */
public interface ISourceFileImplSupport
    extends ISourceElementImplSupport, ISourceFileImplExtension
{
    @Override
    default int defaultHashCode_()
    {
        IFile file = getFile_();
        if (file != null)
            return file.hashCode();
        return ISourceElementImplSupport.super.defaultHashCode_();
    }

    @Override
    default boolean defaultEquals_(Object obj)
    {
        if (!(obj instanceof ISourceFileImplSupport))
            return false;
        IFile file = getFile_();
        return (file == null || file.equals(
            ((ISourceFileImplSupport)obj).getFile_()))
            && ISourceElementImplSupport.super.defaultEquals_(obj);
    }

    /**
     * {@inheritDoc}
     * <p>
     * This implementation delegates to {@link #getFileBuffer_(IContext,
     * IProgressMonitor)} if this source file is not a working copy;
     * otherwise, it returns the working copy buffer.
     * </p>
     * @throws CoreException {@inheritDoc}
     * @throws OperationCanceledException {@inheritDoc}
     */
    @Override
    default IBuffer getBuffer_(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
        if (!acquireExistingWorkingCopy_(subMonitor.split(10)))
        {
            return getFileBuffer_(context, subMonitor.split(90));
        }
        else
        {
            try
            {
                WorkingCopyInfo info =
                    getElementManager_().peekAtWorkingCopyInfo(this);

                if (info == null)
                    throw new AssertionError(
                        "This method probably needs to be overridden"); //$NON-NLS-1$

                IBuffer buffer = info.getBuffer();
                buffer.addRef();
                return buffer;
            }
            finally
            {
                releaseWorkingCopy_();
            }
        }
    }

    @Override
    default boolean becomeWorkingCopy_(IContext context,
        IProgressMonitor monitor) throws CoreException
    {
        if (context == null)
            throw new IllegalArgumentException();

        IBuffer buffer = context.get(WORKING_COPY_BUFFER);
        if (buffer == null)
            try (IBuffer defaultBuffer = getFileBuffer_(context, null))
            {
                return becomeWorkingCopy_(with(of(WORKING_COPY_BUFFER,
                    defaultBuffer), context), monitor);
            }

        IWorkingCopyCallback callback = context.get(WORKING_COPY_CALLBACK);
        if (callback == null)
            callback = new DefaultWorkingCopyCallback();

        WorkingCopyInfo info = new WorkingCopyInfo(buffer,
            newWorkingCopyContext_(context), new ReconcileStrategy(this),
            callback);

        return WorkingCopyHelper.becomeWorkingCopy(this, info, monitor);
    }

    @Override
    default boolean acquireExistingWorkingCopy_(IProgressMonitor monitor)
    {
        return WorkingCopyHelper.acquireExistingWorkingCopy(this, monitor);
    }

    @Override
    default boolean releaseWorkingCopy_()
    {
        WorkingCopyInfo info = getElementManager_().releaseWorkingCopyInfo(
            this);
        if (info == null)
            throw new IllegalStateException("Not a working copy: " + toString_( //$NON-NLS-1$
                of(FORMAT_STYLE, MEDIUM)));
        if (info.isDisposed() && info.created)
        {
            workingCopyModeChanged_();
            return true;
        }
        return false;
    }

    @Override
    default IContext getWorkingCopyContext_()
    {
        WorkingCopyInfo info = getElementManager_().peekAtWorkingCopyInfo(this);
        if (info == null)
            return null;
        if (info.created)
            return info.getContext();
        // special case: wc creation is in progress on the current thread
        if (this.equals(ReconcileOperation.CURRENTLY_RECONCILED.get()))
            return info.getContext();
        return null;
    }

    @Override
    default boolean isWorkingCopy_()
    {
        return getWorkingCopyContext_() != null;
    }

    @Override
    default boolean needsReconciling_()
    {
        if (!acquireExistingWorkingCopy_(null))
            return false;
        else
        {
            try
            {
                WorkingCopyInfo info =
                    getElementManager_().peekAtWorkingCopyInfo(this);

                if (info == null)
                    throw new AssertionError(
                        "This method probably needs to be overridden"); //$NON-NLS-1$

                return info.callback.needsReconciling();
            }
            finally
            {
                releaseWorkingCopy_();
            }
        }
    }

    @Override
    default void reconcile_(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
        if (!acquireExistingWorkingCopy_(subMonitor.split(10)))
            return; // not a working copy
        else
        {
            try
            {
                WorkingCopyInfo info =
                    getElementManager_().peekAtWorkingCopyInfo(this);

                if (info == null)
                    throw new AssertionError(
                        "This method probably needs to be overriden"); //$NON-NLS-1$

                info.callback.reconcile(context, subMonitor.split(90));
            }
            finally
            {
                releaseWorkingCopy_();
            }
        }
    }

    /**
     * Returns a reconcile operation for this source file.
     * <p>
     * This implementation returns a new instance of {@link
     * NotifyingReconcileOperation} if there is a notification manager
     * registered in the model context. Otherwise, a new instance of
     * {@link ReconcileOperation} is returned.
     * </p>
     * <p>
     * This method is called internally; it is not intended to be invoked by
     * clients.
     * </p>
     *
     * @return a reconcile operation for this source file (not <code>null</code>)
     */
    default ReconcileOperation getReconcileOperation_()
    {
        if (Elements.getModelContext(this).get(
            INotificationManager.class) != null)
            return new NotifyingReconcileOperation(this);

        return new ReconcileOperation(this);
    }

    /**
     * Returns a context to be associated with a new working copy of this
     * source file. The given operation context is propagated from the
     * {@link #becomeWorkingCopy_} method.
     * <p>
     * The returned context is composed of the context explicitly {@link
     * ISourceFileImplExtension#WORKING_COPY_CONTEXT specified} when creating
     * the working copy and an intrinsic context of the working copy itself,
     * in that order.
     * </p>
     * <p>
     * This implementation returns <code>context.getOrDefault(WORKING_COPY_CONTEXT)</code>.
     * </p>
     * <p>
     * This method is called internally; it is not intended to be invoked by
     * clients.
     * </p>
     *
     * @param context the operation context (never <code>null</code>)
     * @return the working copy context (not <code>null</code>)
     */
    default IContext newWorkingCopyContext_(IContext context)
    {
        return context.getOrDefault(WORKING_COPY_CONTEXT);
    }

    /**
     * Notifies about a working copy mode change: either the source file
     * became a working copy or reverted back from the working copy mode.
     * <p>
     * This implementation does nothing if no notification manager is
     * registered in the model context. Otherwise, it sends out a delta
     * notification indicating the nature of the working copy mode change.
     * </p>
     * <p>
     * This method is called internally; it is not intended to be invoked by
     * clients.
     * </p>
     */
    default void workingCopyModeChanged_()
    {
        INotificationManager notificationManager = Elements.getModelContext(
            this).get(INotificationManager.class);
        if (notificationManager == null)
            return;

        ElementDelta.Factory deltaFactory = Elements.getModelContext(this).get(
            ElementDelta.Factory.class);
        if (deltaFactory == null)
            deltaFactory = element -> new ElementDelta(element);

        ElementDelta.Builder builder = new ElementDelta.Builder(
            deltaFactory.newDelta(getRoot_()));

        if (fileExists_())
            builder.changed(this, F_WORKING_COPY);
        else if (isWorkingCopy_())
            builder.added(this, F_WORKING_COPY);
        else
            builder.removed(this, F_WORKING_COPY);

        notificationManager.fireElementChangeEvent(new ElementChangeEvent(
            ElementChangeEvent.POST_CHANGE, builder.getDelta()));
    }

    /**
     * Returns whether the underlying file exists.
     * <p>
     * This implementation returns <code>getFile_().exists()</code> if
     * this source file has an underlying <code>IFile</code>; otherwise,
     * it throws an assertion error.
     * </p>
     *
     * @return <code>true</code> if the underlying file exists,
     *  and <code>false</code> otherwise
     */
    default boolean fileExists_()
    {
        IFile file = getFile_();
        if (file == null)
            throw new AssertionError("Please override this method"); //$NON-NLS-1$
        return file.exists();
    }

    /**
     * Returns a snapshot provider for the underlying file's stored contents.
     * <p>
     * The client takes (potentially shared) ownership of the returned provider
     * and is responsible for releasing it. The provider will be disposed
     * only after it is released by every owner. The provider must not
     * be accessed by clients that don't own it.
     * </p>
     * <p>
     * This implementation returns a snapshot provider for the stored contents
     * of the underlying {@link #getFile_() IFile}; it throws an assertion error
     * if this source file has no underlying file in the workspace.
     * </p>
     *
     * @return a snapshot provider for the underlying file's stored contents
     *  (not <code>null</code>)
     * @see ISnapshotProvider
     */
    default ISnapshotProvider getFileSnapshotProvider_()
    {
        IFile file = getFile_();
        if (file == null)
            throw new AssertionError("Please override this method"); //$NON-NLS-1$
        return () ->
        {
            TextFileSnapshot result = new TextFileSnapshot(file,
                TextFileSnapshot.Layer.FILESYSTEM);
            if (!result.exists())
            {
                throw new IllegalStateException(newDoesNotExistException_());
            }
            if (result.getContents() == null && !result.getStatus().isOK())
            {
                throw new IllegalStateException(new CoreException(
                    result.getStatus()));
            }
            return result;
        };
    }

    /**
     * Returns the buffer opened for the underlying file of this source file.
     * Note that buffers may be shared by multiple clients, so the returned buffer
     * may have unsaved changes if it has been modified by another client.
     * <p>
     * The client takes (potentially shared) ownership of the returned buffer
     * and is responsible for releasing it. The buffer will be disposed
     * only after it is released by every owner. The buffer must not
     * be accessed by clients that don't own it.
     * </p>
     * <p>
     * Implementations are encouraged to support the following standard options,
     * which may be specified in the given context:
     * </p>
     * <ul>
     * <li>
     * {@link org.eclipse.handly.model.Elements#CREATE_BUFFER CREATE_BUFFER} -
     * Indicates whether a new buffer should be created if none already exists.
     * </li>
     * </ul>
     * <p>
     * This implementation returns the buffer opened for the underlying
     * {@link #getFile_() IFile}; it throws an assertion error if this source file
     * has no underlying file in the workspace.
     * </p>
     *
     * @param context the operation context (never <code>null</code>)
     * @param monitor a progress monitor, or <code>null</code>
     *  if progress reporting is not desired. The caller must not rely on
     *  {@link IProgressMonitor#done()} having been called by the receiver
     * @return the buffer opened for the underlying file of this source file,
     *  or <code>null</code> if <code>CREATE_BUFFER == false</code> and
     *  there is currently no buffer opened for that file
     * @throws CoreException if the buffer could not be opened successfully
     * @throws OperationCanceledException if this method is canceled
     * @see IBuffer
     */
    default IBuffer getFileBuffer_(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        IFile file = getFile_();
        if (file == null)
            throw new AssertionError("Please override this method"); //$NON-NLS-1$
        ICoreTextFileBufferProvider provider =
            ICoreTextFileBufferProvider.forLocation(file.getFullPath(),
                LocationKind.IFILE, ITextFileBufferManager.DEFAULT);
        if (!context.getOrDefault(CREATE_BUFFER)
            && provider.getBuffer() == null)
        {
            return null;
        }
        return new TextFileBuffer(provider, monitor);
    }

    @Override
    default void validateExistence_(IContext context) throws CoreException
    {
        if (!isWorkingCopy_())
        {
            if (!fileExists_())
                throw newDoesNotExistException_();
        }
    }

    @Override
    default void openParent_(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        if (isWorkingCopy_())
            return; // don't open the parent element for a working copy
        ISourceElementImplSupport.super.openParent_(context, monitor);
    }

    @Override
    default void buildStructure_(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        if (!context.containsKey(SOURCE_CONTENTS) && !context.containsKey(
            SOURCE_AST))
        {
            if (isWorkingCopy_())
                throw new AssertionError();
            // NOTE: source files that are not working copies must reflect
            // the structure of the underlying file rather than the buffer
            NonExpiringSnapshot snapshot;
            try (ISnapshotProvider provider = getFileSnapshotProvider_())
            {
                try
                {
                    snapshot = new NonExpiringSnapshot(provider);
                }
                catch (IllegalStateException e)
                {
                    Throwable cause = e.getCause();
                    if (cause instanceof CoreException)
                        throw (CoreException)cause;
                    throw new CoreException(Activator.createErrorStatus(
                        e.getMessage(), e));
                }
            }
            context = with(of(SOURCE_CONTENTS, snapshot.getContents()), of(
                SOURCE_SNAPSHOT, snapshot.getWrappedSnapshot()), context);
        }

        buildSourceStructure_(context, monitor);

        Map<IElement, Object> newElements = context.get(NEW_ELEMENTS);
        Object body = newElements.get(this);
        if (body instanceof SourceElementBody)
        {
            SourceElementBody thisBody = (SourceElementBody)body;

            String source = context.get(SOURCE_CONTENTS);
            if (source != null)
                thisBody.setFullRange(new TextRange(0, source.length()));

            ISnapshot snapshot = context.get(SOURCE_SNAPSHOT);
            if (snapshot != null)
                thisBody.setSnapshot(snapshot, newElements);
        }
    }

    /**
     * Specifies the source AST.
     * @see #buildSourceStructure_(IContext, IProgressMonitor)
     */
    Property<Object> SOURCE_AST = Property.get(
        ISourceFileImplSupport.class.getName() + ".sourceAst", Object.class); //$NON-NLS-1$
    /**
     * Specifies the source string.
     * @see #buildSourceStructure_(IContext, IProgressMonitor)
     */
    Property<String> SOURCE_CONTENTS = Property.get(
        ISourceFileImplSupport.class.getName() + ".sourceContents", //$NON-NLS-1$
        String.class);
    /**
     * Specifies the source snapshot.
     * @see #buildSourceStructure_(IContext, IProgressMonitor)
     */
    Property<ISnapshot> SOURCE_SNAPSHOT = Property.get(
        ISourceFileImplSupport.class.getName() + ".sourceSnapshot", //$NON-NLS-1$
        ISnapshot.class);

    /**
     * Creates and initializes bodies for this element and for each
     * of its descendant elements according to options specified in the
     * given context. Uses the {@link #NEW_ELEMENTS} map in the given context
     * to associate the created bodies with their respective elements.
     * <p>
     * The following context options influence how the structure is built and,
     * if simultaneously present, must be mutually consistent:
     * </p>
     * <ul>
     * <li>
     * {@link #SOURCE_AST} - Specifies the AST to use when building the structure.
     * The AST is safe to read in the dynamic context of this method call, but
     * must not be modified.
     * </li>
     * <li>
     * {@link #SOURCE_CONTENTS} - Specifies the source string to use when
     * building the structure.
     * </li>
     * </ul>
     * <p>
     * At least one of <code>SOURCE_AST</code> or <code>SOURCE_CONTENTS</code>
     * will have a non-null value in the given context.
     * </p>
     * <p>
     * The given context may provide additional data that this method can use,
     * including the following:
     * </p>
     * <ul>
     * <li>
     * {@link #SOURCE_SNAPSHOT} - Specifies the source snapshot from which
     * <code>SOURCE_AST</code> was created or <code>SOURCE_CONTENTS</code>
     * was obtained. The snapshot may expire.
     * </li>
     * </ul>
     *
     * @param context the operation context (never <code>null</code>)
     * @param monitor a progress monitor (never <code>null</code>).
     *  The caller must not rely on {@link IProgressMonitor#done()}
     *  having been called by the receiver
     * @throws CoreException if this method fails
     * @throws OperationCanceledException if this method is canceled
     */
    void buildSourceStructure_(IContext context, IProgressMonitor monitor)
        throws CoreException;

    @Override
    default void close_(IContext context)
    {
        synchronized (getElementManager_())
        {
            if (isWorkingCopy_())
                return;
            ISourceElementImplSupport.super.close_(context);
        }
    }

    @Override
    default void toStringName_(StringBuilder builder, IContext context)
    {
        if (isWorkingCopy_())
            builder.append("[Working copy] "); //$NON-NLS-1$
        ISourceElementImplSupport.super.toStringName_(builder, context);
    }

    /**
     * Reconciles a working copy.
     * <p>
     * This class or a subclass of this class are not intended to be used by
     * clients for purposes other than extension or instance creation;
     * instances of this class or a subclass of this class are not intended
     * to be used by clients for purposes other than returning from {@link
     * ISourceFileImplSupport#getReconcileOperation_() getReconcileOperation_()}.
     * </p>
     *
     * @see NotifyingReconcileOperation
     */
    class ReconcileOperation
    {
        /**
         * Indicates whether the structure should be rebuilt when reconciling
         * is forced. Default value: <code>false</code>.
         * @see #reconcile(IContext, IProgressMonitor)
         */
        protected static final Property<Boolean> REBUILD_STRUCTURE_IF_FORCED =
            Property.get(ReconcileOperation.class.getName()
                + ".rebuildStructureIfForced", //$NON-NLS-1$
                Boolean.class).withDefault(false);

        static final Property<Boolean> INITIAL_RECONCILE = Property.get(
            ReconcileOperation.class.getName() + ".initialReconcile", //$NON-NLS-1$
            Boolean.class).withDefault(false);

        static final Property<Boolean> RECONCILING_FORCED = Property.get(
            ReconcileOperation.class.getName() + ".reconcilingForced", //$NON-NLS-1$
            Boolean.class).withDefault(false);

        static final ThreadLocal<ISourceFileImplSupport> CURRENTLY_RECONCILED =
            new ThreadLocal<>(); // the source file being reconciled

        /**
         * This operation's source file.
         */
        protected final ISourceFileImplSupport sourceFile;

        /**
         * Constructs a reconcile operation for the given source file.
         *
         * @param sourceFile not <code>null</code>
         */
        protected ReconcileOperation(ISourceFileImplSupport sourceFile)
        {
            if (sourceFile == null)
                throw new IllegalArgumentException();
            this.sourceFile = sourceFile;
        }

        /**
         * Reconciles the working copy according to options specified
         * in the given context.
         * <p>
         * The following context options can influence whether the structure
         * of the working copy gets rebuilt:
         * </p>
         * <ul>
         * <li>
         * {@link #REBUILD_STRUCTURE_IF_FORCED} - Indicates whether the structure
         * should be rebuilt even if reconciling was forced, i.e. the working copy
         * buffer has not been modified since the last time it was reconciled.
         * </li>
         * </ul>
         * <p>
         * The following context options influence rebuilding of the structure
         * of the working copy and, if simultaneously present, must be mutually
         * consistent:
         * </p>
         * <ul>
         * <li>
         * {@link #SOURCE_AST} - Specifies the AST to use when building the
         * structure. The AST is safe to read in the dynamic context of this
         * method call, but must not be modified.
         * </li>
         * <li>
         * {@link #SOURCE_CONTENTS} - Specifies the source string to use when
         * building the structure.
         * </li>
         * </ul>
         * <p>
         * At least one of <code>SOURCE_AST</code> or <code>SOURCE_CONTENTS</code>
         * must have a non-null value in the given context.
         * </p>
         * <p>
         * The given context may provide additional data that this method can use,
         * including the following:
         * </p>
         * <ul>
         * <li>
         * {@link #SOURCE_SNAPSHOT} - Specifies the source snapshot from which
         * <code>SOURCE_AST</code> was created or <code>SOURCE_CONTENTS</code>
         * was obtained. The snapshot may expire.
         * </li>
         * </ul>
         * <p>
         * Subclasses may override this method, but must make sure to call
         * the <b>super</b> implementation.
         * </p>
         * <p>
         * This implementation calls {@link #reconcileStructure} iff
         * {@link #shouldReconcileStructure} returns <code>true</code>.
         * </p>
         *
         * @param context the operation context (not <code>null</code>)
         * @param monitor a progress monitor, or <code>null</code>
         *  if progress reporting is not desired. The caller must not rely on
         *  {@link IProgressMonitor#done()} having been called by the receiver
         * @throws CoreException if the working copy cannot be reconciled
         * @throws OperationCanceledException if this method is canceled
         */
        protected void reconcile(IContext context, IProgressMonitor monitor)
            throws CoreException
        {
            if (shouldReconcileStructure(context))
            {
                reconcileStructure(context, monitor);
            }
        }

        /**
         * Returns whether the structure of the working copy needs to be
         * reconciled by rebuilding it according to options specified in the
         * given context.
         * <p>
         * Subclasses may override this method but must return <code>true</code>
         * whenever the <b>super</b> implementation returns <code>true</code>;
         * they may return <code>true</code> when the <b>super</b> implementation
         * returns <code>false</code>.
         * </p>
         *
         * @param context the operation context (not <code>null</code>)
         * @return <code>true</code> if the working copy structure needs to be
         *  reconciled; <code>false</code> otherwise
         * @see #reconcile(IContext, IProgressMonitor)
         * @see #reconcileStructure(IContext, IProgressMonitor)
         */
        protected boolean shouldReconcileStructure(IContext context)
        {
            return isInitialReconcile(context) || !isReconcilingForced(context)
                || context.getOrDefault(REBUILD_STRUCTURE_IF_FORCED);
        }

        /**
         * Returns whether the reconcile operation is initial reconcile.
         *
         * @param context the operation context (not <code>null</code>)
         * @return <code>true</code> if the reconcile operation is initial
         *  reconcile; <code>false</code> otherwise
         * @see #reconcile(IContext, IProgressMonitor)
         * @see #reconcileStructure(IContext, IProgressMonitor)
         */
        protected static boolean isInitialReconcile(IContext context)
        {
            return context.getOrDefault(INITIAL_RECONCILE);
        }

        /**
         * Returns whether reconciling was forced, i.e. the source has not been
         * modified since the last time the model was reconciled.
         *
         * @param context the operation context (not <code>null</code>)
         * @return <code>true</code> if the reconciling was forced;
         *  <code>false</code> otherwise
         * @see #reconcile(IContext, IProgressMonitor)
         * @see #reconcileStructure(IContext, IProgressMonitor)
         */
        protected static boolean isReconcilingForced(IContext context)
        {
            return context.getOrDefault(RECONCILING_FORCED);
        }

        /**
         * Reconciles the structure of the working copy by rebuilding it
         * according to options specified in the given context.
         * <p>
         * The following context options influence rebuilding of the structure
         * of the working copy and, if simultaneously present, must be mutually
         * consistent:
         * </p>
         * <ul>
         * <li>
         * {@link #SOURCE_AST} - Specifies the AST to use when building the
         * structure. The AST is safe to read in the dynamic context of this
         * method call, but must not be modified.
         * </li>
         * <li>
         * {@link #SOURCE_CONTENTS} - Specifies the source string to use when
         * building the structure.
         * </li>
         * </ul>
         * <p>
         * At least one of <code>SOURCE_AST</code> or <code>SOURCE_CONTENTS</code>
         * must have a non-null value in the given context.
         * </p>
         * <p>
         * The given context may provide additional data that this method can use,
         * including the following:
         * </p>
         * <ul>
         * <li>
         * {@link #SOURCE_SNAPSHOT} - Specifies the source snapshot from which
         * <code>SOURCE_AST</code> was created or <code>SOURCE_CONTENTS</code>
         * was obtained. The snapshot may expire.
         * </li>
         * </ul>
         * <p>
         * Subclasses may override this method, but must make sure to call
         * the <b>super</b> implementation.
         * </p>
         *
         * @param context the operation context (not <code>null</code>)
         * @param monitor a progress monitor, or <code>null</code>
         *  if progress reporting is not desired. The caller must not rely on
         *  {@link IProgressMonitor#done()} having been called by the receiver
         * @throws CoreException if the working copy cannot be reconciled
         * @throws OperationCanceledException if this method is canceled
         * @see #reconcile(IContext, IProgressMonitor)
         * @see #shouldReconcileStructure(IContext)
         */
        protected void reconcileStructure(IContext context,
            IProgressMonitor monitor) throws CoreException
        {
            if (context.get(SOURCE_AST) == null && context.get(
                SOURCE_CONTENTS) == null)
            {
                throw new IllegalArgumentException();
            }
            if (CURRENTLY_RECONCILED.get() != null)
                throw new AssertionError(); // should never happen
            CURRENTLY_RECONCILED.set(sourceFile);
            try
            {
                sourceFile.open_(with(of(FORCE_OPEN, true), context), monitor);
            }
            finally
            {
                CURRENTLY_RECONCILED.set(null);
            }
            if (isInitialReconcile(context))
            {
                WorkingCopyInfo info =
                    sourceFile.getElementManager_().peekAtWorkingCopyInfo(
                        sourceFile);
                if (!info.created)
                    throw new AssertionError(); // should never happen

                sourceFile.workingCopyModeChanged_(); // notify about wc creation
            }
        }
    }

    /**
     * Reconciles a working copy and sends out a delta notification
     * indicating the nature of the change of the working copy since
     * the last time it was reconciled. Uses the notification manager
     * registered in the model context.
     * <p>
     * This class or a subclass of this class are not intended to be used by
     * clients for purposes other than extension or instance creation;
     * instances of this class or a subclass of this class are not intended
     * to be used by clients for purposes other than returning from {@link
     * ISourceFileImplSupport#getReconcileOperation_() getReconcileOperation_()}.
     * </p>
     *
     * @see INotificationManager
     */
    class NotifyingReconcileOperation
        extends ReconcileOperation
    {
        /**
         * Constructs a notifying reconcile operation for the given source file.
         *
         * @param sourceFile not <code>null</code>
         */
        protected NotifyingReconcileOperation(ISourceFileImplSupport sourceFile)
        {
            super(sourceFile);
        }

        /**
         * {@inheritDoc}
         * <p>
         * If <code>shouldReconcileStructure</code> returns <code>true</code>,
         * this implementation invokes <code>reconcileStructure</code>, builds
         * the resulting delta using an element {@link #newChangeRecorder()
         * change recorder}, and sends out a <code>POST_RECONCILE</code> event
         * using the notification manager registered in the model context.
         * </p>
         */
        @Override
        protected void reconcile(IContext context, IProgressMonitor monitor)
            throws CoreException
        {
            if (!shouldReconcileStructure(context))
                super.reconcile(context, monitor);
            else
            {
                ElementChangeRecorder recorder = newChangeRecorder();
                recorder.beginRecording(sourceFile);

                super.reconcile(context, monitor);

                IElementDelta delta = recorder.endRecording().getDelta();
                if (delta != null && ElementDeltas.getKind(delta) == CHANGED)
                {
                    Elements.getModelContext(sourceFile).get(
                        INotificationManager.class).fireElementChangeEvent(
                            new ElementChangeEvent(
                                ElementChangeEvent.POST_RECONCILE, delta));
                }
            }
        }

        /**
         * Returns a new instance of element change recorder for this operation.
         *
         * @return a new instance of element change recorder
         *  (never <code>null</code>)
         */
        protected ElementChangeRecorder newChangeRecorder()
        {
            return new ElementChangeRecorder();
        }
    }
}

abstract class WorkingCopyHelper
{
    static boolean becomeWorkingCopy(ISourceFileImplSupport sourceFile,
        WorkingCopyInfo info, IProgressMonitor monitor) throws CoreException
    {
        WorkingCopyHelper helper = new WorkingCopyHelper(sourceFile)
        {
            @Override
            WorkingCopyInfo doAcquireWorkingCopy()
            {
                return sourceFile.getElementManager_().putWorkingCopyInfoIfAbsent(
                    sourceFile, info);
            }

            @Override
            boolean isCanceled()
            {
                if (monitor == null)
                    return false;
                return monitor.isCanceled();
            }
        };
        WorkingCopyInfo existingInfo = helper.acquireWorkingCopy();
        if (existingInfo == null)
        {
            boolean success = false;
            try
            {
                info.initTask.execute(monitor);
                success = true;
            }
            finally
            {
                if (!success)
                    sourceFile.releaseWorkingCopy_();
            }
        }
        return existingInfo == null;
    }

    static boolean acquireExistingWorkingCopy(ISourceFileImplSupport sourceFile,
        IProgressMonitor monitor)
    {
        WorkingCopyHelper helper = new WorkingCopyHelper(sourceFile)
        {
            @Override
            WorkingCopyInfo doAcquireWorkingCopy()
            {
                return sourceFile.getElementManager_().getWorkingCopyInfo(
                    sourceFile);
            }

            @Override
            boolean isCanceled()
            {
                if (monitor == null)
                    return false;
                return monitor.isCanceled();
            }
        };
        WorkingCopyInfo existingInfo = helper.acquireWorkingCopy();
        return existingInfo != null;
    }

    private final ISourceFileImplSupport sourceFile;

    private WorkingCopyHelper(ISourceFileImplSupport sourceFile)
    {
        if (sourceFile == null)
            throw new IllegalArgumentException();
        this.sourceFile = sourceFile;
    }

    WorkingCopyInfo acquireWorkingCopy()
    {
        for (;;)
        {
            if (isCanceled())
                throw new OperationCanceledException();
            WorkingCopyInfo info = doAcquireWorkingCopy();
            if (info == null)
                return null;
            boolean success = false;
            try
            {
                success = waitForInit(info);
            }
            finally
            {
                if (!success)
                    sourceFile.releaseWorkingCopy_();
            }
            if (success)
                return info;
        }
    }

    abstract WorkingCopyInfo doAcquireWorkingCopy();

    boolean isCanceled()
    {
        return false;
    }

    private boolean waitForInit(WorkingCopyInfo info)
    {
        for (int i = 0; i < 10; i++)
        {
            if (isCanceled())
                throw new OperationCanceledException();
            try
            {
                return info.initTask.wasSuccessful(10, TimeUnit.MILLISECONDS);
            }
            catch (InterruptedException e)
            {
            }
            catch (TimeoutException e)
            {
            }
        }
        return false;
    }
}

class ReconcileStrategy
    implements IReconcileStrategy
{
    private final ISourceFileImplSupport sourceFile;

    ReconcileStrategy(ISourceFileImplSupport sourceFile)
    {
        if (sourceFile == null)
            throw new IllegalArgumentException();
        this.sourceFile = sourceFile;
    }

    @Override
    public void reconcile(IContext context, IProgressMonitor monitor)
        throws CoreException
    {
        if (context.get(SOURCE_AST) == null && context.get(
            SOURCE_CONTENTS) == null)
        {
            throw new IllegalArgumentException();
        }

        Context context2 = new Context();

        WorkingCopyInfo info =
            sourceFile.getElementManager_().peekAtWorkingCopyInfo(sourceFile);
        context2.bind(
            ISourceFileImplSupport.ReconcileOperation.INITIAL_RECONCILE).to(
                !info.created);

        context2.bind(
            ISourceFileImplSupport.ReconcileOperation.RECONCILING_FORCED).to(
                context.getOrDefault(RECONCILING_FORCED));

        if (context.containsKey(SOURCE_AST))
            context2.bind(ISourceFileImplSupport.SOURCE_AST).to(context.get(
                SOURCE_AST));

        if (context.containsKey(SOURCE_CONTENTS))
            context2.bind(ISourceFileImplSupport.SOURCE_CONTENTS).to(
                context.get(SOURCE_CONTENTS));

        if (context.containsKey(SOURCE_SNAPSHOT))
            context2.bind(ISourceFileImplSupport.SOURCE_SNAPSHOT).to(
                context.get(SOURCE_SNAPSHOT));

        sourceFile.getReconcileOperation_().reconcile(with(context2, context),
            monitor);
    }
}
