# Defining Custom Notifications

Live validation determines the constraints to evaluate by the events that they declare as triggers. By default, support is provided for the standard event types defined by EMF: SET, ADD, REMOVE, etc. However, sometimes these are too fine-grained, and accurately specifying the triggering events for different features could be difficult, verbose, or even impossible.

> [as SVG]

Enter the notification generator. This facility allows clients to define custom event types that are more abstract. For example, a constraint might be triggered on additions or removals in any containment feature. So, an application can register a custom "ContainmentChange" event type on the org.eclipse.emf.validation.eventTypes extension point.

       <extension
             point="org.eclipse.emf.validation.eventTypes">

          <eventType
                name="ContainmentChange"
                featureSpecific="false"
                notificationGenerator="org.eclipse.example.ContainmentNotificationGenerator">
          </eventType>
      </extension>

The name attribute specifies the non-localizable name that clients will use in their live constraint declarations as a trigger. If the event type is feature-specific, then clients can also specify features to match along with the event type. If the event type is not feature-specific, then it is considered to apply to the notifier element as a whole.

## The Notification Generator

The other key component of the event type declaration is the notificationGenerator. This indicates a class implementing the INotificationGenerator that will be called upon during live validation to analyze the list of raw Notifications and compute the custom notifications, if any. Custom events created in this way are not fed recursively through the generation process; only the basic notifications from the EMF content are processed in this way.

Custom event types are created implicitly by accessing their static instances in the EMFEventType. The framework automatically assigns them unique event type IDs that are different from those pre-defined by EMF.

        public Collection generateNotifications(Collection notifications) {
            Collection result = new ArrayList();

            for (Iterator iter = notifications.iterator(); iter.hasNext(); ) {
                Notification notification = (Notification) iter.next();
                Object feature = notification.getFeature();

                if ((feature instanceof EReference) && ((EReference) feature).isContainment()) {
                    Collection children = Collections.EMPTY_SET;

                    switch (notification.getEventType()) {
                    case Notification.ADD:
                        child1 = Collections.singleton(notification.getNewValue());
                        break;
                    case Notification.REMOVE:
                        child1 = Collections.singleton(notification.getOldValue());
                        break;
                    case Notification.SET:
                    case Notification.UNSET:
                        children = new ArrayList(2);
                        children.add(notification.getNewValue());
                        children.add(notification.getOldValue());
                        break;
                    case Notification.ADD_MANY:
                        children = (Collection) notification.getNewValue();
                        break;
                    case Notification.ADD_REMOVE:
                        children = (Collection) notification.getOldValue();
                        break;
                    }

                    // create a ContainmentChange event from the child's perspective.
                    // The EMFEventType class guarantees unique event type codes
                    for (Iterator iter = children.iterator(); iter.hasNext();) {
                        result.add(new ENotificationImpl(
                            (InternalEObject) iter.next(),
                            EMFEventType.getInstance("ContainmentChange").toNotificationType(),
                            Notification.NO_FEATURE_ID, // non-feature-specific example
                            null, null));
                    }
                }
            }

            return result;
        }

Copyright (c) 2000, 2007 IBM Corporation and others. All Rights Reserved.