/// ------------------------------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="MasterQuestionParser"/> class.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public MasterQuestionParser(QuestionSections sections, IEnumerable <string> questionWords,
                                    IEnumerable <IKeyTerm> keyTerms, KeyTermRules keyTermRules,
                                    IEnumerable <PhraseCustomization> customizations,
                                    IEnumerable <Substitution> phraseSubstitutions)
        {
            m_sections      = sections;
            m_questionWords = questionWords;
            if (questionWords != null)
            {
                m_questionWordsLookupTable = new Dictionary <int, List <List <Word> > >();
                foreach (string questionWordPhrase in questionWords)
                {
                    List <Word>         listOfWordsInQuestion = questionWordPhrase.Split(' ').Select(w => (Word)w).ToList();
                    int                 count = listOfWordsInQuestion.Count;
                    List <List <Word> > listOfQuestionsForCount;
                    if (!m_questionWordsLookupTable.TryGetValue(count, out listOfQuestionsForCount))
                    {
                        m_questionWordsLookupTable[count] = listOfQuestionsForCount = new List <List <Word> >();
                    }
                    listOfQuestionsForCount.Add(listOfWordsInQuestion);
                }
            }
            if (customizations != null)
            {
                m_customizations = new Dictionary <int, SortedDictionary <QuestionKey, Customizations> >();
                foreach (var customization in customizations)
                {
                    var bookKey = customization.ScrStartReference.Book;
                    SortedDictionary <QuestionKey, Customizations> customizationsForBook;
                    if (!m_customizations.TryGetValue(bookKey, out customizationsForBook))
                    {
                        m_customizations[bookKey] = customizationsForBook = new SortedDictionary <QuestionKey, Customizations>();
                    }

                    var            customizationsKey = customization.Key;
                    Customizations customizationsForKey;
                    if (!customizationsForBook.TryGetValue(customizationsKey, out customizationsForKey))
                    {
                        customizationsForBook[customizationsKey] = customizationsForKey = new Customizations();
                    }
                    customizationsForKey.Add(customization);
                }
            }
            if (keyTerms != null)
            {
                m_keyTermsTable = new Dictionary <Word, List <KeyTermMatch> >(keyTerms.Count());
                PopulateKeyTermsTable(keyTerms, keyTermRules);
            }

            if (phraseSubstitutions != null)
            {
                m_phraseSubstitutions = new Dictionary <Regex, string>(phraseSubstitutions.Count());
                foreach (Substitution substitutePhrase in phraseSubstitutions)
                {
                    m_phraseSubstitutions[substitutePhrase.RegEx] = substitutePhrase.RegExReplacementString;
                }
            }

            m_partsTable = new SortedDictionary <int, Dictionary <Word, List <ParsedPart> > >();
        }
        public void KeyTermRules_Initialize_GetsCorrectRules()
        {
            string xmlRules = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                              "<KeyTermRules>" +
                              "<KeyTermRule id=\"Ar\" rule=\"MatchForRefOnly\"/>" +
                              "<KeyTermRule id=\"ask; pray\" rule=\"MatchForRefOnly\"/>" +
                              "<KeyTermRule id=\"(pe quot) say\" rule=\"Exclude\"/>" +
                              "<KeyTermRule id=\"bless, praise\">" +
                              "  <Alternate name=\"blesses\"/>" +
                              "  <Alternate name=\"blessing\"/>" +
                              "</KeyTermRule>" +
                              "<KeyTermRule id=\"(?&lt;term&gt;.+): \\(\\d+\\).+; \" regex=\"true\"/>" +
                              "<KeyTermRule id=\"\\(\\d+\\) (?&lt;term&gt;[^;]+): \\([^;]+\\)\" regex=\"true\"/>" +
                              "</KeyTermRules>";
            KeyTermRules rules = XmlSerializationHelper.DeserializeFromString <KeyTermRules>(xmlRules);

            rules.Initialize();
            Assert.AreEqual(2, rules.RegexRules.Count());
            Assert.IsTrue(rules.RegexRules.Any(r => r.ToString() == "(?<term>.+): \\(\\d+\\).+; "));
            Assert.IsTrue(rules.RegexRules.Any(r => r.ToString() == "\\(\\d+\\) (?<term>[^;]+): \\([^;]+\\)"));
            Assert.IsTrue(rules.RulesDictionary["ar"].Rule == KeyTermRule.RuleType.MatchForRefOnly);
            KeyTermRule rule;

            Assert.IsTrue(rules.RulesDictionary.TryGetValue("ask; pray", out rule));
        }
 /// ------------------------------------------------------------------------------------
 /// <summary>
 /// Initializes a new instance of the <see cref="MasterQuestionParser"/> class.
 /// </summary>
 /// ------------------------------------------------------------------------------------
 public MasterQuestionParser(string filename, IEnumerable <string> questionWords,
                             IEnumerable <IKeyTerm> keyTerms, KeyTermRules keyTermRules,
                             IEnumerable <PhraseCustomization> customizations,
                             IEnumerable <Substitution> phraseSubstitutions) :
     this(XmlSerializationHelper.DeserializeFromFile <QuestionSections>(filename),
          questionWords, keyTerms, keyTermRules, customizations, phraseSubstitutions)
 {
 }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Populates the key terms table.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void PopulateKeyTermsTable(IEnumerable <IKeyTerm> keyTerms, KeyTermRules rules)
        {
            KeyTermMatchBuilder matchBuilder;

            foreach (IKeyTerm keyTerm in keyTerms)
            {
                matchBuilder = new KeyTermMatchBuilder(keyTerm,
                                                       rules == null ? null : rules.RulesDictionary, rules == null ? null : rules.RegexRules);

                foreach (KeyTermMatch matcher in matchBuilder.Matches.Where(matcher => matcher.WordCount != 0))
                {
                    List <KeyTermMatch> foundMatchers;
                    Word firstWord = matcher[0];
                    if (!m_keyTermsTable.TryGetValue(firstWord, out foundMatchers))
                    {
                        m_keyTermsTable[firstWord] = foundMatchers = new List <KeyTermMatch>();
                    }

                    KeyTermMatch existingMatcher = foundMatchers.FirstOrDefault(m => m.Equals(matcher));
                    if (existingMatcher == null)
                    {
                        foundMatchers.Add(matcher);
                    }
                    else
                    {
                        existingMatcher.AddTerm(keyTerm);
                    }
                }
            }

#if DEBUG
            if (rules != null)
            {
                string unUsedRules = rules.RulesDictionary.Values.Where(r => !r.Used).ToString(Environment.NewLine);
                if (unUsedRules.Length > 0)
                {
                    MessageBox.Show("Unused KeyTerm Rules: \n" + unUsedRules, "Transcelerator");
                }
            }
#endif
        }
 /// ------------------------------------------------------------------------------------
 /// <summary>
 /// Initializes a new instance of the <see cref="MasterQuestionParser"/> class. This
 /// version is useful when you just need a parser to use for ad-hoc questions, since
 /// it does not take an initial collection of sections with questions to be parsed.
 /// </summary>
 /// ------------------------------------------------------------------------------------
 public MasterQuestionParser(IEnumerable <string> questionWords,
                             IEnumerable <IKeyTerm> keyTerms, KeyTermRules keyTermRules,
                             IEnumerable <Substitution> phraseSubstitutions) : this(default(QuestionSections), questionWords,
                                                                                    keyTerms, keyTermRules, null, phraseSubstitutions)
 {
 }