Java tutorial
/******************************************************************************* * Copyright (c) 2010-2012, Tamas Szabo, 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: * Tamas Szabo, Abel Hegedus - initial API and implementation *******************************************************************************/ package org.eclipse.incquery.runtime.evm.api; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.incquery.runtime.evm.api.event.EventFilter; import org.eclipse.incquery.runtime.evm.api.event.EventRealm; import org.eclipse.incquery.runtime.evm.api.resolver.ConflictResolver; import org.eclipse.incquery.runtime.evm.api.resolver.ScopedConflictSet; import org.eclipse.incquery.runtime.evm.specific.resolver.ArbitraryOrderConflictResolver; import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.common.collect.Table; /** * An RuleBase is associated to an {@link EventRealm} and * it is responsible for creating, managing and disposing rules in * the Rule Engine. It provides an unmodifiable view for the collection of applicable activations. * * @author Tamas Szabo * */ public class RuleBase { private final EventRealm eventRealm; private final Table<RuleSpecification<?>, EventFilter<?>, RuleInstance<?>> ruleInstanceTable; private final Agenda agenda; private final Logger logger; /** * Instantiates a new RuleBase instance with the given {@link EventRealm}. * * @param eventRealm * the {@link EventRealm} instance */ protected RuleBase(final EventRealm eventRealm) { this.eventRealm = checkNotNull(eventRealm, "Cannot create RuleBase with null event source"); this.ruleInstanceTable = HashBasedTable.create(); this.logger = Logger.getLogger(this.toString()); this.agenda = new Agenda(this, new ArbitraryOrderConflictResolver()); } /** * Instantiates the given specification over the EventRealm of the RuleBase. * If the specification was already instantiated, the existing instance is returned. * * @param specification the rule to be instantiated * @return the created or existing rule instance */ protected <EventAtom> RuleInstance<EventAtom> instantiateRule(final RuleSpecification<EventAtom> specification, final EventFilter<? super EventAtom> filter) { checkNotNull(specification, "Cannot instantiate null rule!"); checkNotNull(filter, "Cannot instantiate rule with null filter!"); // if(ruleInstanceTable.containsRow(specification)) { final RuleInstance<EventAtom> instance = findInstance(specification, filter); if (instance != null) { return instance; } // } final RuleInstance<EventAtom> rule = specification.instantiateRule(eventRealm, filter); rule.addActivationNotificationListener(agenda.getActivationListener(), true); ruleInstanceTable.put(specification, filter, rule); return rule; } /** * Removes and disposes of a rule instance. * @param instance * @return true, if the instance was part of the RuleBase */ protected <EventAtom> boolean removeRule(final RuleInstance<EventAtom> instance) { checkNotNull(instance, "Cannot remove null rule instance!"); return removeRule(instance.getSpecification(), instance.getFilter()); } /** * Removes and disposes of a rule instance with the given specification. * * @param specification * @param filter the partial match used as filter * @return true, if the specification had an instance in the RuleBase */ protected <EventAtom> boolean removeRule(final RuleSpecification<EventAtom> specification, final EventFilter<? super EventAtom> filter) { checkNotNull(specification, "Cannot remove null rule specification!"); checkNotNull(filter, "Cannot remove instance for null filter"); final RuleInstance<?> instance = findInstance(specification, filter); if (instance != null) { instance.dispose(); ruleInstanceTable.remove(specification, filter); return true; } return false; } /** * Disposes of each rule instance managed by the agenda. * */ protected void dispose() { for (final RuleInstance<?> instance : ruleInstanceTable.values()) { instance.dispose(); } } /** * @return the eventRealm */ public EventRealm getEventRealm() { return eventRealm; } public Multimap<RuleSpecification<?>, EventFilter<?>> getRuleSpecificationMultimap() { final Multimap<RuleSpecification<?>, EventFilter<?>> ruleMap = HashMultimap.create(); final Map<RuleSpecification<?>, Map<EventFilter<?>, RuleInstance<?>>> rowMap = ruleInstanceTable.rowMap(); for (final Entry<RuleSpecification<?>, Map<EventFilter<?>, RuleInstance<?>>> entry : rowMap.entrySet()) { ruleMap.putAll(entry.getKey(), entry.getValue().keySet()); } return ruleMap; } /** * @return an immutable copy of the set of rule instances */ public Set<RuleInstance<?>> getRuleInstances() { return ImmutableSet.copyOf(ruleInstanceTable.values()); } /** * Returns the filtered instance managed by the RuleBase for the given specification. * * @param specification * @param filter the partial match to be used as filter * @return the instance, if it exists, null otherwise */ public <EventAtom> RuleInstance<EventAtom> getInstance(final RuleSpecification<EventAtom> specification, final EventFilter<? super EventAtom> filter) { checkNotNull(specification, "Cannot get instance for null specification"); checkNotNull(filter, "Cannot get instance for null filter"); return findInstance(specification, filter); } @SuppressWarnings("unchecked") private <EventAtom> RuleInstance<EventAtom> findInstance(final RuleSpecification<EventAtom> specification, final EventFilter<? super EventAtom> filter) { // Collection<RuleInstance> instances = ruleInstanceTable.get(specification); // if(instances.size() > 0) { // // // Atom realFilter = checkNotEmpty(filter); // Atom realFilter = filter; // // always use filter (EmptyAtom.INSTANCE) // for (RuleInstance ruleInstance : instances) { // Atom instanceFilter = ruleInstance.getFilter(); // if (realFilter != null && instanceFilter != null && realFilter.equals(instanceFilter)) { // return ruleInstance; // } // if(realFilter == null && instanceFilter == null){ // return ruleInstance; // } // } // } // return null; // EventFilter<EventAtom> realFilter = filter; // if(filter.isEmpty()) { // realFilter = EmptyAtom.INSTANCE; // } return (RuleInstance<EventAtom>) ruleInstanceTable.get(specification, filter); } /** * Creates a scoped conflict set of the enabled activations of the provided rule specifications and filters * using the given conflict resolver. * The set will be incrementally updated until disposed. * * @param conflictResolver * @param specifications */ public ScopedConflictSet createScopedConflictSet(final ConflictResolver conflictResolver, final Multimap<RuleSpecification<?>, EventFilter<?>> specifications) { final ScopedConflictSet set = new ScopedConflictSet(this, conflictResolver, specifications); return set; } /** * @return the agenda */ public Agenda getAgenda() { return agenda; } /** * @return the logger */ public Logger getLogger() { return logger; } }