@Override
 protected ENotificationImpl lostMatchIteration(IPatternMatch signature) {
   InternalEObject source = getSourceValue(signature);
   Integer delta = (Integer) getTargetValue(signature);
   if (delta == null && countOnly) {
     delta = -1;
   }
   Integer value = counterMemory.get(source);
   if (value == null) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error(
             "[IncqueryFeatureHandler] Space-time continuum breached (should never happen): decreasing a counter with no previous value");
   } else if (value >= delta) {
     int tempMemory = value - delta;
     int oldValue = value;
     counterMemory.put(source, tempMemory);
     return new ENotificationImpl(source, Notification.SET, getFeature(), oldValue, tempMemory);
   } else {
     IncQueryLoggingUtil.getLogger(getClass())
         .error(
             String.format(
                 "[IncqueryFeatureHandler] Exception during update: The counter of %s for feature %s cannot go below zero!",
                 source, getFeature()));
   }
   return null;
 }
 protected void initialize(
     final IncQueryMatcher<IPatternMatch> matcher,
     String sourceParamName,
     String targetParamName) {
   if (initialized) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error("[QueryBasedFeature] Feature already initialized!");
     return;
   }
   initialized = true;
   this.matcher = matcher;
   this.sourceParamName = sourceParamName;
   this.targetParamName = targetParamName;
   if (matcher.getPositionOfParameter(sourceParamName) == null) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error("[QueryBasedFeature] Source parameter " + sourceParamName + " not found!");
   }
   if (targetParamName != null && matcher.getPositionOfParameter(targetParamName) == null) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error("[QueryBasedFeature] Target parameter " + targetParamName + " not found!");
   }
   if ((targetParamName == null) != (getKind() == QueryBasedFeatureKind.COUNTER)) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error(
             "[QueryBasedFeature] Invalid configuration (no targetParamName needed for Counter)!");
   }
   // IPatternMatch partialMatch = matcher.newEmptyMatch();
   // partialMatch.set(sourceParamName, source);
   this.dm = matcher.newDeltaMonitor(true);
   engineLifecycleListener = new EngineLifecycleListener();
   listener = new ModelUpdateListener();
 }
 /**
  * @param feature
  * @param kind
  * @param keepCache
  */
 protected SumQueryBasedFeature(EStructuralFeature feature, QueryBasedFeatureKind kind) {
   super(feature, false);
   if (!(feature instanceof EAttribute)) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error(
             "[IncqueryFeatureHandler] Invalid configuration (Aggregate can be used only with EAttribute)!");
   }
   this.countOnly = QueryBasedFeatureKind.COUNTER.equals(kind);
 }
 @SuppressWarnings("unchecked")
 @Override
 public void engineWiped() {
   String patternName = matcher.getPatternName();
   try {
     matcher =
         (IncQueryMatcher<IPatternMatch>)
             QuerySpecificationRegistry.getQuerySpecification(patternName)
                 .getMatcher(engineForMatcher());
   } catch (IncQueryException e) {
     IncQueryLoggingUtil.getLogger(getClass())
         .error("[QueryBasedFeature] Exception during wipe callback: " + e.getMessage(), e);
   }
   dm = matcher.newDeltaMonitor(false);
 }
 @Override
 protected ENotificationImpl newMatchIteration(IPatternMatch signature) {
   InternalEObject source = getSourceValue(signature);
   Integer oldValue = getIntValue(source);
   Integer delta = (Integer) getTargetValue(signature);
   if (delta == null && countOnly) {
     delta = 1;
   }
   if (delta != null && oldValue <= Integer.MAX_VALUE - delta) {
     int tempMemory = oldValue + delta;
     counterMemory.put(source, tempMemory);
     return new ENotificationImpl(
         source, Notification.SET, getFeature(), getIntValue(source), tempMemory);
   } else {
     IncQueryLoggingUtil.getLogger(getClass())
         .error(
             String.format(
                 "[IncqueryFeatureHandler] Exception during update: The counter of %s for feature %s reached the maximum value of int!",
                 source, getFeature()));
   }
   return null;
 }
