Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "VIATRA/Query/UserDocumentation/API/Advanced"

Line 1: Line 1:
 +
= Overview =
 +
TODO
 +
== Running example ==
 +
All the code examples and explanations will be given in the context of the [[EMFIncQuery/UserDocumentation/HeadlessExecution|Headless]] example.
 +
The up-to-date sample source code to this page is found in Git here: http://git.eclipse.org/c/incquery/org.eclipse.incquery.examples.git/tree/headless
 +
== Javadoc  ==
 +
The most up-to-date Javadocs for the EMF-IncQuery API can be found online at http://eclipse.org/incquery/javadoc/
 
= The IncQuery Generic API  =
 
= The IncQuery Generic API  =
 
 
The "generic" API differs from the generated one in two key aspects:  
 
The "generic" API differs from the generated one in two key aspects:  
 
 
*it can be used to apply queries and use other IncQuery features '''without''' generating code and loading the resulting bundles into the running configuration. In other words, you just need to supply the EMF-based in-memory representation (an instance of the Pattern class)  
 
*it can be used to apply queries and use other IncQuery features '''without''' generating code and loading the resulting bundles into the running configuration. In other words, you just need to supply the EMF-based in-memory representation (an instance of the Pattern class)  
 
*the generic API is not "type safe" in the sense that the Java types of your pattern variables is not known and needs to be handled dynamically (e.g. by instanceof - typecase combos).
 
*the generic API is not "type safe" in the sense that the Java types of your pattern variables is not known and needs to be handled dynamically (e.g. by instanceof - typecase combos).

Revision as of 11:20, 11 April 2013

Overview

TODO

Running example

All the code examples and explanations will be given in the context of the Headless example. The up-to-date sample source code to this page is found in Git here: http://git.eclipse.org/c/incquery/org.eclipse.incquery.examples.git/tree/headless

Javadoc

The most up-to-date Javadocs for the EMF-IncQuery API can be found online at http://eclipse.org/incquery/javadoc/

The IncQuery Generic API

The "generic" API differs from the generated one in two key aspects:

  • it can be used to apply queries and use other IncQuery features without generating code and loading the resulting bundles into the running configuration. In other words, you just need to supply the EMF-based in-memory representation (an instance of the Pattern class)
  • the generic API is not "type safe" in the sense that the Java types of your pattern variables is not known and needs to be handled dynamically (e.g. by instanceof - typecase combos).

Initializing matchers and accessing results

Sample code

With the Generic API:

public String executeGeneric(String modelPath, String patternFQN) {
 StringBuilder results = new StringBuilder();
 Resource resource = loadModel(modelPath);
 if (resource != null) {
  try {
   // get all matches of the pattern
   IncQueryMatcher matcher = MatcherFactoryRegistry.getMatcherFactory(patternFQN).getMatcher(resource);
   Collection<IPatternMatch> matches = matcher.getAllMatches();
   prettyPrintMatches(results, matches);
  } catch (IncQueryException e) {
   e.printStackTrace();
   results.append(e.getMessage());
  }
 } else {
  results.append("Resource not found");
 }
 return results.toString();
}

API interfaces

IPatternMatch

/**
 * Generic interface for a single match of a pattern. Each instance is a (partial) substitution of pattern parameters,
 * essentially a parameter to value mapping. Can also represent a partial match; unsubstituted parameters are assigned to null. Pattern matchers must never return
 * a partial match, but they accept partial matches as method parameters.
 */
public interface IPatternMatch extends Cloneable {
    /** @return the pattern for which this is a match. */
    public Pattern pattern();
    /** Identifies the name of the pattern for which this is a match. */
    public String patternName();
    /** Returns the list of symbolic parameter names. */
    public String[] parameterNames();
    /** Returns the value of the parameter with the given name, or null if name is invalid. */
    public Object get(String parameterName);
    /** Returns the value of the parameter at the given position, or null if position is invalid. */
    public Object get(int position);
    /** Sets the parameter with the given name to the given value.     */
    public boolean set(String parameterName, Object newValue);
     /** Sets the parameter at the given position to the given value.     */
    public boolean set(int position, Object newValue);
    /** Returns whether the match object can be further modified after its creation. Setters work only if the match is mutable.      */
    public boolean isMutable();
    /** Converts the match to an array representation, with each pattern parameter at their respective position.      */
    public Object[] toArray();
    /** Prints the list of parameter-value pairs. */
    public String prettyPrint();
}

