package accrue.analysis.pointer.analyses;

import accrue.analysis.pointer.CContext;
import accrue.analysis.pointer.CallSiteNode;
import accrue.analysis.pointer.HContext;

/**
 * Analysis that keeps the first N call sites where the file called from matches a particular prefix. 
 * Once the context stack is full, no more call sites are tracked, even if they 
 * match. This can be used together with a more general analysis, using 
 * {@link CrossProductAnalysis}, to gain distinguish calls to particular methods 
 * or packages. For example to calls from an application by using 
 * "myapplication.mypkg" or "myapplication.mypkg.MyClass" for the prefix.
 */
public class StickFirstCalledFrom extends StickFirstMatches {

    /**
     * Any call sites to methods from the given prefix will be tracked up to the specified sensitivity.
     */
    private final String prefix;

    /**
     * Create an analysis that tracks called from a particular prefix with the 
     * given context-call-stack depth, once that depth is reached the context is 
     * "stuck" and no more call sites are added.
     * 
     * @param sensitivity
     *            depth of the call stack to keep track of
     * @param prefixToTrack
     *            Methods called from this prefix will be tracked up to the sensitivity, 
     *            deeper than the sensitivity they will "stick" in the context.
     */
    public StickFirstCalledFrom(int sensitivity, String prefixToTrack) {
        super(sensitivity);
        this.prefix = prefixToTrack;
    }

    /**
     * Create an analysis that tracks methods called from a particular prefix with the 
     * given context-call-stack depth, once that depth is reached the context is 
     * "stuck" and no more call sites are added.
     * 
     * @param prefixToTrack
     *            Methods called from this prefix will be tracked up to the sensitivity, 
     *            deeper than the sensitivity they will "stick" in the context.
     */
    public StickFirstCalledFrom(String prefixToTrack) {
        this.prefix = prefixToTrack;
    }

    @Override
    public String toString() {
        return "CalledFromStickFirst(" + this.prefix + ")";
    }

    @Override
    boolean match(CallSiteNode callSite, HContext receiver,
            CContext callerContext) {

        String fullName = callSite.getPosition().path();

        if (fullName != null && fullName.startsWith(prefix)) {
            return true;
        }

        return false;
    }
}
