blob: a337586fe05cc76a271b1007671d559ac0bd5ff6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* SAP AG - initial API and implementation
******************************************************************************/
package org.eclipse.ocl.examples.eventmanager;
import java.util.Collection;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.ocl.examples.eventmanager.filters.AndFilter;
import org.eclipse.ocl.examples.eventmanager.filters.EventTypeFilter;
import org.eclipse.ocl.examples.eventmanager.filters.NewValueClassFilter;
import org.eclipse.ocl.examples.eventmanager.filters.NewValueClassFilterIncludingSubclasses;
import org.eclipse.ocl.examples.eventmanager.filters.OldValueClassFilter;
import org.eclipse.ocl.examples.eventmanager.filters.OldValueClassFilterIncludingSubclasses;
import org.eclipse.ocl.examples.eventmanager.filters.OrFilter;
/**
* Used to obtain an {@link EventManager} instance that listens to change
* {@link Notification}s occurring on zero or more {@link ResourceSet}s.
* Additionally, an event manager factory offers factory methods for event
* filters.
*
* @author Philipp Berger, Axel Uhl
*/
public interface EventManagerFactory {
/**
* The default instance implementing this interface
*/
EventManagerFactory eINSTANCE = org.eclipse.ocl.examples.eventmanager.framework.EventManagerFactoryImpl
.init();
/**
* Creates a new or re-uses an existing {@link EventManager} that was
* previously created by calling this operation (and not by
* {@link #createEventManagerFor(ResourceSet)}). The event manager receives
* all change notifications from all notifiers contained directly or
* indirectly by <code>set</code>. Those events matching the filters
* provided by listeners in their call to
* {@link EventManager#subscribe(EventFilter, org.eclipse.emf.common.notify.Adapter)}
* will be passed on to those listener {@link Adapter}s.
*
* @param set
* if <code>null</code>, a <code>null</code> result will be
* returned
* @return a valid, non-<code>null</code> {@link EventManager} if and only
* if <code>set!=null</code>
*/
EventManager getEventManagerFor(ResourceSet set);
/**
* Creates a new {@link EventManager} that initially does not receive change
* notifications from any resource set. This is useful if you want to be
* able to already register adapters with the event manager without knowing
* the resource sets from which those adapters later shall receive their
* notifications. Well-suited for creating long-lived event managers.
*/
EventManager createEventManager();
/**
* Creates a new {@link EventManager} that receives all change notifications
* from all notifiers contained directly or indirectly by <code>set</code>.
* Those events matching the filters provided by listeners in their call to
* {@link EventManager#subscribe(EventFilter, org.eclipse.emf.common.notify.Adapter)}
* will be passed on to those listener {@link Adapter}s. The event manager
* returned will never be returned by
* {@link #getEventManagerFor(ResourceSet)}. This is useful if you need to
* control which adapters subscribe to the event manager returned.
*/
EventManager createEventManagerFor(ResourceSet set);
/**
* Filters for a {@link Notification}'s {@link Notification#getEventType()
* event type}, such as {@link Notification#ADD} or
* {@link Notification#REMOVE}.
*
* @see EventTypeFilter#EventTypeFilter(int, boolean)
*/
EventFilter createEventTypeFilter(int eventType);
/**
* Creates a filter that matches if and only if <code>filter</code> does not
* match.
*/
EventFilter createNotFilter(EventFilter filter);
/**
* Creates a filter that matches a notification if its
* {@link Notification#getFeature() feature} equals <code>feature</code>.
*/
EventFilter createStructuralFeatureFilter(EStructuralFeature feature);
/**
* Creates a filter that matches a notification that indicates a change in
* containment. This may be an {@link EReference} with its
* {@link EReference#isContainer()} or {@link EReference#isContainment()}
* set to <code>true</code>, or it may be a change in the containment of a
* {@link Resource} in a {@link ResourceSet} or of an {@link EObject} in a
* {@link Resource}.
*/
EventFilter createContainmentFilter();
/**
* Creates a filter that matches a {@link Notification} if the
* {@link Notification#getNotifier() object that changed}
* {@link EObject#eClass() has <code>clazz</code> as its class}.
*/
EventFilter createClassFilter(EClass clazz);
/**
* Creates a filter that matches a notification if its
* {@link Notification#getNotifier() notifier}'s {@link EObject#eClass()
* class} equals the class passed to this filter's constructor or any
* subclasses thereof.
*/
EventFilter createClassFilterIncludingSubclasses(EClass clazz);
/**
* Creates a filter that matches an event's
* {@link Notification#getOldValue()} {@link EObject#eClass() class} against
* <code>clazz</code>. An exact match, not considering any inheritance
* relations, is required. If the {@link Notification#getOldValue() new
* value} is a collection, e.g., because several elements were removed from
* a many-feature at once, this filter matches if at least one of the
* elements' class is matched.
* <p>
*
* When several such filters are combined in an {@link AndFilter}, the
* {@link AndFilter} matches if all of its operand filters match. This does
* not require the individual {@link OldValueClassFilter}s to match based on
* the same element in case the old value happens to be a collection. For
* example, assume there are two classes <code>X</code> and <code>Y</code>.
* Assume there is an {@link AndFilter} with two {@link OldValueClassFilter}s
* inside, one matching <code>X</code>, the other matching <code>Y</code>.
* If there are two elements in the old value collection of the
* {@link Notification}, one of type <code>X</code> and the other of type
* <code>Y</code>, the first {@link OldValueClassFilter} matches because of
* the <code>X</code> element, and the second {@link OldValueClassFilter}
* matches because of the <code>Y</code> element and hence the
* {@link AndFilter} matches. However, no single element in the old value
* collection fulfills both criteria.
*/
EventFilter createOldValueClassFilter(EClass clazz);
/**
* Creates an filter that matches an event's
* {@link Notification#getOldValue()} {@link EObject#eClass() class} against
* <code>clazz</code> and all subclasses thereof. If the new value is a
* collection then this filter matches if at least one of the collection's
* elements is matched.
* <p>
*
* When several such filters are combined in an {@link AndFilter}, the
* {@link AndFilter} matches if all of its operand filters match. This does
* not require the individual {@link OldValueClassFilterIncludingSubclasses}
* s to match based on the same element in case the old value happens to be
* a collection. For example, assume there are two classes <code>X</code>
* and <code>Y</code> with a class <code>Z</code> that has both,
* <code>X</code> and <code>Y</code> as its superclasses (multiple
* inheritance). Assume there is an {@link AndFilter} with two
* {@link OldValueClassFilterIncludingSubclasses}s inside, one matching
* <code>X</code>, the other matching <code>Y</code>. If only a single
* element is the old value of a {@link Notification}, the {@link AndFilter}
* matches the notification if and only if the old value conforms to both,
* <code>X</code> and <code>Y</code>, for example if its type is
* <code>Z</code>. However, if there are two elements in the old value
* collection of the {@link Notification}, one of type <code>X</code> and
* the other of type <code>Y</code>, the first
* {@link OldValueClassFilterIncludingSubclasses} matches because of the
* <code>X</code> element, and the second
* {@link OldValueClassFilterIncludingSubclasses} matches because of the
* <code>Y</code> element and hence the {@link AndFilter} matches. However,
* no single element in the old value collection fulfills both criteria.
*/
EventFilter createOldValueClassFilterIncludingSubclasses(EClass clazz);
/**
* Creates a filter that matches an event's
* {@link Notification#getNewValue()} {@link EObject#eClass() class}. An
* exact match, not considering any inheritance relations, is required. If
* the {@link Notification#getNewValue() new value} is a collection, e.g.,
* because several elements were assigned to a many-feature at once, this
* filter matches if at least one of the elements' class is matched.
* <p>
*
* When several such filters are combined in an {@link AndFilter}, the
* {@link AndFilter} matches if all of its operand filters match. This does
* not require the individual {@link NewValueClassFilter}s to match based on
* the same element in case the new value happens to be a collection. For
* example, assume there are two classes <code>X</code> and <code>Y</code>.
* Assume there is an {@link AndFilter} with two {@link NewValueClassFilter}s
* inside, one matching <code>X</code>, the other matching <code>Y</code>.
* If there are two elements in the new value collection of the
* {@link Notification}, one of type <code>X</code> and the other of type
* <code>Y</code>, the first {@link NewValueClassFilter} matches because of
* the <code>X</code> element, and the second {@link NewValueClassFilter}
* matches because of the <code>Y</code> element and hence the
* {@link AndFilter} matches. However, no single element in the new value
* collection fulfills both criteria.
*/
EventFilter createNewValueClassFilter(EClass clazz);
/**
* Creates a filter that matches an event's
* {@link Notification#getNewValue()} {@link EObject#eClass() class} to
* <code>clazz</code> and all subclasses thereof. If the new value is a
* collection then this filter matches if at least one of the collection's
* elements is matched.
* <p>
*
* When several such filters are combined in an {@link AndFilter}, the
* {@link AndFilter} matches if all of its operand filters match. This does
* not require the individual {@link NewValueClassFilterIncludingSubclasses}
* s to match based on the same element in case the new value happens to be
* a collection. For example, assume there are two classes <code>X</code>
* and <code>Y</code> with a class <code>Z</code> that has both,
* <code>X</code> and <code>Y</code> as its superclasses (multiple
* inheritance). Assume there is an {@link AndFilter} with two
* {@link NewValueClassFilterIncludingSubclasses}s inside, one matching
* <code>X</code>, the other matching <code>Y</code>. If only a single
* element is the new value of a {@link Notification}, the {@link AndFilter}
* matches the notification if and only if the new value conforms to both,
* <code>X</code> and <code>Y</code>, for example if its type is
* <code>Z</code>. However, if there are two elements in the new value
* collection of the {@link Notification}, one of type <code>X</code> and
* the other of type <code>Y</code>, the first
* {@link NewValueClassFilterIncludingSubclasses} matches because of the
* <code>X</code> element, and the second
* {@link NewValueClassFilterIncludingSubclasses} matches because of the
* <code>Y</code> element and hence the {@link AndFilter} matches. However,
* no single element in the new value collection fulfills both criteria.
*/
EventFilter createNewValueClassFilterIncludingSubclasses(EClass clazz);
/**
* Constructs an {@link #createAndFilterFor(EventFilter...) AndFilter}
* combining a {@link #createClassFilter(EClass) ClassFilter} for
* <code>eClass</code> and a
* {@link #createStructuralFeatureFilter(EStructuralFeature) StructuralFeatureFilter}
* for <code>referredProperty</code>.
*/
EventFilter createFilterForEReference(EClass eClass,
EReference referredProperty);
/**
* Constructs an {@link #createAndFilterFor(EventFilter...) AndFilter}
* combining a {@link #createClassFilter(EClass) ClassFilter} for
* <code>eClass</code> and an
* {@link #createStructuralFeatureFilter(EStructuralFeature) StructuralFeatureFilter}
* for <code>referredProperty</code>.
*/
EventFilter createFilterForEAttribute(EClass eClass,
EAttribute referredProperty);
/**
* Creates an event filter that listens for events which indicate that an
* element of type <code>cls</code> has been added to the event manager's
* {@link ResourceSet}, either by directly assigning it to the immediate
* {@link Resource#getContents() contents} of a resource owned by the
* {@link ResourceSet}, or by assigning it to the containment reference of
* an element that is already part of the {@link ResourceSet}, or by adding
* a parent in the containment hierarchy to the {@link ResourceSet}.
*/
EventFilter createFilterForElementInsertion(EClass cls);
/**
* Creates a filter tree, which will match if the given class get inserted
* or deleted by an event
*
* @param cls
* class to listen for
* @return the new filter tree
*/
EventFilter createFilterForElementInsertionOrDeletion(EClass cls);
/**
* Shortcut, to create an {@link OrFilter} for incoming {@link EventFilter}s
*
* @param eventFilters
* filter to combine with an OR
* @return the created {@link OrFilter}
*/
EventFilter createOrFilterFor(EventFilter... eventFilters);
/**
* Creates an {@link AndFilter} for incoming {@link EventFilter}s. The
* resulting filter matches a {@link Notification} if and only if the
* {@link Notification} is matched by all <code>eventFilters</code>.
*
* @param eventFilters
* filter to combine with an <code>and</code>
* @return the created {@link AndFilter}
*/
EventFilter createAndFilterFor(EventFilter... eventFilters);
/**
* If <code>event</code> indicates the setting/adding/removal of/to/from a
* containment reference, then it is expanded into a collection of event
* notifications that document the creation or, respectively, dismantling of
* the entire containment hierarchy.
* <p>
*
* In any case, <code>event</code> is part of the collection returned.
*/
Collection<Notification> createNotificationForComposites(Notification event);
/**
* Ensures that weakly-referenced structures are expunged so that particularly all
* cleanup threads will terminate.
*/
void dispose();
} // EventManagerFactory