blob: 04e4e1b16b1262c02c640d1eeaa0e6b950eb45b1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Obeo.
* 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:
* Obeo - initial API and implementation and/or initial documentation
* ...
*******************************************************************************/
package org.eclipse.intent.mapping.ide;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.intent.mapping.base.IBase;
import org.eclipse.intent.mapping.base.ILocation;
import org.eclipse.intent.mapping.base.ILocationDescriptor;
import org.eclipse.intent.mapping.ide.connector.IFileDelegateRegistry;
import org.eclipse.intent.mapping.ide.internal.connector.FileDelegateRegistry;
import org.eclipse.intent.mapping.ide.resource.IFileLocation;
/**
* Ide mapping utilities.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public final class IdeMappingUtils {
/**
* Listener for the {@link IdeMappingUtils#getSynchronizationPalette() synchronization palette}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public interface ISynchronizationPaletteListener {
/**
* Stub implementation.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
class Stub implements ISynchronizationPaletteListener {
/**
* {@inheritDoc}
*
* @see org.eclipse.intent.mapping.ide.IdeMappingUtils.ISynchronizationPaletteListener#locationActivated(org.eclipse.intent.mapping.base.ILocationDescriptor)
*/
public void locationActivated(ILocationDescriptor locationDescriptor) {
// nothing to do here
}
/**
* {@inheritDoc}
*
* @see org.eclipse.intent.mapping.ide.IdeMappingUtils.ISynchronizationPaletteListener#locationDeactivated(org.eclipse.intent.mapping.base.ILocationDescriptor)
*/
public void locationDeactivated(ILocationDescriptor locationDescriptor) {
// nothing to do here
}
/**
* {@inheritDoc}
*
* @see org.eclipse.intent.mapping.ide.IdeMappingUtils.ISynchronizationPaletteListener#contentsAdded(org.eclipse.intent.mapping.base.ILocationDescriptor)
*/
public void contentsAdded(ILocationDescriptor locationDescriptor) {
// nothing to do here
}
/**
* {@inheritDoc}
*
* @see org.eclipse.intent.mapping.ide.IdeMappingUtils.ISynchronizationPaletteListener#contentsRemoved(org.eclipse.intent.mapping.base.ILocationDescriptor)
*/
public void contentsRemoved(ILocationDescriptor locationDescriptor) {
// nothing to do here
}
}
/**
* Notifies that the given {@link ILocationDescriptor} has been activated.
*
* @param locationDescriptor
* the activated {@link ILocationDescriptor}
*/
void locationActivated(ILocationDescriptor locationDescriptor);
/**
* Notifies that the given {@link ILocationDescriptor} has been deactivated.
*
* @param locationDescriptor
* the deactivated {@link ILocationDescriptor}
*/
void locationDeactivated(ILocationDescriptor locationDescriptor);
/**
* Notifies that a {@link ILocationDescriptor} has been added.
*
* @param locationDescriptor
* the added {@link ILocationDescriptor}
*/
void contentsAdded(ILocationDescriptor locationDescriptor);
/**
* Notifies that a {@link ILocationDescriptor} has been removed.
*
* @param locationDescriptor
* the removed {@link ILocationDescriptor}
*/
void contentsRemoved(ILocationDescriptor locationDescriptor);
}
/**
* Listener for {@link IdeMappingUtils#getCurrentBase() current base}
* {@link IdeMappingUtils#setCurrentBase(IBase) change}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public interface ICurrentBaseListener {
/**
* Notifies that the {@link IdeMappingUtils#getCurrentBase() current base} has been
* {@link IdeMappingUtils#setCurrentBase(IBase) changed}.
*
* @param oldBase
* the old {@link IBase}
* @param newBase
* the new {@link IBase}
*/
void currentBaseChanged(IBase oldBase, IBase newBase);
}
/**
* The {@link IFileDelegateRegistry} instance.
*/
private static final IFileDelegateRegistry REGISTRY = new FileDelegateRegistry();
/**
* Mapping from an {@link ILocation} and it's {@link IMarker}.
*/
private static final Map<ILocation, IMarker> LOCATION_TO_MARKER = new HashMap<ILocation, IMarker>();
/**
* The palette of {@link ILocationDescriptor} to link with.
*/
private static final Map<ILocationDescriptor, Boolean> LOCATIONS_PALETTE = new LinkedHashMap<ILocationDescriptor, Boolean>();
/**
* The {@link List} of {@link ISynchronizationPaletteListener}.
*/
private static final List<ISynchronizationPaletteListener> LOCATIONS_PALETTE_LISTENERS = new ArrayList<ISynchronizationPaletteListener>();
/**
* The {@link List} of {@link ISynchronizationPaletteListener}.
*/
private static final List<ICurrentBaseListener> CURRENT_BASE_LISTENERS = new ArrayList<ICurrentBaseListener>();
/**
* The current {@link IBase}.
*/
private static IBase currentBase;
static {
CURRENT_BASE_LISTENERS.add(new ICurrentBaseListener() {
public void currentBaseChanged(IBase oldBase, IBase newBase) {
for (ILocationDescriptor descriptor : getSynchronizationPalette()) {
removeLocationFromPalette(descriptor);
}
}
});
}
/**
* Constructor.
*/
private IdeMappingUtils() {
// nothing to do here
}
/**
* Gets the {@link IFileDelegateRegistry}.
*
* @return the {@link IFileDelegateRegistry}
*/
public static IFileDelegateRegistry getFileConectorDelegateRegistry() {
return REGISTRY;
}
/**
* Adapts the given {@link Object element} into an {@link Object} of the given {@link Class}.
*
* @param element
* the {@link Object element}
* @param cls
* the {@link Class}
* @return the {@link Object} of the given {@link Class} if any, <code>null</code> otherwise
* @param <T>
* the kind of result
*/
@SuppressWarnings("unchecked")
public static <T> T adapt(Object element, Class<T> cls) {
final T res;
if (cls.isInstance(element)) {
res = (T)element;
} else if (element instanceof IAdaptable) {
final T adaptedElement = (T)((IAdaptable)element).getAdapter(cls);
if (adaptedElement != null) {
res = adaptedElement;
} else {
res = (T)Platform.getAdapterManager().getAdapter(element, cls);
}
} else if (element != null) {
res = (T)Platform.getAdapterManager().getAdapter(element, cls);
} else {
res = null;
}
return res;
}
/**
* Sets the current {@link IBase} to the given {@link IBase}.
*
* @param newBase
* the new {@link IBase}
*/
public static void setCurrentBase(IBase newBase) {
if (currentBase != newBase) {
final IBase oldBase = currentBase;
currentBase = newBase;
for (ICurrentBaseListener listener : getCurrentBaseListeners()) {
listener.currentBaseChanged(oldBase, newBase);
}
}
}
/**
* Gets the current {@link IBase}.
*
* @return the current {@link IBase}
*/
public static IBase getCurrentBase() {
return currentBase;
}
/**
* Gets the {@link ILocation#getContainer() containing} {@link IFileLocation} of the given
* {@link ILocation} or itself if it's a {@link IFileLocation}.
*
* @param location
* the {@link ILocation}
* @return the {@link ILocation#getContainer() containing} {@link IFileLocation} of the given
* {@link ILocation} or itself if it's a {@link IFileLocation}, <code>null</code> if none is found
*/
public static IFileLocation getContainingFileLocation(ILocation location) {
final IFileLocation res;
if (location instanceof IFileLocation) {
res = (IFileLocation)location;
} else if (location.getContainer() instanceof ILocation) {
res = getContainingFileLocation((ILocation)location.getContainer());
} else {
res = null;
}
return res;
}
/**
* Gets or creates the {@link IMarker} for the given {@link ILocation}.
*
* @param location
* the {@link ILocation}
* @return the {@link IMarker} for the given {@link ILocation} if any exists or can be created,
* <code>null</code> otherwise
*/
public static IMarker getOrCreateMarker(ILocation location) {
final IMarker res;
final IMarker existingMarker = getMarker(location);
if (existingMarker == null) {
res = IdeMappingUtils.adapt(location, IMarker.class);
if (res != null) {
LOCATION_TO_MARKER.put(location, res);
}
} else {
res = existingMarker;
}
return res;
}
/**
* Gets the cached marker for the given {@link ILocation}.
*
* @param location
* the {@link ILocation}
* @return the cached marker for the given {@link ILocation} if any, <code>null</code> otherwise
*/
public static IMarker getMarker(ILocation location) {
return LOCATION_TO_MARKER.get(location);
}
/**
* {@link IMarker#delete() Deletes} the {@link IMarker} for the given {@link ILocation}.
*
* @param location
* the {@link ILocation}
*/
public static void deleteMarker(ILocation location) {
final IMarker marker = LOCATION_TO_MARKER.remove(location);
if (marker != null) {
try {
marker.delete();
} catch (CoreException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
"unable to delete a location markers for " + marker.getResource().getFullPath()
.toString(), e));
}
}
}
/**
* Removes the {@link IMarker} for the given {@link ILocation}.
*
* @param location
* the {@link ILocation}
* @see #deleteMarker(ILocation) for deletion
*/
public static void removeMarker(ILocation location) {
LOCATION_TO_MARKER.remove(location);
}
/**
* Gets the palette of {@link ILocationDescriptor} to link with.
*
* @return the palette of {@link ILocationDescriptor} to link with
*/
public static Set<ILocationDescriptor> getSynchronizationPalette() {
synchronized(LOCATIONS_PALETTE) {
return Collections.unmodifiableSet(new LinkedHashSet(LOCATIONS_PALETTE.keySet()));
}
}
/**
* Gets the {@link List} of {@link ISynchronizationPaletteListener} in a thread safe way.
*
* @return the {@link List} of {@link ISynchronizationPaletteListener} in a thread safe way
*/
private static List<ISynchronizationPaletteListener> getSynchronizationPaletteListeners() {
synchronized(LOCATIONS_PALETTE_LISTENERS) {
return new ArrayList<ISynchronizationPaletteListener>(LOCATIONS_PALETTE_LISTENERS);
}
}
/**
* Adds the given {@link ILocationDescriptor} to the {@link #getSynchronizationPalette() palette of
* location descriptor}.
*
* @param locationDescriptor
* the {@link ILocationDescriptor} to add
*/
public static void addLocationToPalette(ILocationDescriptor locationDescriptor) {
final Boolean added;
synchronized(LOCATIONS_PALETTE) {
added = LOCATIONS_PALETTE.put(locationDescriptor, false);
}
if (added == null || added) {
for (ISynchronizationPaletteListener listener : getSynchronizationPaletteListeners()) {
listener.contentsAdded(locationDescriptor);
}
}
}
/**
* Removes the given {@link ILocationDescriptor} from the {@link #getSynchronizationPalette() palette of
* location descriptor}.
*
* @param locationDescriptor
* the {@link ILocation} to remove
*/
public static void removeLocationFromPalette(ILocationDescriptor locationDescriptor) {
final Boolean removed;
synchronized(LOCATIONS_PALETTE) {
removed = LOCATIONS_PALETTE.remove(locationDescriptor);
}
if (removed != null) {
for (ISynchronizationPaletteListener listener : getSynchronizationPaletteListeners()) {
listener.contentsRemoved(locationDescriptor);
}
}
}
/**
* Adds the given {@link ISynchronizationPaletteListener}.
*
* @param listener
* the {@link ISynchronizationPaletteListener} to add
*/
public static void addSynchronizationPaletteListener(ISynchronizationPaletteListener listener) {
synchronized(LOCATIONS_PALETTE_LISTENERS) {
LOCATIONS_PALETTE_LISTENERS.add(listener);
}
}
/**
* removes the given {@link ISynchronizationPaletteListener}.
*
* @param listener
* the {@link ISynchronizationPaletteListener} to remove
*/
public static void removeSynchronizationPaletteListener(ISynchronizationPaletteListener listener) {
synchronized(LOCATIONS_PALETTE_LISTENERS) {
LOCATIONS_PALETTE_LISTENERS.remove(listener);
}
}
/**
* Activates the given {@link ILocationDescriptor} form the {@link #getSynchronizationPalette() palette of
* location descriptor}.
*
* @param locationDescriptor
* the {@link ILocationDescriptor} to activate
*/
public static void activateLocation(ILocationDescriptor locationDescriptor) {
final boolean changed;
synchronized(LOCATIONS_PALETTE) {
if (LOCATIONS_PALETTE.containsKey(locationDescriptor)) {
final Boolean lastValue = LOCATIONS_PALETTE.put(locationDescriptor, Boolean.TRUE);
changed = lastValue == null || !lastValue;
} else {
changed = false;
}
}
if (changed) {
for (ISynchronizationPaletteListener listener : getSynchronizationPaletteListeners()) {
listener.locationActivated(locationDescriptor);
}
}
}
/**
* Deactivates the given {@link ILocationDescriptor} form the {@link #getSynchronizationPalette() palette
* of location descriptor}.
*
* @param locationDescriptor
* the {@link ILocationDescriptor} to deactivate
*/
public static void deactivateLocation(ILocationDescriptor locationDescriptor) {
final boolean changed;
synchronized(LOCATIONS_PALETTE) {
if (LOCATIONS_PALETTE.containsKey(locationDescriptor)) {
final Boolean lastValue = LOCATIONS_PALETTE.put(locationDescriptor, Boolean.FALSE);
changed = lastValue == null || lastValue;
} else {
changed = false;
}
}
if (changed) {
for (ISynchronizationPaletteListener listener : getSynchronizationPaletteListeners()) {
listener.locationDeactivated(locationDescriptor);
}
}
}
/**
* Tells if the given {@link ILocationDescriptor} from the
* {@link IdeMappingUtils#getSynchronizationPalette() location descriptors palette} is active.
*
* @param locationDescriptor
* the {@link ILocationDescriptor}
* @return <code>true</code> if the given {@link ILocationDescriptor} from the
* {@link IdeMappingUtils#getSynchronizationPalette() location descriptors palette} is active,
* <code>false</code> otherwise
*/
public static boolean isActive(ILocationDescriptor locationDescriptor) {
final boolean res;
synchronized(LOCATIONS_PALETTE) {
final Boolean isActive = LOCATIONS_PALETTE.get(locationDescriptor);
res = isActive != null && isActive;
}
return res;
}
/**
* Tells if there is at least one {@link IdeMappingUtils#isActive(ILocationDescriptor) active}
* {@link ILocationDescriptor} in the {@link IdeMappingUtils#getSynchronizationPalette() location
* descriptors palette} .
*
* @return <code>true</code> if there is at least one {@link IdeMappingUtils#isActive(ILocationDescriptor)
* active} {@link ILocationDescriptor} in the {@link IdeMappingUtils#getSynchronizationPalette()
* location descriptors palette}, <code>false</code> otherwise
*/
public static boolean asActiveLocationDescriptor() {
synchronized(LOCATIONS_PALETTE) {
return LOCATIONS_PALETTE.values().contains(Boolean.TRUE);
}
}
/**
* Gets the {@link List} of {@link ICurrentBaseListener} in a thread safe way.
*
* @return the {@link List} of {@link ICurrentBaseListener} in a thread safe way
*/
private static List<ICurrentBaseListener> getCurrentBaseListeners() {
synchronized(CURRENT_BASE_LISTENERS) {
return new ArrayList<ICurrentBaseListener>(CURRENT_BASE_LISTENERS);
}
}
/**
* Adds the given {@link ICurrentBaseListener}.
*
* @param listener
* the {@link ICurrentBaseListener} to add
*/
public static void addCurrentBaseListener(ICurrentBaseListener listener) {
synchronized(CURRENT_BASE_LISTENERS) {
CURRENT_BASE_LISTENERS.add(listener);
}
}
/**
* Removes the given {@link ICurrentBaseListener}.
*
* @param listener
* the {@link ICurrentBaseListener} to remove
*/
public static void removeCurrentBaseListener(ICurrentBaseListener listener) {
synchronized(CURRENT_BASE_LISTENERS) {
CURRENT_BASE_LISTENERS.remove(listener);
}
}
}