/*****************************************************************************
* Copyright (c) 2010 Atos Origin.
*
*
* 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:
* Atos Origin - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.groups.core.groupcontainment;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.groups.groupcontainment.AbstractContainerNodeDescriptor;
/**
* This registry recovers information from the extensions for the GroupContainment point.
*
* @author vhemery
*/
public class GroupContainmentRegistry {
/** The GroupContainment extension point id */
private static final String GROUP_EXTENSION_POINT = "org.eclipse.papyrus.uml.diagram.common.groups.groupcontainment";
/** The name of the extension node for model containment */
private static final String MODEL_CONTAINER_NODE = "modelContainer";
/** The name of the extension node for graphical container with model reference */
private static final String REFERENCE_CONTAINER_NODE = "referenceContainer";
/** The name of the descriptor attribute */
private static final String CONTAINER_DESCRIPTOR_ATTRIBUTE = "descriptor";
/** The name of the edit part type attribute */
private static final String EDIT_PART_TYPE_ATTRIBUTE = "editPartType";
/** The map of descriptors for model containers, by type of edit part */
private static Map<String, AbstractContainerNodeDescriptor> modelContainersDescriptors = new HashMap<String, AbstractContainerNodeDescriptor>();
/** The map of descriptors for graphical containers only, by type of edit part */
private static Map<String, AbstractContainerNodeDescriptor> graphicalContainersDescriptors = new HashMap<String, AbstractContainerNodeDescriptor>();
/** The map of descriptor allowing to recover the group part from a view, by view type */
private static Map<String, AbstractContainerNodeDescriptor> descriptorForViewType = new HashMap<String, AbstractContainerNodeDescriptor>();
/**
* Initialize the values from the extension point
*/
static {
initialize();
}
/**
* Load all extensions and register the container descriptors
*/
public static void initialize() {
// Load extensions of edit part mapping
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint extensionPoint = registry.getExtensionPoint(GROUP_EXTENSION_POINT);
for(IExtension extension : extensionPoint.getExtensions()) {
for(IConfigurationElement providing : extension.getConfigurationElements()) {
if(MODEL_CONTAINER_NODE.equals(providing.getName())) {
String editPartType = providing.getAttribute(EDIT_PART_TYPE_ATTRIBUTE);
if(editPartType != null) {
try {
Object provider = providing.createExecutableExtension(CONTAINER_DESCRIPTOR_ATTRIBUTE);
if(provider instanceof AbstractContainerNodeDescriptor) {
modelContainersDescriptors.put(editPartType, (AbstractContainerNodeDescriptor)provider);
}
} catch (CoreException e) {
// ignore this extension node
}
}
} else if(REFERENCE_CONTAINER_NODE.equals(providing.getName())) {
String editPartType = providing.getAttribute(EDIT_PART_TYPE_ATTRIBUTE);
if(editPartType != null) {
try {
Object provider = providing.createExecutableExtension(CONTAINER_DESCRIPTOR_ATTRIBUTE);
if(provider instanceof AbstractContainerNodeDescriptor) {
graphicalContainersDescriptors.put(editPartType, (AbstractContainerNodeDescriptor)provider);
}
} catch (CoreException e) {
// ignore this extension node
}
}
}
}
}
}
/**
* Get the AbstractContainerNodeDescriptor from a EClass
*
* @param containerEClass
* @return Set<AbstractContainerNodeDescriptor> Return all the descriptor which match the corresponding EClass
*/
public static Set<AbstractContainerNodeDescriptor> getDescriptorsWithContainerEClass(EClass containerEClass) {
Set<AbstractContainerNodeDescriptor> descriptors = new HashSet<AbstractContainerNodeDescriptor>(modelContainersDescriptors.size() + graphicalContainersDescriptors.size());
Set<AbstractContainerNodeDescriptor> descriptorsResult = new HashSet<AbstractContainerNodeDescriptor>(modelContainersDescriptors.size() + graphicalContainersDescriptors.size());
descriptors.addAll(modelContainersDescriptors.values());
descriptors.addAll(graphicalContainersDescriptors.values());
// filter descriptors
for(AbstractContainerNodeDescriptor descriptor : descriptors) {
if(descriptor.getContainerEClass().equals(containerEClass)) {
descriptorsResult.add(descriptor);
}
}
return descriptorsResult;
}
/**
* Get all the references which can point to a group
*
* @return give back a set of ERefences pointing at group
*/
public static Set<EReference> getAllERefencesFromNodeToGroup() {
Set<EReference> referencesResult = new HashSet<EReference>();
Set<AbstractContainerNodeDescriptor> descriptors = new HashSet<AbstractContainerNodeDescriptor>(modelContainersDescriptors.size() + graphicalContainersDescriptors.size());
descriptors.addAll(modelContainersDescriptors.values());
descriptors.addAll(graphicalContainersDescriptors.values());
for(AbstractContainerNodeDescriptor descriptor : descriptors) {
for(EReference ref : descriptor.getChildrenReferences()) {
EReference eoppositeRef = ref.getEOpposite();
if(eoppositeRef != null) {
referencesResult.add(eoppositeRef);
}
}
}
return referencesResult;
}
/**
* Know whether the edit part is concerned by the group framework, which means there is a container descriptor for its class.
*
* @param editPart
* the edit part to test
* @return true if there is a descriptor
*/
public static boolean isContainerConcerned(IGraphicalEditPart editPart) {
if(editPart == null) {
return false;
}
String editPartClassName = editPart.getClass().getCanonicalName();
return modelContainersDescriptors.containsKey(editPartClassName) || graphicalContainersDescriptors.containsKey(editPartClassName);
}
/**
* Return true it the element pointed by the EditPart is a node whicj=h is concerned by the framework
*
* @param editPart
* of EObject you want to test
* @return
*/
public static boolean isNodeConcerned(IGraphicalEditPart editPart) {
EClass current = editPart.resolveSemanticElement().eClass();
Set<EReference> allReferences = new HashSet<EReference>();
for(AbstractContainerNodeDescriptor nodeDesc1 : modelContainersDescriptors.values()) {
allReferences.addAll(nodeDesc1.getChildrenReferences());
}
for(AbstractContainerNodeDescriptor nodeDesc2 : graphicalContainersDescriptors.values()) {
allReferences.addAll(nodeDesc2.getChildrenReferences());
}
for(EReference ref : allReferences) {
if(ref.getEReferenceType().isSuperTypeOf(current)) {
return true;
}
}
return false;
}
/**
* Get the group descriptor of the edit part concerned by the group framework.
* Warning the edit part has to be exactly the same than the one register in the extension point.
* For example in the case of Activity Diagram. Onlu the compartment edit Part are register.
*
* @param editPart
* the edit part to get descriptor of
* @return container node descriptor or null if none
*/
public static AbstractContainerNodeDescriptor getContainerDescriptor(IGraphicalEditPart editPart) {
String editPartClassName = editPart.getClass().getCanonicalName();
if(modelContainersDescriptors.containsKey(editPartClassName)) {
return modelContainersDescriptors.get(editPartClassName);
} else if(graphicalContainersDescriptors.containsKey(editPartClassName)) {
return graphicalContainersDescriptors.get(editPartClassName);
} else {
return null;
}
}
/**
* Know whether the edit part concerned by the group framework is a model container.
*
* @param editPart
* the edit part to test
* @return true if the container is a direct model container
*/
public static boolean isContainerModel(IGraphicalEditPart editPart) {
String editPartClassName = editPart.getClass().getCanonicalName();
return modelContainersDescriptors.containsKey(editPartClassName);
}
/**
* Get the group compartment part (containing children elements) from a view of the node
*
* @param view
* a view, either of the compartment, or the primary node view
* @param diagramPart
* the diagram edit part to recover parts from views
* @return the group compartment part or null if none is adequate for the group framework
*/
public static IGraphicalEditPart getGroupContainingPartFromView(View view, DiagramEditPart diagramPart) {
String viewType = view.getType();
if(descriptorForViewType.containsKey(viewType)) {
// the appropriate descriptor has already been found for this view type
AbstractContainerNodeDescriptor desc = descriptorForViewType.get(viewType);
if(desc != null) {
return desc.getPartFromView(view, diagramPart);
} else {
return null;
}
} else {
// find the the appropriate descriptor for this view type
for(AbstractContainerNodeDescriptor desc : modelContainersDescriptors.values()) {
IGraphicalEditPart res = desc.getPartFromView(view, diagramPart);
if(res != null) {
// register for further use
descriptorForViewType.put(viewType, desc);
return res;
}
}
for(AbstractContainerNodeDescriptor desc : graphicalContainersDescriptors.values()) {
IGraphicalEditPart res = desc.getPartFromView(view, diagramPart);
if(res != null) {
// register for further use
descriptorForViewType.put(viewType, desc);
return res;
}
}
// register no result for further use
descriptorForViewType.put(viewType, null);
return null;
}
}
}