blob: c3296afb955c9ffd6bb0e7c53cdcc21ae78973c7 [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.filters;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
/**
* Matches an event's {@link Notification#getOldValue()} to an {@link EObject#eClass()}
* and all subclasses of this {@link EClass}. 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.
*
* @author Philipp Berger, Axel Uhl
*
*/
public class OldValueClassFilterIncludingSubclasses extends ClassFilterIncludingSubclasses {
public OldValueClassFilterIncludingSubclasses(EClass clazz, boolean isNegated) {
super(clazz, isNegated);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OldValueClassFilterIncludingSubclasses other = (OldValueClassFilterIncludingSubclasses) obj;
return super.equals(other);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return 43 * super.hashCode();
}
public boolean matchesFor(Notification event) {
if (event.getOldValue() == null) {
return false;
}
if (event.getOldValue() instanceof EObject) {
return matches(((EObject) event.getOldValue()).eClass());
}
if (event.getOldValue() instanceof EList<?>) {
for (Object o : (EList<?>) event.getOldValue()) {
if (o instanceof EObject && matches(((EObject) o).eClass())) {
return true;
}
}
return false;
}
return false;
}
@Override
public String toString() {
if (getWantedClass() != null)
return (isNegated()?"negated ":"") + "old value filter incl subs for old " + getWantedClass().toString();
return (isNegated()?"negated ":"") + "old value filter incl subs for undefined old";
}
@Override
public OldValueClassFilterIncludingSubclasses clone() {
return new OldValueClassFilterIncludingSubclasses(getWantedClass(), isNegated());
}
} // OldValueClassFilterImpl