/**
 * Generated pattern matcher API of the org.eclipse.incquery.testing.queries.RecordRoleValue
 * pattern, providing pattern-specific query methods.
 *
 * <p>Use the pattern matcher on a given model via {@link #on(IncQueryEngine)}, e.g. in conjunction
 * with {@link IncQueryEngine#on(Notifier)}.
 *
 * <p>Matches of the pattern will be represented as {@link RecordRoleValueMatch}.
 *
 * <p>Original source: <code><pre>
 * pattern NotFoundMatchRecord(
 * 	ActualSet : MatchSetRecord,
 * 	ExpectedSet : MatchSetRecord,
 * 	Record : MatchRecord
 * ) = {
 * 	MatchSetRecord.matches(ExpectedSet, Record);
 * 	neg find CorrespondingRecordInMatchSetRecord(Record, CorrespodingRecord, ActualSet);
 * }
 *
 * {@literal @}QueryExplorer(display = false)
 * {@literal @}QueryBasedFeature(feature = "role")
 * pattern RecordRoleValue(
 * 	Record : MatchRecord,
 * 	Role
 * ) = {
 * 	MatchSetRecord.filter(_MS,Record);
 * 	RecordRole::Filter == Role;
 * } or {
 * 	MatchSetRecord.matches(_MS,Record);
 * 	RecordRole::Match == Role;
 * }
 * </pre></code>
 *
 * @see RecordRoleValueMatch
 * @see RecordRoleValueProcessor
 * @see RecordRoleValueQuerySpecification
 */
@SuppressWarnings("all")
public class RecordRoleValueMatcher extends BaseMatcher<RecordRoleValueMatch> {
  /**
   * @return the singleton instance of the query specification of this pattern
   * @throws IncQueryException if the pattern definition could not be loaded
   */
  public static IQuerySpecification<RecordRoleValueMatcher> querySpecification()
      throws IncQueryException {
    return RecordRoleValueQuerySpecification.instance();
  }

  /**
   * Initializes the pattern matcher within an existing EMF-IncQuery engine. If the pattern matcher
   * is already constructed in the engine, only a light-weight reference is returned. The match set
   * will be incrementally refreshed upon updates.
   *
   * @param engine the existing EMF-IncQuery engine in which this matcher will be created.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   */
  public static RecordRoleValueMatcher on(final IncQueryEngine engine) throws IncQueryException {
    // check if matcher already exists
    RecordRoleValueMatcher matcher = engine.getExistingMatcher(querySpecification());
    if (matcher == null) {
      matcher = new RecordRoleValueMatcher(engine);
      // do not have to "put" it into engine.matchers, reportMatcherInitialized() will take care of
      // it
    }
    return matcher;
  }

  private static final int POSITION_RECORD = 0;

  private static final int POSITION_ROLE = 1;

  private static final Logger LOGGER = IncQueryLoggingUtil.getLogger(RecordRoleValueMatcher.class);

  /**
   * Initializes the pattern matcher over a given EMF model root (recommended: Resource or
   * ResourceSet). If a pattern matcher is already constructed with the same root, only a
   * light-weight reference is returned. The scope of pattern matching will be the given EMF model
   * root and below (see FAQ for more precise definition). The match set will be incrementally
   * refreshed upon updates from this scope.
   *
   * <p>The matcher will be created within the managed {@link IncQueryEngine} belonging to the EMF
   * model root, so multiple matchers will reuse the same engine and benefit from increased
   * performance and reduced memory footprint.
   *
   * @param emfRoot the root of the EMF containment hierarchy where the pattern matcher will
   *     operate. Recommended: Resource or ResourceSet.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   * @deprecated use {@link #on(IncQueryEngine)} instead, e.g. in conjunction with {@link
   *     IncQueryEngine#on(Notifier)}
   */
  @Deprecated
  public RecordRoleValueMatcher(final Notifier emfRoot) throws IncQueryException {
    this(IncQueryEngine.on(emfRoot));
  }