IncQueryMatcher

/**
 * Interface for an EMF-IncQuery matcher associated with a graph pattern.
 * 
 * @param <Match>
 *            the IPatternMatch type representing a single match of this pattern.
 * @author Bergmann Gábor
 */
public interface IncQueryMatcher<Match extends IPatternMatch> {
    // REFLECTION
    /** The pattern that will be matched. */
    public abstract Pattern getPattern();
    /** Fully qualified name of the pattern. */
    public abstract String getPatternName();
    /** Returns the index of the symbolic parameter with the given name. */
    public abstract Integer getPositionOfParameter(String parameterName);
    /** Returns the array of symbolic parameter names. */
    public abstract String[] getParameterNames();
    // ALL MATCHES
    /** Returns the set of all pattern matches.     */
    public abstract Collection<Match> getAllMatches();
   /* with input bindings */
    public abstract Collection<Match> getAllMatches(Match partialMatch);
    // SINGLE MATCH
    /** Returns an arbitrarily chosen pattern match. Neither determinism nor randomness of selection is guaranteed. */
    public abstract Match getOneArbitraryMatch();
    public abstract Match getOneArbitraryMatch(Match partialMatch);
    // MATCH CHECKING
    /**Indicates whether the given combination of specified pattern parameters constitute a valid pattern match */
    public abstract boolean hasMatch(Match partialMatch);
    // NUMBER OF MATCHES
    /** Returns the number of all pattern matches. */
    public abstract int countMatches();
    public abstract int countMatches(Match partialMatch);
    // MATCH processing
    /** Executes the given processor on each match of the pattern. */
    public abstract void forEachMatch(IMatchProcessor<? super Match> processor);
    public abstract void forEachMatch(Match partialMatch, IMatchProcessor<? super Match> processor);
    public abstract boolean forOneArbitraryMatch(IMatchProcessor<? super Match> processor);
    public abstract boolean forOneArbitraryMatch(Match partialMatch, IMatchProcessor<? super Match> processor);
    // CHANGE MONITORING
    // attach delta monitor for high-level change detection
    public abstract void addCallbackOnMatchUpdate(IMatchUpdateListener<Match> listener, boolean fireNow);
    public abstract void removeCallbackOnMatchUpdate(IMatchUpdateListener<Match> listener);
    /** Registers a new delta monitor on this pattern matcher. The DeltaMonitor can be used to track changes (delta) in
     * the set of pattern matches from now on. It can also be reset to track changes from a later point in time, and
     * changes can even be acknowledged on an individual basis. */
    public abstract DeltaMonitor<Match> newDeltaMonitor(boolean fillAtStart);
    public abstract DeltaMonitor<Match> newFilteredDeltaMonitor(boolean fillAtStart, Match partialMatch);
    /** Registers a callback that will be run each time EMF-IncQuery match sets are refreshed after a model update.
     * Typically useful to check delta monitors. When the callback is issued, the pattern match sets are guaranteed to
     * reflect the post-state after the update. */
    public boolean addCallbackAfterUpdates(Runnable callback);
    public boolean removeCallbackAfterUpdates(Runnable callback);
    /**
     * Registers a callback that will be run each time the EMF-IncQuery engine is wiped or disposed. Typically useful if
     * delta monitors are used, especially of the {@link IncQueryEngine} is managed. */
    public boolean addCallbackAfterWipes(Runnable callback);
    public boolean removeCallbackAfterWipes(Runnable callback);
 
    /**
     * Returns an empty, mutable Match for the matcher. 
     * Fields of the mutable match can be filled to create a partial match, usable as matcher input. 
     * This can be used to call the matcher with a partial match 
     *  even if the specific class of the matcher or the match is unknown.*/
    public abstract Match newEmptyMatch();
    public abstract Match newMatch(Object... parameters);
    /**
     * Retrieve the set of values that occur in matches for the given parameterName. */
    public abstract Set<Object> getAllValues(final String parameterName);
    /**
     * Retrieve the set of values that occur in matches for the given parameterName, that conforms to the given fixed
     * values of some parameters. */
    public abstract Set<Object> getAllValues(final String parameterName, Match partialMatch);
}

