blob: e169df418a60ba119cd7f44e75e03a84a9dc0a69 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008-2021 See4sys, BMW Car IT, itemis, Siemens 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:
* See4sys - Initial API and implementation
* BMW Car IT - Avoid usage of Object.finalize
* itemis - [409014] Listener URIChangeDetector registered for all transactional editing domains
* Siemens - [577073] URI change detector delegate extension
*
* </copyright>
*/
package org.eclipse.sphinx.emf.workspace.referentialintegrity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.ResourceSetChangeEvent;
import org.eclipse.emf.transaction.ResourceSetListenerImpl;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.sphinx.emf.domain.factory.AbstractResourceSetListenerInstaller;
import org.eclipse.sphinx.emf.util.EcorePlatformUtil;
import org.eclipse.sphinx.emf.workspace.Activator;
import org.eclipse.sphinx.platform.resources.DefaultResourceChangeHandler;
import org.eclipse.sphinx.platform.resources.ResourceDeltaVisitor;
import org.eclipse.sphinx.platform.util.PlatformLogUtil;
/**
* URIChangeDetector is in charge of Handling URI Change Detection.It converts {@link IResourceChangeEvent} and
* {@link ResourceSetChangeEvent} into {@link URIChangeEvent} and notifies registered {@link URIChangeListener}.see also
* {@link URIChangeListenerRegistry}.
*/
public class URIChangeDetector extends ResourceSetListenerImpl implements IResourceChangeListener {
public static class URIChangeDetectorInstaller extends AbstractResourceSetListenerInstaller<URIChangeDetector> {
public URIChangeDetectorInstaller() {
super(URIChangeDetector.class);
}
}
/**
* Default constructor.
*/
public URIChangeDetector() {
}
@Override
public void setTarget(TransactionalEditingDomain domain) {
super.setTarget(domain);
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
@Override
public void unsetTarget(TransactionalEditingDomain domain) {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
super.unsetTarget(domain);
}
/*
* @see org.eclipse.emf.transaction.ResourceSetListener#resourceSetChanged(org.eclipse.emf.transaction.
* ResourceSetChangeEvent )
*/
@Override
public void resourceSetChanged(ResourceSetChangeEvent event) {
List<?> notifications = event.getNotifications();
// Split the notifications based on their delegate handler into smaller lists
Map<IURIChangeDetectorDelegate, List<Notification>> delegateToNotifications = new HashMap<>();
for (Object o : notifications) {
if (o instanceof Notification) {
Notification notification = (Notification) o;
if (notification.getNotifier() instanceof EObject) {
Resource resource = ((EObject) notification.getNotifier()).eResource();
IURIChangeDetectorDelegate delegate = URIChangeDetectorDelegateRegistry.INSTANCE.getDetectorDelegate(resource);
if (delegate != null) {
delegateToNotifications.computeIfAbsent(delegate, d -> new ArrayList<Notification>()).add(notification);
}
}
}
}
for (IURIChangeDetectorDelegate delegate : delegateToNotifications.keySet()) {
List<Notification> delegateNotifications = delegateToNotifications.get(delegate);
Map<Resource, List<URIChangeNotification>> resourceToUriNotifications = delegate.detectChangedURIs(delegateNotifications);
if (resourceToUriNotifications == null) {
/** assume that the new API is not implemented, call the deprecated API */
for (Notification notification : delegateNotifications) {
if (notification.getNotifier() instanceof EObject) {
EObject newEObject = (EObject) notification.getNotifier();
Resource resource = newEObject.eResource();
@SuppressWarnings("deprecation")
List<URIChangeNotification> uriNotifications = delegate.detectChangedURIs(notification);
if (uriNotifications != null && !uriNotifications.isEmpty()) {
fireURIChanged(createURIChangeEvent(resource, uriNotifications));
}
}
}
} else if (!resourceToUriNotifications.isEmpty()) {
for (Resource resource : resourceToUriNotifications.keySet()) {
fireURIChanged(createURIChangeEvent(resource, resourceToUriNotifications.get(resource)));
}
}
}
}
@Override
public boolean isPostcommitOnly() {
return true;
}
/*
* @seeorg.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.
* IResourceChangeEvent)
*/
@Override
public void resourceChanged(IResourceChangeEvent event) {
try {
IResourceDelta delta = event.getDelta();
if (delta != null) {
IResourceDeltaVisitor visitor = new ResourceDeltaVisitor(event.getType(), new DefaultResourceChangeHandler() {
@Override
public void handleFileMoved(int eventType, IFile oldFile, IFile newFile) {
if (eventType == IResourceChangeEvent.POST_CHANGE) {
Resource resource = EcorePlatformUtil.getResource(oldFile);
if (resource != null) {
IURIChangeDetectorDelegate delegate = URIChangeDetectorDelegateRegistry.INSTANCE.getDetectorDelegate(resource);
if (delegate != null) {
List<URIChangeNotification> notifications = delegate.detectChangedURIs(oldFile, newFile);
if (!notifications.isEmpty()) {
fireURIChanged(createURIChangeEvent(resource, notifications));
}
}
}
}
}
});
delta.accept(visitor);
}
} catch (Exception ex) {
PlatformLogUtil.logAsError(Activator.getDefault(), ex);
}
}
// TODO integrate notification creation into Delegates
protected URIChangeEvent createURIChangeEvent(Resource source, List<URIChangeNotification> notifications) {
if (source != null && notifications != null && notifications.isEmpty()) {
return null;
}
return new URIChangeEvent(source, notifications);
}
private void fireURIChanged(URIChangeEvent event) {
if (event != null) {
for (IURIChangeListener listener : URIChangeListenerRegistry.INSTANCE.getListeners()) {
listener.uriChanged(event);
}
}
}
}