  /**
   * Initializes the pattern matcher within an existing EMF-IncQuery engine. If the pattern matcher
   * is already constructed in the engine, only a light-weight reference is returned. The match set
   * will be incrementally refreshed upon updates.
   *
   * @param engine the existing EMF-IncQuery engine in which this matcher will be created.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   * @deprecated use {@link #on(IncQueryEngine)} instead
   */
  @Deprecated
  public RecordRoleValueMatcher(final IncQueryEngine engine) throws IncQueryException {
    super(engine, querySpecification());
  }

  /**
   * Returns the set of all matches of the pattern that conform to the given fixed values of some
   * parameters.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return matches represented as a RecordRoleValueMatch object.
   */
  public Collection<RecordRoleValueMatch> getAllMatches(
      final MatchRecord pRecord, final RecordRole pRole) {
    return rawGetAllMatches(new Object[] {pRecord, pRole});
  }

  /**
   * Returns an arbitrarily chosen match of the pattern that conforms to the given fixed values of
   * some parameters. Neither determinism nor randomness of selection is guaranteed.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return a match represented as a RecordRoleValueMatch object, or null if no match is found.
   */
  public RecordRoleValueMatch getOneArbitraryMatch(
      final MatchRecord pRecord, final RecordRole pRole) {
    return rawGetOneArbitraryMatch(new Object[] {pRecord, pRole});
  }

  /**
   * Indicates whether the given combination of specified pattern parameters constitute a valid
   * pattern match, under any possible substitution of the unspecified parameters (if any).
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return true if the input is a valid (partial) match of the pattern.
   */
  public boolean hasMatch(final MatchRecord pRecord, final RecordRole pRole) {
    return rawHasMatch(new Object[] {pRecord, pRole});
  }

  /**
   * Returns the number of all matches of the pattern that conform to the given fixed values of some
   * parameters.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return the number of pattern matches found.
   */
  public int countMatches(final MatchRecord pRecord, final RecordRole pRole) {
    return rawCountMatches(new Object[] {pRecord, pRole});
  }

  /**
   * Executes the given processor on each match of the pattern that conforms to the given fixed
   * values of some parameters.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @param processor the action that will process each pattern match.
   */
  public void forEachMatch(
      final MatchRecord pRecord,
      final RecordRole pRole,
      final IMatchProcessor<? super RecordRoleValueMatch> processor) {
    rawForEachMatch(new Object[] {pRecord, pRole}, processor);
  }

  /**
   * Executes the given processor on an arbitrarily chosen match of the pattern that conforms to the
   * given fixed values of some parameters. Neither determinism nor randomness of selection is
   * guaranteed.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @param processor the action that will process the selected match.
   * @return true if the pattern has at least one match with the given parameter values, false if
   *     the processor was not invoked
   */
  public boolean forOneArbitraryMatch(
      final MatchRecord pRecord,
      final RecordRole pRole,
      final IMatchProcessor<? super RecordRoleValueMatch> processor) {
    return rawForOneArbitraryMatch(new Object[] {pRecord, pRole}, processor);
  }

  /**
   * Registers a new filtered delta monitor on this pattern matcher. The DeltaMonitor can be used to
   * track changes (delta) in the set of filtered pattern matches from now on, considering those
   * matches only that conform to the given fixed values of some parameters. It can also be reset to
   * track changes from a later point in time, and changes can even be acknowledged on an individual
   * basis. See {@link DeltaMonitor} for details.
   *
   * @param fillAtStart if true, all current matches are reported as new match events; if false, the
   *     delta monitor starts empty.
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return the delta monitor.
   * @deprecated use the IncQuery Databinding API (IncQueryObservables) instead.
   */
  @Deprecated
  public DeltaMonitor<RecordRoleValueMatch> newFilteredDeltaMonitor(
      final boolean fillAtStart, final MatchRecord pRecord, final RecordRole pRole) {
    return rawNewFilteredDeltaMonitor(fillAtStart, new Object[] {pRecord, pRole});
  }

