ProteinList_Filter::Impl::Impl(ProteinListPtr _original, const Predicate& predicate)
:   original(_original), getSequence(false)
{
    if (!original.get()) throw runtime_error("[ProteinList_Filter] Null pointer");

    // iterate through the proteins, using predicate to build the sub-list
    for (size_t i=1, end=original->size(); i<=end; ++i)
    {
        if (predicate.done()) break;

        ProteinPtr protein = original->protein(i-1, getSequence);
        tribool accepted = predicate.accept(*protein);

        if (accepted || getSequence) // if still indeterminate with getSequence = true, it passes the filter by default
        {
            pushProtein(*protein);            
        }
        else if (!accepted)
        {
            // do nothing 
        }
        else // indeterminate and !getSequence
        {
            // try again with getSequence = true
            getSequence = true;
            --i;
        }
    }
}