All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.text.link.LinkedModeManager Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2000, 2008 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.link;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.text.IDocument;


/**
 * A linked mode manager ensures exclusive access of linked position infrastructures to documents. There
 * is at most one LinkedModeManager installed on the same document. The getManager
 * methods will return the existing instance if any of the specified documents already have an installed
 * manager.
 *
 * @since 3.0
 */
class LinkedModeManager {

	/**
	 * Our implementation of ILinkedModeListener.
	 */
	private class Listener implements ILinkedModeListener {

		@Override
		public void left(LinkedModeModel model, int flags) {
			LinkedModeManager.this.left(model, flags);
		}

		@Override
		public void suspend(LinkedModeModel model) {
			// not interested
		}

		@Override
		public void resume(LinkedModeModel model, int flags) {
			// not interested
		}

	}

	/** Global map from documents to managers. */
	private static Map fgManagers= new HashMap<>();

	/**
	 * Returns whether there exists a LinkedModeManager on document.
	 *
	 * @param document the document of interest
	 * @return true if there exists a LinkedModeManager on document, false otherwise
	 */
	public static boolean hasManager(IDocument document) {
		return fgManagers.get(document) != null;
	}

	/**
	 * Returns whether there exists a LinkedModeManager on any of the documents.
	 *
	 * @param documents the documents of interest
	 * @return true if there exists a LinkedModeManager on any of the documents, false otherwise
	 */
	public static boolean hasManager(IDocument[] documents) {
		for (IDocument document : documents) {
			if (hasManager(document))
				return true;
		}
		return false;
	}

	/**
	 * Returns the manager for the given documents. If force is
	 * true, any existing conflicting managers are canceled, otherwise,
	 * the method may return null if there are conflicts.
	 *
	 * @param documents the documents of interest
	 * @param force whether to kill any conflicting managers
	 * @return a manager able to cover the requested documents, or null if there is a conflict and force was set to false
	 */
	public static LinkedModeManager getLinkedManager(IDocument[] documents, boolean force) {
		if (documents == null || documents.length == 0)
			return null;

		Set mgrs= new HashSet<>();
		LinkedModeManager mgr= null;
		for (IDocument document : documents) {
			mgr= fgManagers.get(document);
			if (mgr != null)
				mgrs.add(mgr);
		}
		if (mgrs.size() > 1)
			if (force) {
				for (LinkedModeManager m : mgrs) {
					m.closeAllEnvironments();
				}
			} else {
				return null;
			}

		if (mgrs.isEmpty())
			mgr= new LinkedModeManager();

		for (IDocument document : documents)
			fgManagers.put(document, mgr);

		return mgr;
	}

	/**
	 * Cancels any linked mode manager for the specified document.
	 *
	 * @param document the document whose LinkedModeManager should be canceled
	 */
	public static void cancelManager(IDocument document) {
		LinkedModeManager mgr= fgManagers.get(document);
		if (mgr != null)
			mgr.closeAllEnvironments();
	}

	/** The hierarchy of environments managed by this manager. */
	private Stack fEnvironments= new Stack<>();
	private Listener fListener= new Listener();

	/**
	 * Notify the manager about a leaving model.
	 *
	 * @param model the model to nest
	 * @param flags the reason and commands for leaving linked mode
	 */
	private void left(LinkedModeModel model, int flags) {
		if (!fEnvironments.contains(model))
			return;

		while (!fEnvironments.isEmpty()) {
			LinkedModeModel env= fEnvironments.pop();
			if (env == model)
				break;
			env.exit(ILinkedModeListener.NONE);
		}

		if (fEnvironments.isEmpty()) {
			removeManager();
		}
	}

	private void closeAllEnvironments() {
		while (!fEnvironments.isEmpty()) {
			LinkedModeModel env= fEnvironments.pop();
			env.exit(ILinkedModeListener.NONE);
		}

		removeManager();
	}

	private void removeManager() {
		for (Iterator it= fgManagers.values().iterator(); it.hasNext();) {
			if (it.next() == this)
				it.remove();
		}
	}

	/**
	 * Tries to nest the given LinkedModeModel onto the top of
	 * the stack of environments managed by the receiver. If force
	 * is true, any environments on the stack that create a conflict
	 * are killed.
	 *
	 * @param model the model to nest
	 * @param force whether to force the addition of the model
	 * @return true if nesting was successful, false otherwise (only possible if force is false
	 */
	public boolean nestEnvironment(LinkedModeModel model, boolean force) {
		Assert.isNotNull(model);

		try {
			while (true) {
				if (fEnvironments.isEmpty()) {
					model.addLinkingListener(fListener);
					fEnvironments.push(model);
					return true;
				}

				LinkedModeModel top= fEnvironments.peek();
				if (model.canNestInto(top)) {
					model.addLinkingListener(fListener);
					fEnvironments.push(model);
					return true;
				} else if (!force) {
					return false;
				} else { // force
					fEnvironments.pop();
					top.exit(ILinkedModeListener.NONE);
					// continue;
				}
			}
		} finally {
			// if we remove any, make sure the new one got inserted
			Assert.isTrue(!fEnvironments.isEmpty());
		}
	}

	/**
	 * Returns the LinkedModeModel that is on top of the stack of
	 * environments managed by the receiver.
	 *
	 * @return the topmost LinkedModeModel
	 */
	public LinkedModeModel getTopEnvironment() {
		if (fEnvironments.isEmpty())
			return null;
		return fEnvironments.peek();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy