blob: 1685b7434d9a8aa82231462e159c301252e8a490 [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.framework;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.ocl.examples.eventmanager.filters.AndFilter;
import org.eclipse.ocl.examples.eventmanager.util.Statistics;
/**
* A Registration represents a set of events that a listener wants to receive. Due to the fact that one call to
* register..() on the EventRegistry interface can result in multiple registrations (due to the internal design),
* registrations can be pooled into a set (the {@link RegistrationSet}).
*
* @author Daniel Vocke (D044825), Axel Uhl (D043530)
*/
class Registration {
/**
* Registration objects are re-used to keep the tables in the event manager as small as possible and
* free of redundancy. Therefore, a registration can belong to multiple {@link RegistrationSet}s, each
* representing a listener.
*/
private Set<RegistrationSet> registrationSets;
/**
* A bit field where each bit is taken from the {@link RegistrationManagerTableBased#filterTypeToBitMask} values,
* representing a table with which this registration is registered. This number can be used as index into
* the registration sets stored in the filter tables.
*/
private final int bitSetForTablesRegisteredWith;
/**
* Stores the <code>AndFilter</code> for which this registration was created.
*/
private final AndFilter andFilter;
/**
* For each table, holds the number of times this registration must be
* matched for a {@link Notification} to pass. Assume, for example, a
* registration is created for an {@link AndFilter} that has two operands
* asking for two different criteria of the same sort, e.g., two different
* {@link EClass}es. (Such a filter would, e.g., be matched by an
* <code>ADD_MANY</code> notification whose new value collection holds at
* least one object of each class requested. In this case, the
* {@link Registration} must only be considered "matched" if two matches
* were produced for the objects delivered by the
* {@link TableForEventFilter#getAffectedObject(org.eclipse.emf.common.notify.Notification)}
* operation.<p>
*
* This array stores the numbers of matches required per table. It will hold 0
* for those tables where the registration is not registered, and at least 1
* for all tables where it is registered.
*/
private int[] requiredMatchesPerTable;
/**
* @param bitSetForTablesRegisteredWith
* a bit set indicating for which tables this listener is
* registered. This bit set corresponds with what
* {@link RegistrationManagerTableBased#getTablesForBitSet(int)}
* takes as an argument.
* @param andFilter
* when running in "debug mode" with the {@link Statistics}
* capturing turned on, the <code>andFilter</code> will be
* remembered (otherwise, a {@link Registration} doesn't know its
* filter, hence the filter can eventually get garbage-collected)
* and will be shown in the {@link #toString()} output.
* @param requiredMatchesPerTable
* the total number of tables that are managed by the
* {@link EventManagerTableBased} for which this is a
* registration
*/
Registration(int bitSetForTablesRegisteredWith, AndFilter andFilter, int[] requiredMatchesPerTable) {
this.bitSetForTablesRegisteredWith = bitSetForTablesRegisteredWith;
this.andFilter = andFilter;
registrationSets = new HashSet<RegistrationSet>();
this.requiredMatchesPerTable = requiredMatchesPerTable;
}
/**
* @param i
* number of the table (0-based, as in
* {@link RegistrationManagerTableBased}'s tables, for which to
* tell how many matches this registration requires from this table
*/
public int getMatchesRequiredForTable(int i) {
return requiredMatchesPerTable[i];
}
/**
* Can be used as index into registration arrays, such as those managed by
* {@link FilterTableEntry}.
*/
public int getBitSetForTablesRegisteredWith() {
return bitSetForTablesRegisteredWith;
}
/**
* When a call to register...() on the EventRegistry interface results in multiple Registrations, those Registrations will be
* pooled in a RegistrationSet. This can happen due to the internal design where "OR connected" filters are splitted into
* multiple Registrations.
*
* @return an unmodifiable collection of the RegistrationSets that pool all Registrations that were created during one
* registration call
*/
Set<RegistrationSet> getRegistrationSets() {
return Collections.unmodifiableSet(registrationSets);
}
/**
* Adds the registration to the {@link #registrationSets} collection. Note that this operation
* does not maintain any opposite reference in {@link RegistrationSet}.
*/
void addRegistrationSet(RegistrationSet registrationSet) {
registrationSets.add(registrationSet);
}
/**
* Removes <code>registationSet</code> from {@link #registrationSets} and returns <code>true</code> if that removed the last
* {@link RegistrationSet} of which this {@link Registration} was a part. Note, that <code>false</code> will be returned
* if {@link #registrationSets} was already empty when calling this method.
*/
boolean removeRegistrationSet(RegistrationSet registrationSet) {
boolean result = false;
if (registrationSets.remove(registrationSet)) {
result = registrationSets.size() == 0;
}
return result;
}
public String toString() {
return super.toString()+" bitSet "+bitSetForTablesRegisteredWith;
}
public AndFilter getAndFilter() {
return andFilter;
}
}