package accrue.analysis.pointer.analyses;

import polyglot.types.MemberInstance;
import accrue.analysis.pointer.CContext;
import accrue.analysis.pointer.CallSiteNode;
import accrue.analysis.pointer.HContext;

/**
 * Call site sensitive for any callees matching a given prefix
 */
public class CallSiteForCallee extends CallSiteForPattern {

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

    /**
     * Create an analysis that tracks methods with a particular prefix with the 
     * given context-call-stack depth
     * 
     * @param sensitivity
     *            depth of the call stack to keep track of
     * @param prefixToTrack
     *            Methods with this prefix will be tracked up to the sensitivity
     */
    public CallSiteForCallee(int sensitivity, String prefixToTrack) {
        super(sensitivity);
        this.prefix = prefixToTrack;
    }

    /**
     * Create an analysis that tracks methods with a particular prefix with the 
     * given context-call-stack depth and the default sensitivity.
     * 
     * @param prefixToTrack
     *            Methods with this prefix will be tracked up to the sensitivity
     */
    public CallSiteForCallee(String prefixToTrack) {
        this.prefix = prefixToTrack;
    }

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

    @Override
    boolean match(CallSiteNode callSite, HContext receiver,
            CContext callerContext) {
        if (callSite.callee() instanceof MemberInstance) {
            MemberInstance mi = (MemberInstance) callSite.callee();
            if (mi.container().isClass()) {
                String fullName = mi.container().toClass().fullName();
                if (fullName.startsWith(prefix)) {
                    return true;
                }
            }
        }

        return false;
    }
}
