/*******************************************************************************
* Copyright (c) 2010-2012, Abel Hegedus, Istvan Rath and Daniel Varro
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Abel Hegedus - initial API and implementation
*******************************************************************************/
package org.eclipse.incquery.databinding.runtime.collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
import org.eclipse.core.databinding.observable.set.SetDiff;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.incquery.databinding.runtime.api.IncQueryObservables;
import org.eclipse.incquery.runtime.api.IMatcherFactory;
import org.eclipse.incquery.runtime.api.IPatternMatch;
import org.eclipse.incquery.runtime.api.IncQueryEngine;
import org.eclipse.incquery.runtime.api.IncQueryMatcher;
import org.eclipse.incquery.runtime.extensibility.MatcherFactoryRegistry;
import org.eclipse.incquery.runtime.triggerengine.api.Agenda;
import org.eclipse.incquery.runtime.triggerengine.api.IAgenda;
import org.eclipse.incquery.runtime.triggerengine.api.RuleEngine;
import com.google.common.collect.Sets;
/**
* Observable view of a match set for a given {@link IncQueryMatcher} on a model (match sets of an
* {@link IncQueryMatcher} are not ordered by default).
*
* <p>
* This implementation uses the {@link RuleEngine} to get notifications for match set changes, and can be instantiated
* using either an existing {@link IncQueryMatcher}, or an {@link IMatcherFactory} and either a {@link Notifier},
* {@link IncQueryEngine} or {@link Agenda}.
*
* @author Abel Hegedus
*
*/
public class ObservablePatternMatchSet<Match extends IPatternMatch> extends AbstractObservableSet implements
IObservablePatternMatchCollection<Match> {
private final Set<Match> cache = Collections.synchronizedSet(new HashSet<Match>());
/**
* Creates an observable view of the match set of the given {@link IncQueryMatcher}.
*
* <p>
* Consider using {@link IncQueryObservables#observeMatchesAsSet} instead!
*
* @param matcher
* the {@link IncQueryMatcher} to use as the source of the observable set
*/
@SuppressWarnings("unchecked")
public <Matcher extends IncQueryMatcher<Match>> ObservablePatternMatchSet(Matcher matcher) {
IMatcherFactory<Matcher> matcherFactory = (IMatcherFactory<Matcher>) MatcherFactoryRegistry
.getOrCreateMatcherFactory(matcher.getPattern());
ObservableCollectionHelper.createRuleInAgenda(this, matcherFactory,
RuleEngine.getInstance().getOrCreateAgenda(matcher.getEngine()));
}
/**
* Creates an observable view of the match set of the given {@link IMatcherFactory} initialized on the given
* {@link Notifier}.
*
* <p>
* Consider using {@link IncQueryObservables#observeMatchesAsSet} instead!
*
* @param factory
* the {@link IMatcherFactory} used to create a matcher
* @param notifier
* the {@link Notifier} on which the matcher is created
*/
public <Matcher extends IncQueryMatcher<Match>> ObservablePatternMatchSet(IMatcherFactory<Matcher> factory,
Notifier notifier) {
this(factory, RuleEngine.getInstance().getOrCreateAgenda(notifier));
}
/**
* Creates an observable view of the match set of the given {@link IMatcherFactory} initialized on the given
* {@link IncQueryEngine}.
*
* <p>
* Consider using {@link IncQueryObservables#observeMatchesAsSet} instead!
*
* @param factory
* the {@link IMatcherFactory} used to create a matcher
* @param engine
* the {@link IncQueryEngine} on which the matcher is created
*/
public <Matcher extends IncQueryMatcher<Match>> ObservablePatternMatchSet(IMatcherFactory<Matcher> factory,
IncQueryEngine engine) {
this(factory, RuleEngine.getInstance().getOrCreateAgenda(engine));
}
/**
* Creates an observable view of the match set of the given {@link IMatcherFactory} initialized on the given
* {@link IncQueryEngine}.
*
* <p>
* Consider using {@link IncQueryObservables#observeMatchesAsSet} instead!
*
* @param factory
* the {@link IMatcherFactory} used to create a matcher
* @param agenda
* an existing {@link Agenda} that specifies the used model
*/
public <Matcher extends IncQueryMatcher<Match>> ObservablePatternMatchSet(IMatcherFactory<Matcher> factory,
IAgenda agenda) {
super();
ObservableCollectionHelper.createRuleInAgenda(this, factory, agenda);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.databinding.observable.list.IObservableList#getElementType()
*/
@Override
public Object getElementType() {
return IPatternMatch.class;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.databinding.observable.set.AbstractObservableSet#getWrappedSet()
*/
@Override
protected Set<Match> getWrappedSet() {
return cache;
}
@SuppressWarnings("unchecked")
@Override
public void addMatch(Match match) {
cache.add(match);
SetDiff diff = Diffs.createSetDiff(Sets.newHashSet(match), Collections.EMPTY_SET);
fireSetChange(diff);
}
@SuppressWarnings("unchecked")
@Override
public void removeMatch(Match match) {
cache.remove(match);
SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Sets.newHashSet(match));
fireSetChange(diff);
}
}