/******************************************************************************* * Copyright (c) 2010, 2011 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 *******************************************************************************/ package org.eclipse.mylyn.docs.intent.collab.ide.notification; import com.google.common.collect.Sets; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.mylyn.docs.intent.collab.handlers.notification.Notificator; import org.eclipse.mylyn.docs.intent.collab.handlers.notification.RepositoryChangeNotification; import org.eclipse.mylyn.docs.intent.collab.handlers.notification.RepositoryChangeNotificationFactoryHolder; /** * Listens for any change that occur on an instance of the given types, an notify the associated * TypeNotificator. * * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a> */ public class WorkspaceTypeListener { /** * The type notificator to notify if changes are detected. */ private final Notificator typeNotificator; /** * List of the types to listen. */ private final Set<EStructuralFeature> listenedTypes; /** * WorkspaceTypeListener constructor. * * @param typeNotificator * The type notificator to notify if changes are detected * @param typesToListen * List of the types to listen */ public WorkspaceTypeListener(Notificator typeNotificator, Set<EStructuralFeature> typesToListen) { this.typeNotificator = typeNotificator; this.listenedTypes = new LinkedHashSet<EStructuralFeature>(); this.listenedTypes.addAll(typesToListen); } /** * This method is called by the Workspace Session any time a resource located on the repository changes ; * must notify the notificator if the resource contained one of the listened types. * * @param resource * the resource that has changed */ public void notifyResourceChanged(Resource resource) { boolean changesDetected = false; // We determine if any of the roots contained in the resource is a listened type Iterator<EObject> contentIterator = Sets.newLinkedHashSet(resource.getContents()).iterator(); while (contentIterator.hasNext() && !changesDetected) { EObject nextRoot = contentIterator.next(); Iterator<EStructuralFeature> rootFeaturesIterator = nextRoot.eClass().getEAllStructuralFeatures() .iterator(); while (rootFeaturesIterator.hasNext() && !changesDetected) { EStructuralFeature next = rootFeaturesIterator.next(); changesDetected = isListenedTypeModification(next); } } // If this type Listener must notify its associated notificator if (changesDetected) { RepositoryChangeNotification newNotification = RepositoryChangeNotificationFactoryHolder .getChangeNotificationFactory().createRepositoryChangeNotification(resource); if (newNotification != null) { this.typeNotificator.notifyHandlers(newNotification); } } } /** * Returns true if the given feature matches any listened types of this typeListener. * * @param feature * the feature to test. * @return true if the given feature matches any listened types of this typeListener, false otherwise. */ private boolean isListenedTypeModification(EStructuralFeature feature) { boolean isListenedType = false; for (Iterator<EStructuralFeature> iterator = listenedTypes.iterator(); iterator.hasNext() && !isListenedType;) { ENamedElement listenedtype = iterator.next(); if (listenedtype instanceof EStructuralFeature) { isListenedType = listenedtype.equals(feature); } if (listenedtype instanceof EClass) { isListenedType = ((EClass)listenedtype).getEAllStructuralFeatures().contains(feature); } } return isListenedType; } }