The Pattern Registry and Matcher Factories

TODO

IMatcherFactory

/**
 * Interface for an IncQuery matcher factory. Each factory is associated with a pattern. Methods instantiate a matcher
 * of the pattern with various parameters.
 * 
 * @author Bergmann Gábor
 * 
 */
public interface IMatcherFactory<Matcher extends IncQueryMatcher<? extends IPatternMatch>> {
 
    /**
     * @throws IncQueryException
     *             if there was an error loading the pattern definition
     * @returns the pattern for which matchers can be instantiated.
     */
    public Pattern getPattern();
 
    /**
     * Identifies the pattern for which matchers can be instantiated.
     */
    public String getPatternFullyQualifiedName();
 
    /**
     * 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 lightweight reference is created.
     * 
     * <p>
     * The scope of pattern matching will be the given EMF model root and below (see FAQ for more precise definition).
     * <p>
     * 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 tree where the pattern matcher will operate. Recommended: Resource or ResourceSet.
     * @throws IncQueryException
     *             if an error occurs during pattern matcher creation
     */
    public Matcher getMatcher(Notifier emfRoot) throws IncQueryException;
 
    /**
     * Initializes the pattern matcher within an existing {@link IncQueryEngine}. If the pattern matcher is already
     * constructed in the engine, only a lightweight reference is created.
     * <p>
     * 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 Matcher getMatcher(IncQueryEngine engine) throws IncQueryException;
}


Advanced query result set change processing

Match update callbacks

private void changeProcessing_lowlevel(final StringBuilder results, IncQueryMatcher<? extends IPatternMatch> matcher) {
		// (+) these update callbacks are called whenever there is an actual change in the
		// result set of the pattern you are interested in. Hence, they are called fewer times
		// than the "afterUpdates" option, giving better performance.
		// (-)  the downside is that the callbacks are *not* guaranteed to be called in a consistent
		// state (i.e. when the update propagation is settled), hence
		//  * you must not invoke pattern matching and model manipulation _inside_ the callback method
		//  * the callbacks might encounter "hazards", i.e. when an appearance is followed immediately by a disappearance.
		matcher.addCallbackOnMatchUpdate(new IMatchUpdateListener<IPatternMatch>() {
			@Override
			public void notifyDisappearance(IPatternMatch match) {
				// left empty
			}
			@Override
			public void notifyAppearance(IPatternMatch match) {
				results.append("\tNew match found by changeset low level callback: " + match.prettyPrint()+"\n");
			}
		}, false);
	}

After update callbacks and DeltaMonitors

 
	private void changeProcessing_deltaMonitor(final StringBuilder results, IncQueryMatcher<? extends IPatternMatch> matcher) {
		final DeltaMonitor<? extends IPatternMatch> dm = matcher.newDeltaMonitor(false);
		// (+) these updates are guaranteed to be called in a *consistent* state,
		// i.e. when the pattern matcher is guaranteed to be consistent with the model
		// anything can be written into the callback method
		// (-) the downside is that the callback is called after *every* update
		// that propagates through the matcher, i.e. also when the updates do not actually
		// influence the result set you are interested in. Hence, the performance is somewhat
		// lower than for the "lowlevel" option.
		matcher.addCallbackAfterUpdates(new Runnable() {
			@Override
			public void run() {
				for (IPatternMatch newMatch : dm.matchFoundEvents) {
					results.append("\tNew match found by changeset delta monitor: " + newMatch.prettyPrint()+"\n");
				}
				for (IPatternMatch lostMatch : dm.matchLostEvents) {
					// left empty
				}
			}
		});
	}

Advanced IncQuery Lifecycle management

Managed vs. unmanaged IncQueryEngines

TODO

* dispose
* wipe


IncQuery Base

TODO

Extracting reachability paths from transitive closure

TODO

Back to the top