Stores search critera for one participant in an email social network.
An array of EmailParticipantCriteria objects gets passed to EmailNetworkAnalyzer.AnalyzeEmailNetwork().
Наследование: Object
    AnalyzeEmailNetworkInternal
    (
        EmailParticipantCriteria [] participantsCriteria,
        Nullable<DateTime> startTime,
        Nullable<DateTime> endTime,
        String subjectText,
        String bodyText,
        String folder,
        Nullable<Int64> minimumSize,
        Nullable<Int64> maximumSize,
        Nullable<AttachmentFilter> attachmentFilter,
        Nullable<Boolean> hasCc,
        Nullable<Boolean> hasBcc,
        Nullable<Boolean> isReplyFromParticipant1,
        Boolean useCcForEdgeWeights,
        Boolean useBccForEdgeWeights,
        BackgroundWorker backgroundWorker,
        DoWorkEventArgs doWorkEventArgs
    )
    {
        CheckAnalyzeMethodArguments(participantsCriteria, startTime, endTime,
            subjectText, bodyText, folder, minimumSize, maximumSize,
            attachmentFilter, isReplyFromParticipant1);

        Debug.Assert(backgroundWorker == null || doWorkEventArgs != null);

        AssertValid();

        String sQuery = CreateQuery(participantsCriteria, startTime, endTime,
            subjectText, bodyText, folder, minimumSize, maximumSize,
            attachmentFilter, hasCc, hasBcc, isReplyFromParticipant1);

        OleDbDataReader oDataReader = GetDataReader(sQuery);

        EmailParticipantPair [] aoEmailParticipantPairs = null;

        try
        {
            aoEmailParticipantPairs = AnalyzeEmailNetworkInternal(
                oDataReader, useCcForEdgeWeights, useBccForEdgeWeights,
                backgroundWorker, doWorkEventArgs);
        }
        finally
        {
            oDataReader.Close();
        }

        return (aoEmailParticipantPairs);
    }
    AnalyzeEmailNetworkAsync
    (
        EmailParticipantCriteria [] participantsCriteria,
        Nullable<DateTime> startTime,
        Nullable<DateTime> endTime,
        String subjectText,
        String bodyText,
        String folder,
        Nullable<Int64> minimumSize,
        Nullable<Int64> maximumSize,
        Nullable<AttachmentFilter> attachmentFilter,
        Nullable<Boolean> hasCc,
        Nullable<Boolean> hasBcc,
        Nullable<Boolean> isReplyFromParticipant1,
        Boolean useCcForEdgeWeights,
        Boolean useBccForEdgeWeights
    )
    {
        AssertValid();

        const String MethodName = "AnalyzeEmailNetworkAsync";

        if (this.IsBusy)
        {
            throw new InvalidOperationException( String.Format(

                "{0}:{1}: An asynchronous operation is already in progress."
                ,
                this.ClassName,
                MethodName
                ) );
        }

        // Wrap the arguments in an object that can be passed to
        // BackgroundWorker.RunWorkerAsync().

        AnalyzeEmailNetworkAsyncArgs oAnalyzeEmailNetworkAsyncArgs =
            new AnalyzeEmailNetworkAsyncArgs();

        oAnalyzeEmailNetworkAsyncArgs.ParticipantsCriteria =
            participantsCriteria;

        oAnalyzeEmailNetworkAsyncArgs.StartTime = startTime;
        oAnalyzeEmailNetworkAsyncArgs.EndTime = endTime;
        oAnalyzeEmailNetworkAsyncArgs.SubjectText = subjectText;
        oAnalyzeEmailNetworkAsyncArgs.BodyText = bodyText;
        oAnalyzeEmailNetworkAsyncArgs.Folder = folder;
        oAnalyzeEmailNetworkAsyncArgs.MinimumSize = minimumSize;
        oAnalyzeEmailNetworkAsyncArgs.MaximumSize = maximumSize;
        oAnalyzeEmailNetworkAsyncArgs.AttachmentFilter = attachmentFilter;
        oAnalyzeEmailNetworkAsyncArgs.HasCc = hasCc;
        oAnalyzeEmailNetworkAsyncArgs.HasBcc = hasBcc;

        oAnalyzeEmailNetworkAsyncArgs.IsReplyFromParticipant1 =
            isReplyFromParticipant1;

        oAnalyzeEmailNetworkAsyncArgs.UseCcForEdgeWeights =
            useCcForEdgeWeights;

        oAnalyzeEmailNetworkAsyncArgs.UseBccForEdgeWeights =
            useBccForEdgeWeights;

        // Create a BackgroundWorker and handle its events.

        m_oBackgroundWorker = new BackgroundWorker();

        m_oBackgroundWorker.WorkerSupportsCancellation = true;

        m_oBackgroundWorker.DoWork += new DoWorkEventHandler(
            BackgroundWorker_DoWork);

        m_oBackgroundWorker.RunWorkerCompleted +=
            new RunWorkerCompletedEventHandler(
                BackgroundWorker_RunWorkerCompleted);

        m_oBackgroundWorker.RunWorkerAsync(oAnalyzeEmailNetworkAsyncArgs);
    }
    AnalyzeEmailNetwork
    (
        EmailParticipantCriteria [] participantsCriteria,
        Nullable<DateTime> startTime,
        Nullable<DateTime> endTime,
        String subjectText,
        String bodyText,
        String folder,
        Nullable<Int64> minimumSize,
        Nullable<Int64> maximumSize,
        Nullable<AttachmentFilter> attachmentFilter,
        Nullable<Boolean> hasCc,
        Nullable<Boolean> hasBcc,
        Nullable<Boolean> isReplyFromParticipant1,
        Boolean useCcForEdgeWeights,
        Boolean useBccForEdgeWeights
    )
    {
        AssertValid();

        return ( AnalyzeEmailNetworkInternal(participantsCriteria, startTime,
            endTime, subjectText, bodyText, folder, minimumSize, maximumSize,
            attachmentFilter, hasCc, hasBcc, isReplyFromParticipant1,
            useCcForEdgeWeights, useBccForEdgeWeights, null, null) );
    }
    CreateQuery
    (
        EmailParticipantCriteria [] participantsCriteria,
        Nullable<DateTime> startTime,
        Nullable<DateTime> endTime,
        String subjectText,
        String bodyText,
        String folder,
        Nullable<Int64> minimumSize,
        Nullable<Int64> maximumSize,
        Nullable<AttachmentFilter> attachmentFilter,
        Nullable<Boolean> hasCc,
        Nullable<Boolean> hasBcc,
        Nullable<Boolean> isReplyFromParticipant1
    )
    {
        AssertValid();

        StringBuilder oStringBuilder = new StringBuilder();
        oStringBuilder.Append(BaseQuery);

        String sEscapedFirstParticipant = null;
        Int32 i = 0;

        StringBuilder oParticipantCriteriaStringBuilder =
            new StringBuilder();

        if (participantsCriteria != null)
        {
            foreach (EmailParticipantCriteria oParticipantCriteria in
                participantsCriteria)
            {
                String sEscapedParticipant =
                    EscapeStringForContains(oParticipantCriteria.Participant);

                Debug.Assert( !String.IsNullOrEmpty(sEscapedParticipant) );

                if (i == 0)
                {
                    sEscapedFirstParticipant = sEscapedParticipant;
                }

                i++;

                IncludedIn eIncludedIn = oParticipantCriteria.IncludedIn;

                if (eIncludedIn == IncludedIn.None)
                {
                    // Skip this one.

                    continue;
                }

                if (oParticipantCriteriaStringBuilder.Length > 0)
                {
                    // The participants are ORed together.

                    oParticipantCriteriaStringBuilder.Append(" OR ");
                }

                // This part of the query will look like this, in pseudocode:
                //
                // ( Contains(To, Participant) 
                // OR Contains(From, Participant) OR Contains(Cc, Participant)
                // OR Contains(Bcc, Participant) )

                // Open the outer clause.

                oParticipantCriteriaStringBuilder.Append("(");

                // Append a clause for each IncludedIn flag.

                Boolean bParticipantClauseAppended = false;

                AppendParticipantClauseToQuery(sEscapedParticipant,
                    eIncludedIn, IncludedIn.From,
                    oParticipantCriteriaStringBuilder,
                    ref bParticipantClauseAppended);

                AppendParticipantClauseToQuery(sEscapedParticipant,
                    eIncludedIn, IncludedIn.To,
                    oParticipantCriteriaStringBuilder,
                    ref bParticipantClauseAppended);

                AppendParticipantClauseToQuery(sEscapedParticipant,
                    eIncludedIn, IncludedIn.Cc,
                    oParticipantCriteriaStringBuilder,
                    ref bParticipantClauseAppended);

                AppendParticipantClauseToQuery(sEscapedParticipant,
                    eIncludedIn, IncludedIn.Bcc,
                    oParticipantCriteriaStringBuilder,
                    ref bParticipantClauseAppended);

                // Close the outer clause.

                oParticipantCriteriaStringBuilder.Append(")");
            }

            if (oParticipantCriteriaStringBuilder.Length > 0)
            {
                oStringBuilder.AppendFormat(

                    " AND ({0}) "
                    ,
                    oParticipantCriteriaStringBuilder
                    );
            }
        }

        const String DateSentClause =
            " AND System.Message.DateSent {0} '{1}'"
            ;

        if (startTime.HasValue)
        {
            oStringBuilder.AppendFormat(

                DateSentClause
                ,
                ">=",
                FormatTime(startTime.Value)
                );
        }

        if (endTime.HasValue)
        {
            oStringBuilder.AppendFormat(

                DateSentClause
                ,
                "<=",
                FormatTime(endTime.Value)
                );
        }

        if ( !String.IsNullOrEmpty(subjectText) )
        {
            // Important note:
            //
            // System.Subject works for the subject on Vista with its original
            // search engine, and with Windows Desktop Search 4.0.  On XP with
            // Windows.Desktop.Search, however, System.Subject does not work.
            // System.Title works in Vista/WDS4.0 and XP/WDS4.0.  (It has not
            // yet been tested on Vista with its original search engine).

            oStringBuilder.AppendFormat(

                " AND Contains(System.Title, '\"{0}\"')"
                ,
                EscapeStringForContains(subjectText)
                );
        }

        if ( !String.IsNullOrEmpty(bodyText) )
        {
            oStringBuilder.AppendFormat(

                " AND Contains ('\"{0}\"')"
                ,
                EscapeStringForContains(bodyText)
                );
        }

        if ( !String.IsNullOrEmpty(folder) )
        {
            oStringBuilder.AppendFormat(

                " AND System.ItemFolderPathDisplay = '{0}'"
                ,
                EscapeStringForEquals(folder)
                );
        }

        if (minimumSize.HasValue)
        {
            oStringBuilder.AppendFormat(

                " AND System.Size >= {0}"
                ,
                minimumSize.Value
                );
        }

        if (maximumSize.HasValue)
        {
            oStringBuilder.AppendFormat(

                " AND System.Size <= {0}"
                ,
                maximumSize.Value
                );
        }

        if (attachmentFilter.HasValue)
        {
            oStringBuilder.AppendFormat(

                " AND System.Message.HasAttachments = {0}"
                ,
                attachmentFilter.Value == AttachmentFilter.NoAttachment ?
                    "FALSE" : "TRUE"
                );

            if (attachmentFilter.Value ==
                AttachmentFilter.HasAttachmentFromParticipant1)
            {
                Debug.Assert( !String.IsNullOrEmpty(sEscapedFirstParticipant) );

                oStringBuilder.AppendFormat(

                    " AND Contains(System.Message.FromAddress, '\"{0}\"')"
                    ,
                    sEscapedFirstParticipant
                    );
            }
        }

        if (hasCc.HasValue)
        {
            oStringBuilder.AppendFormat(

                " AND System.Message.CcAddress IS {0} NULL"
                ,
                hasCc.Value ? "NOT": String.Empty
                );
        }

        if (hasBcc.HasValue)
        {
            oStringBuilder.AppendFormat(

                " AND System.Message.BccAddress IS {0} NULL"
                ,
                hasBcc.Value ? "NOT": String.Empty
                );
        }

        if (isReplyFromParticipant1.HasValue)
        {
            // IMPORTANT NOTE: As of April 2008, the
            // System.Message.IsFwdOrReply message property needed to implement
            // this is always null, so specifying a value here will always
            // return an empty recordset.
            //
            // Note: System.Message.IsFwdOrReply is an Int32, not a Boolean.
            // The documentation doesn't indicate what the possible values are.
            // I'm assuming that 1 means true and 0 means false.

            oStringBuilder.AppendFormat(

                " AND ( System.Message.IsFwdOrReply = {0} AND"
                + " Contains(System.Message.FromAddress, '\"{1}\"') )"
                ,
                isReplyFromParticipant1.Value ? 1 : 0,
                sEscapedFirstParticipant
                );
        }

        return ( oStringBuilder.ToString() );
    }
    CheckAnalyzeMethodArguments
    (
        EmailParticipantCriteria [] participantsCriteria,
        Nullable<DateTime> startTime,
        Nullable<DateTime> endTime,
        String subjectText,
        String bodyText,
        String folder,
        Nullable<Int64> minimumSize,
        Nullable<Int64> maximumSize,
        Nullable<AttachmentFilter> attachmentFilter,
        Nullable<Boolean> isReplyFromParticipant1
    )
    {
        AssertValid();

        ArgumentChecker oArgumentChecker = this.ArgumentChecker;

        Boolean bHasFirstParticipant = false;

        if (participantsCriteria != null)
        {
            foreach (EmailParticipantCriteria participantCriteria in
                participantsCriteria)
            {
                if ( String.IsNullOrEmpty(participantCriteria.Participant) )
                {
                    oArgumentChecker.ThrowArgumentException(AnalyzeMethodName,
                        "participantsCriteria",
                        "An email address wasn't specified.",
                        null
                        );
                }

                bHasFirstParticipant = true;
            }
        }

        if (startTime.HasValue && endTime.HasValue &&
            endTime.Value < startTime.Value)
        {
            oArgumentChecker.ThrowArgumentException(AnalyzeMethodName,
                "endTime",

                "The end time must be greater than or equal to the start"
                + " time.",

                null
                );
        }

        CheckAnalyzeMethodArgument(subjectText, "subjectText");
        CheckAnalyzeMethodArgument(bodyText, "bodyText");
        CheckAnalyzeMethodArgument(folder, "folder");

        if (minimumSize.HasValue)
        {
            oArgumentChecker.CheckArgumentPositive(
                AnalyzeMethodName, "minimumSize", minimumSize.Value);
        }

        if (maximumSize.HasValue)
        {
            oArgumentChecker.CheckArgumentPositive(
                AnalyzeMethodName, "maximumSize", maximumSize.Value);
        }

        if (minimumSize.HasValue && maximumSize.HasValue &&
            maximumSize.Value < minimumSize.Value)
        {
            oArgumentChecker.ThrowArgumentException(AnalyzeMethodName,
                "maximumSize",

                "maximumSize must be greater than or equal to"
                + " minimumSize."
                ,
                null
                );
        }

        if (attachmentFilter.HasValue &&
            attachmentFilter.Value ==
                AttachmentFilter.HasAttachmentFromParticipant1
            && !bHasFirstParticipant)
        {
            oArgumentChecker.ThrowArgumentException(AnalyzeMethodName,
                "attachmentFilter",

                "If attachmentFilter is HasAttachmentsFromParticipant1, a"
                + " first participant must also be specified.",

                null
                );
        }

        if (isReplyFromParticipant1.HasValue && !bHasFirstParticipant)
        {
            oArgumentChecker.ThrowArgumentException(AnalyzeMethodName,
                "optionaIsReplyFromParticipant1",

                "If isReplyFromParticipant1 is specified, a first participant"
                + " must also be specified."
                ,
                null
                );
        }
    }
    DataGridViewRowToEmailParticipantCriteria
    (
        DataGridViewRow oRow
    )
    {
        Debug.Assert(oRow != null);
        AssertValid();

        EmailParticipantCriteria oEmailParticipantCriteria =
            new EmailParticipantCriteria();

        String sParticipant =
            (String)oRow.Cells[this.colParticipant.Name].Value;

        if ( !String.IsNullOrEmpty(sParticipant) )
        {
            // Trim the participant string.

            sParticipant = sParticipant.Trim();
            oRow.Cells[this.colParticipant.Name].Value = sParticipant;
        }

        if ( !String.IsNullOrEmpty(sParticipant) )
        {
            sParticipant = ParticipantToAnalyzer(sParticipant);
        }

        oEmailParticipantCriteria.Participant = sParticipant;

        IncludedIn eIncludedIn = IncludedIn.None;

        if ( DataGridViewCheckBoxCellIsChecked(oRow, this.colFrom.Name) )
        {
            eIncludedIn |= IncludedIn.From;
        }

        if ( DataGridViewCheckBoxCellIsChecked(oRow, this.colTo.Name) )
        {
            eIncludedIn |= IncludedIn.To;
        }

        if ( DataGridViewCheckBoxCellIsChecked(oRow, this.colCc.Name) )
        {
            eIncludedIn |= IncludedIn.Cc;
        }

        if ( DataGridViewCheckBoxCellIsChecked(oRow, this.colBcc.Name) )
        {
            eIncludedIn |= IncludedIn.Bcc;
        }

        oEmailParticipantCriteria.IncludedIn = eIncludedIn;

        return (oEmailParticipantCriteria);
    }