  /**
   * Returns a new (partial) Match object for the matcher. This can be used e.g. to call the matcher
   * with a partial match.
   *
   * <p>The returned match will be immutable. Use {@link #newEmptyMatch()} to obtain a mutable match
   * object.
   *
   * @param pRecord the fixed value of pattern parameter Record, or null if not bound.
   * @param pRole the fixed value of pattern parameter Role, or null if not bound.
   * @return the (partial) match object.
   */
  public RecordRoleValueMatch newMatch(final MatchRecord pRecord, final RecordRole pRole) {
    return new RecordRoleValueMatch.Immutable(pRecord, pRole);
  }

  /**
   * Retrieve the set of values that occur in matches for Record.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<MatchRecord> rawAccumulateAllValuesOfRecord(final Object[] parameters) {
    Set<MatchRecord> results = new HashSet<MatchRecord>();
    rawAccumulateAllValues(POSITION_RECORD, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for Record.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<MatchRecord> getAllValuesOfRecord() {
    return rawAccumulateAllValuesOfRecord(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for Record.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<MatchRecord> getAllValuesOfRecord(final RecordRoleValueMatch partialMatch) {
    return rawAccumulateAllValuesOfRecord(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for Record.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<MatchRecord> getAllValuesOfRecord(final RecordRole pRole) {
    return rawAccumulateAllValuesOfRecord(new Object[] {null, pRole});
  }

  /**
   * Retrieve the set of values that occur in matches for Role.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<RecordRole> rawAccumulateAllValuesOfRole(final Object[] parameters) {
    Set<RecordRole> results = new HashSet<RecordRole>();
    rawAccumulateAllValues(POSITION_ROLE, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for Role.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<RecordRole> getAllValuesOfRole() {
    return rawAccumulateAllValuesOfRole(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for Role.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<RecordRole> getAllValuesOfRole(final RecordRoleValueMatch partialMatch) {
    return rawAccumulateAllValuesOfRole(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for Role.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<RecordRole> getAllValuesOfRole(final MatchRecord pRecord) {
    return rawAccumulateAllValuesOfRole(new Object[] {pRecord, null});
  }

  @Override
  protected RecordRoleValueMatch tupleToMatch(final Tuple t) {
    try {
      return new RecordRoleValueMatch.Immutable(
          (org.eclipse.incquery.snapshot.EIQSnapshot.MatchRecord) t.get(POSITION_RECORD),
          (org.eclipse.incquery.snapshot.EIQSnapshot.RecordRole) t.get(POSITION_ROLE));
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in tuple not properly typed!", e);
      return null;
    }
  }

  @Override
  protected RecordRoleValueMatch arrayToMatch(final Object[] match) {
    try {
      return new RecordRoleValueMatch.Immutable(
          (org.eclipse.incquery.snapshot.EIQSnapshot.MatchRecord) match[POSITION_RECORD],
          (org.eclipse.incquery.snapshot.EIQSnapshot.RecordRole) match[POSITION_ROLE]);
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in array not properly typed!", e);
      return null;
    }
  }

  @Override
  protected RecordRoleValueMatch arrayToMatchMutable(final Object[] match) {
    try {
      return new RecordRoleValueMatch.Mutable(
          (org.eclipse.incquery.snapshot.EIQSnapshot.MatchRecord) match[POSITION_RECORD],
          (org.eclipse.incquery.snapshot.EIQSnapshot.RecordRole) match[POSITION_ROLE]);
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in array not properly typed!", e);
      return null;
    }
  }
}
/**
 * Generated pattern matcher API of the
 * hu.bme.mit.trainbenchmark.ttc.benchmark.emfincquery.routeSensor pattern, providing
 * pattern-specific query methods.
 *
 * <p>Use the pattern matcher on a given model via {@link #on(IncQueryEngine)}, e.g. in conjunction
 * with {@link IncQueryEngine#on(Notifier)}.
 *
 * <p>Matches of the pattern will be represented as {@link RouteSensorMatch}.
 *
 * <p>Original source: <code><pre>
 * pattern routeSensor(route, sensor, switchPosition, sw)
 * {
 * 	Route.follows(route, switchPosition);
 * 	SwitchPosition.^switch(switchPosition, sw);
 * 	TrackElement.sensor(sw, sensor);
 * 	neg find definedBy(route, sensor);
 * }
 * </pre></code>
 *
 * @see RouteSensorMatch
 * @see RouteSensorProcessor
 * @see RouteSensorQuerySpecification
 */
@SuppressWarnings("all")
public class RouteSensorMatcher extends BaseMatcher<RouteSensorMatch> {
  /**
   * Initializes the pattern matcher within an existing EMF-IncQuery engine. If the pattern matcher
   * is already constructed in the engine, only a light-weight reference is returned. The match set
   * will be incrementally refreshed upon updates.
   *
   * @param engine the existing EMF-IncQuery engine in which this matcher will be created.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   */
  public static RouteSensorMatcher on(final IncQueryEngine engine) throws IncQueryException {
    // check if matcher already exists
    RouteSensorMatcher matcher = engine.getExistingMatcher(querySpecification());
    if (matcher == null) {
      matcher = new RouteSensorMatcher(engine);
      // do not have to "put" it into engine.matchers, reportMatcherInitialized() will take care of
      // it
    }
    return matcher;
  }

