/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company 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:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.dialogs.MessageDialog;
import com.rcpcompany.utils.logging.LogUtils;
/**
* Various utilities related to the model.
*
* @author Tonny Madsen, The RCP Company
*/
public final class UIBEcoreUtils {
private UIBEcoreUtils() {
}
/**
* Returns a description of the objects that has a <em>required</em> reference into the
* specified set of objects (or their containment children).
*
* @param objects the objects to test
* @return the objects with references
*/
public static Map<EObject, Collection<EStructuralFeature.Setting>> findIncomingRequiredReferences(
Collection<? extends EObject> objects) {
/*
* Find the involved objects
*/
final Collection<EObject> eObjects = getContainmentTree(objects);
/*
* Find all references into these objects
*/
final EditingDomain domain = EditingDomainUtils.getEditingDomain();
final Map<EObject, Collection<EStructuralFeature.Setting>> usages = EcoreUtil.UsageCrossReferencer.findAll(
eObjects, domain.getResourceSet());
/*
* Find the objects that have a required reference into the objects
*/
for (final Map.Entry<EObject, Collection<EStructuralFeature.Setting>> entry : usages.entrySet().toArray(
new Map.Entry[usages.entrySet().size()])) {
final EObject eObject = entry.getKey();
if (eObject.eResource() != null) {
continue;
}
final Collection<EStructuralFeature.Setting> settings = entry.getValue();
for (final EStructuralFeature.Setting setting : settings.toArray(new EStructuralFeature.Setting[settings
.size()])) {
final EObject referencingEObject = setting.getEObject();
if (eObjects.contains(referencingEObject)) {
continue;
}
final EStructuralFeature sf = setting.getEStructuralFeature();
/*
* Keep the reference if it is not-changeable
*/
if (!sf.isChangeable()) {
continue;
}
/*
* If it is a to-one required reference, then we keep it
*/
if (!sf.isMany() && sf.isRequired()) {
continue;
}
settings.remove(setting);
}
if (entry.getValue().isEmpty()) {
usages.remove(eObject);
}
}
if (usages.isEmpty()) return null;
return usages;
}
/**
* Returns the collection of objects from the specified set of objects and their containment
* children.
*
* @param objects the objects
* @return the same objects along with their containment children
*/
private static Collection<EObject> getContainmentTree(Collection<? extends EObject> objects) {
final Collection<EObject> objs = new ArrayList<EObject>();
for (final Object wrappedObject : objects) {
final Object object = AdapterFactoryEditingDomain.unwrap(wrappedObject);
if (object instanceof EObject) {
objs.add((EObject) object);
for (final Iterator<EObject> j = ((EObject) object).eAllContents(); j.hasNext();) {
objs.add(j.next());
}
} else if (object instanceof Resource) {
for (final Iterator<EObject> j = ((Resource) object).getAllContents(); j.hasNext();) {
objs.add(j.next());
}
}
}
return objs;
}
/**
* Shows an error dialog.
*
* @param title the title for the dialog
* @param description the first line(s) of a description used for the dialog
* @param references the references for the objects that cannot be handled
*/
public static void showErrorDialog(String title, String description, Map<EObject, Collection<Setting>> references) {
LogUtils.debug("", title);
if (references == null) {
description += "\n\nReferences are found.";
} else {
description += "\n\nThe following references are found:\n";
for (final Entry<EObject, Collection<Setting>> e : references.entrySet()) {
description += "\n " + IBindingObjectInformation.Factory.getQualifiedName(e.getKey()) + ":";
for (final Setting s : e.getValue()) {
description += "\n " + s.getEStructuralFeature().getName() + " of "
+ IBindingObjectInformation.Factory.getQualifiedName(s.getEObject());
}
}
}
MessageDialog.openError(null, title, description);
}
}