/******************************************************************************* * Copyright (c) 2011 Codehaus.org, SpringSource, and others. * 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: * Andrew Eisenberg - Initial implemenation *******************************************************************************/ package org.codehaus.groovy.eclipse.dsl.pointcuts; import groovy.lang.Closure; import java.util.Collection; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IStorage; /** * A pointcut that can be defined in a DSLD file. A pointcut describes * <i>where</i> a contribution group should be applied. * <p> * An {@link IPointcut} instance may contain state, but they must be immutable once created. * Pointcut evaluation may be occurring simultaneously on multiple threads. * <p> * Here is the order in which the methods are called: * <ol> * <li> any number of {@link #addArgument(Object)} and {@link #addArgument(String, Object)}. * but a pointcut must have only named or only unnamed arguments. The two styles * cannot be mixed * <li> {@link #verify()}. If this method does not return an OK status, then the following methods are not called * <li> {@link #normalize()} this method will reorganize this query and contained queries to make more efficient. * after this method call, Poincuts are immutable * <li> {@link #matches(GroovyDSLDContext)}. This method can be called any number of times and from different threads. * It should not mutate state * <ol> * * There are several broad categories of pointcuts, each with their own expectactions: * <ol> * <li>Filtering pointcuts, which require a surrounding pointcut to pass some state in (eg- find field/method) * <li>Structural pointcuts, which depend on the lexical structure of the code (eg- enclosingClass) * <li>Layout pointcuts, which depend on invariant factors external to the current module (eg- location in project, or file name) * <li>Semantic pointcuts, which depend on inferencing (eg- currentType) * </ol> * Each category offers a different way to internally optimize * * * @author andrew * @created Nov 17, 2010 */ public interface IPointcut { /** * Detmrmines if this pointcut is applicable in the current context * @param pattern corresponding to the current location being inferred. * @param toMatch objet to match on (might be a {@link Collection}) * @return a {@link BindingSet} corresponding to the items bound in this * pointcut evaluation, or else null if there was no match */ Collection<?> matches(GroovyDSLDContext pattern, Object toMatch); /** * A unique identifier for the container that created this context. * @return a unique identifier */ IStorage getContainerIdentifier(); /** * Recursively rewrites this query so that it can run faster * @return a rewritten query that will likely run faster, or this object if no nomralization is applicable. */ IPointcut normalize(); /** * Adds an argument for this pointcut * @param name the optional name for this argument or null if none * @param argument the argument (may be another pointcut, or a string parameter, etc) */ void addArgument(String name, Object argument); /** * Adds an argument for this pointcut. Variant of {@link #addArgument(String, Object)} that * does not take a name * @param argument the argument (may be another pointcut, or a string parameter, etc) */ void addArgument(Object argument); void verify() throws PointcutVerificationException; Object getFirstArgument(); String getFirstArgumentName(); Object[] getArgumentValues(); String[] getArgumentNames(); void setProject(IProject project); /** * Associates the {@link IContributionGroup} with this pointcut. * The pointcut and the contribution group are registered in the {@link DSLDStore} * @param contributionGroupClosure the closure that will be used by an {@link IContributionGroup} */ void accept(@SuppressWarnings("rawtypes") Closure contributionGroupClosure); /** * Do a fast match on this pattern. Return false, if there is no way that any pattern that is contained inside * of this one could ever match. Return true if there is a chance. * * For example if the {@link IPointcut} looks at file names or file paths and there this initial pattern does * not match, then there are no sub-patterns that can ever match. * * @param pattern * @return */ boolean fastMatch(GroovyDSLDContext pattern); /** * User-readable name of the pointcut * @return */ String getPointcutName(); /** * Extended name printed out during errors * @return */ String getPointcutDebugName(); }