  private static final int POSITION_ROUTE = 0;

  private static final int POSITION_SENSOR = 1;

  private static final int POSITION_SWITCHPOSITION = 2;

  private static final int POSITION_SW = 3;

  private static final Logger LOGGER = IncQueryLoggingUtil.getLogger(RouteSensorMatcher.class);

  /**
   * Initializes the pattern matcher over a given EMF model root (recommended: Resource or
   * ResourceSet). If a pattern matcher is already constructed with the same root, only a
   * light-weight reference is returned. The scope of pattern matching will be the given EMF model
   * root and below (see FAQ for more precise definition). The match set will be incrementally
   * refreshed upon updates from this scope.
   *
   * <p>The matcher will be created within the managed {@link IncQueryEngine} belonging to the EMF
   * model root, so multiple matchers will reuse the same engine and benefit from increased
   * performance and reduced memory footprint.
   *
   * @param emfRoot the root of the EMF containment hierarchy where the pattern matcher will
   *     operate. Recommended: Resource or ResourceSet.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   * @deprecated use {@link #on(IncQueryEngine)} instead, e.g. in conjunction with {@link
   *     IncQueryEngine#on(Notifier)}
   */
  @Deprecated
  public RouteSensorMatcher(final Notifier emfRoot) throws IncQueryException {
    this(IncQueryEngine.on(emfRoot));
  }

  /**
   * Initializes the pattern matcher within an existing EMF-IncQuery engine. If the pattern matcher
   * is already constructed in the engine, only a light-weight reference is returned. The match set
   * will be incrementally refreshed upon updates.
   *
   * @param engine the existing EMF-IncQuery engine in which this matcher will be created.
   * @throws IncQueryException if an error occurs during pattern matcher creation
   * @deprecated use {@link #on(IncQueryEngine)} instead
   */
  @Deprecated
  public RouteSensorMatcher(final IncQueryEngine engine) throws IncQueryException {
    super(engine, querySpecification());
  }

  /**
   * Returns the set of all matches of the pattern that conform to the given fixed values of some
   * parameters.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @return matches represented as a RouteSensorMatch object.
   */
  public Collection<RouteSensorMatch> getAllMatches(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw) {
    return rawGetAllMatches(new Object[] {pRoute, pSensor, pSwitchPosition, pSw});
  }

  /**
   * Returns an arbitrarily chosen match of the pattern that conforms to the given fixed values of
   * some parameters. Neither determinism nor randomness of selection is guaranteed.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @return a match represented as a RouteSensorMatch object, or null if no match is found.
   */
  public RouteSensorMatch getOneArbitraryMatch(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw) {
    return rawGetOneArbitraryMatch(new Object[] {pRoute, pSensor, pSwitchPosition, pSw});
  }

  /**
   * Indicates whether the given combination of specified pattern parameters constitute a valid
   * pattern match, under any possible substitution of the unspecified parameters (if any).
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @return true if the input is a valid (partial) match of the pattern.
   */
  public boolean hasMatch(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw) {
    return rawHasMatch(new Object[] {pRoute, pSensor, pSwitchPosition, pSw});
  }

  /**
   * Returns the number of all matches of the pattern that conform to the given fixed values of some
   * parameters.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @return the number of pattern matches found.
   */
  public int countMatches(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw) {
    return rawCountMatches(new Object[] {pRoute, pSensor, pSwitchPosition, pSw});
  }

  /**
   * Executes the given processor on each match of the pattern that conforms to the given fixed
   * values of some parameters.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @param processor the action that will process each pattern match.
   */
  public void forEachMatch(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw,
      final IMatchProcessor<? super RouteSensorMatch> processor) {
    rawForEachMatch(new Object[] {pRoute, pSensor, pSwitchPosition, pSw}, processor);
  }

  /**
   * Executes the given processor on an arbitrarily chosen match of the pattern that conforms to the
   * given fixed values of some parameters. Neither determinism nor randomness of selection is
   * guaranteed.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @param processor the action that will process the selected match.
   * @return true if the pattern has at least one match with the given parameter values, false if
   *     the processor was not invoked
   */
  public boolean forOneArbitraryMatch(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw,
      final IMatchProcessor<? super RouteSensorMatch> processor) {
    return rawForOneArbitraryMatch(new Object[] {pRoute, pSensor, pSwitchPosition, pSw}, processor);
  }

  /**
   * Returns a new (partial) match. This can be used e.g. to call the matcher with a partial match.
   *
   * <p>The returned match will be immutable. Use {@link #newEmptyMatch()} to obtain a mutable match
   * object.
   *
   * @param pRoute the fixed value of pattern parameter route, or null if not bound.
   * @param pSensor the fixed value of pattern parameter sensor, or null if not bound.
   * @param pSwitchPosition the fixed value of pattern parameter switchPosition, or null if not
   *     bound.
   * @param pSw the fixed value of pattern parameter sw, or null if not bound.
   * @return the (partial) match object.
   */
  public RouteSensorMatch newMatch(
      final Route pRoute,
      final Sensor pSensor,
      final SwitchPosition pSwitchPosition,
      final Switch pSw) {
    return RouteSensorMatch.newMatch(pRoute, pSensor, pSwitchPosition, pSw);
  }

  /**
   * Retrieve the set of values that occur in matches for route.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<Route> rawAccumulateAllValuesOfroute(final Object[] parameters) {
    Set<Route> results = new HashSet<Route>();
    rawAccumulateAllValues(POSITION_ROUTE, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for route.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Route> getAllValuesOfroute() {
    return rawAccumulateAllValuesOfroute(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for route.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Route> getAllValuesOfroute(final RouteSensorMatch partialMatch) {
    return rawAccumulateAllValuesOfroute(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for route.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Route> getAllValuesOfroute(
      final Sensor pSensor, final SwitchPosition pSwitchPosition, final Switch pSw) {
    return rawAccumulateAllValuesOfroute(new Object[] {null, pSensor, pSwitchPosition, pSw});
  }

  /**
   * Retrieve the set of values that occur in matches for sensor.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<Sensor> rawAccumulateAllValuesOfsensor(final Object[] parameters) {
    Set<Sensor> results = new HashSet<Sensor>();
    rawAccumulateAllValues(POSITION_SENSOR, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for sensor.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Sensor> getAllValuesOfsensor() {
    return rawAccumulateAllValuesOfsensor(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for sensor.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Sensor> getAllValuesOfsensor(final RouteSensorMatch partialMatch) {
    return rawAccumulateAllValuesOfsensor(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for sensor.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Sensor> getAllValuesOfsensor(
      final Route pRoute, final SwitchPosition pSwitchPosition, final Switch pSw) {
    return rawAccumulateAllValuesOfsensor(new Object[] {pRoute, null, pSwitchPosition, pSw});
  }

  /**
   * Retrieve the set of values that occur in matches for switchPosition.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<SwitchPosition> rawAccumulateAllValuesOfswitchPosition(final Object[] parameters) {
    Set<SwitchPosition> results = new HashSet<SwitchPosition>();
    rawAccumulateAllValues(POSITION_SWITCHPOSITION, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for switchPosition.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<SwitchPosition> getAllValuesOfswitchPosition() {
    return rawAccumulateAllValuesOfswitchPosition(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for switchPosition.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<SwitchPosition> getAllValuesOfswitchPosition(final RouteSensorMatch partialMatch) {
    return rawAccumulateAllValuesOfswitchPosition(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for switchPosition.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<SwitchPosition> getAllValuesOfswitchPosition(
      final Route pRoute, final Sensor pSensor, final Switch pSw) {
    return rawAccumulateAllValuesOfswitchPosition(new Object[] {pRoute, pSensor, null, pSw});
  }

  /**
   * Retrieve the set of values that occur in matches for sw.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  protected Set<Switch> rawAccumulateAllValuesOfsw(final Object[] parameters) {
    Set<Switch> results = new HashSet<Switch>();
    rawAccumulateAllValues(POSITION_SW, parameters, results);
    return results;
  }

  /**
   * Retrieve the set of values that occur in matches for sw.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Switch> getAllValuesOfsw() {
    return rawAccumulateAllValuesOfsw(emptyArray());
  }

  /**
   * Retrieve the set of values that occur in matches for sw.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Switch> getAllValuesOfsw(final RouteSensorMatch partialMatch) {
    return rawAccumulateAllValuesOfsw(partialMatch.toArray());
  }

  /**
   * Retrieve the set of values that occur in matches for sw.
   *
   * @return the Set of all values, null if no parameter with the given name exists, empty set if
   *     there are no matches
   */
  public Set<Switch> getAllValuesOfsw(
      final Route pRoute, final Sensor pSensor, final SwitchPosition pSwitchPosition) {
    return rawAccumulateAllValuesOfsw(new Object[] {pRoute, pSensor, pSwitchPosition, null});
  }

  @Override
  protected RouteSensorMatch tupleToMatch(final Tuple t) {
    try {
      return RouteSensorMatch.newMatch(
          (hu.bme.mit.trainbenchmark.ttc.railway.Route) t.get(POSITION_ROUTE),
          (hu.bme.mit.trainbenchmark.ttc.railway.Sensor) t.get(POSITION_SENSOR),
          (hu.bme.mit.trainbenchmark.ttc.railway.SwitchPosition) t.get(POSITION_SWITCHPOSITION),
          (hu.bme.mit.trainbenchmark.ttc.railway.Switch) t.get(POSITION_SW));
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in tuple not properly typed!", e);
      return null;
    }
  }

  @Override
  protected RouteSensorMatch arrayToMatch(final Object[] match) {
    try {
      return RouteSensorMatch.newMatch(
          (hu.bme.mit.trainbenchmark.ttc.railway.Route) match[POSITION_ROUTE],
          (hu.bme.mit.trainbenchmark.ttc.railway.Sensor) match[POSITION_SENSOR],
          (hu.bme.mit.trainbenchmark.ttc.railway.SwitchPosition) match[POSITION_SWITCHPOSITION],
          (hu.bme.mit.trainbenchmark.ttc.railway.Switch) match[POSITION_SW]);
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in array not properly typed!", e);
      return null;
    }
  }

  @Override
  protected RouteSensorMatch arrayToMatchMutable(final Object[] match) {
    try {
      return RouteSensorMatch.newMutableMatch(
          (hu.bme.mit.trainbenchmark.ttc.railway.Route) match[POSITION_ROUTE],
          (hu.bme.mit.trainbenchmark.ttc.railway.Sensor) match[POSITION_SENSOR],
          (hu.bme.mit.trainbenchmark.ttc.railway.SwitchPosition) match[POSITION_SWITCHPOSITION],
          (hu.bme.mit.trainbenchmark.ttc.railway.Switch) match[POSITION_SW]);
    } catch (ClassCastException e) {
      LOGGER.error("Element(s) in array not properly typed!", e);
      return null;
    }
  }

  /**
   * @return the singleton instance of the query specification of this pattern
   * @throws IncQueryException if the pattern definition could not be loaded
   */
  public static IQuerySpecification<RouteSensorMatcher> querySpecification()
      throws IncQueryException {
    return RouteSensorQuerySpecification.instance();
  }
}