private void _processConfirmedAttach(QuasiUPAttachmentHelperObject confirmedAttach, List<QuasiUPAttachmentHelperObject> additionalAttachments, Sentence sentence, QuasiUniformPartsAttachmentMainHelperData resultHelpData)
        {
            Log.InfoFormat("Обрабатываем подтвержденный КвазиОЧ-Приложение. Тип1: {0}, Тип2: {1}, Текст: {2}, Id: {3}", confirmedAttach.Type1Confirmed, confirmedAttach.Type2Confirmed, confirmedAttach.Text, confirmedAttach.Id);

            var attachParentElement = sentence.SyntacticParent(confirmedAttach);
            if (attachParentElement != null)
            {
                Log.InfoFormat("  Нашли родителя: Текст: {0}, Id: {1}", attachParentElement.Id, attachParentElement.Text);
                if (attachParentElement.GrammarInfo.PartOfSpeech.Value == PartOfSpeech.Noun.Value || attachParentElement.GrammarInfo.PartOfSpeech.Value == PartOfSpeech.Pronoun.Value)
                {
                    Log.InfoFormat("  У родителя часть речи: существительное или местоимение, добавляем квази ОЧ.");
                    var attachParentElementWithHelperInfo = new QuasiUPAttachmentHelperObject(attachParentElement)
                    {
                        SourceNr = -1,
                        Type1Confirmed = confirmedAttach.Type1Confirmed,
                        Type2Confirmed = confirmedAttach.Type2Confirmed,
                        IsInitiallyType1 = confirmedAttach.IsInitiallyType1,
                        IsInitiallyType2 = confirmedAttach.IsInitiallyType2,
                        IsAdditional = true,
                        AddedParent = true,
                        NewNr = confirmedAttach.SourceNr
                    };
                    additionalAttachments.Add(attachParentElementWithHelperInfo);
                }
                else if(attachParentElement.GrammarInfo.PartOfSpeech.Value == PartOfSpeech.Verb.Value)
                {
                    Log.InfoFormat("  У родителя часть речи: глагол, ищем потомков-существительные с таким же падежом, как у обрабатываемого Квази ОЧ.");
                    var parentChildren = sentence.SyntacticChildren(attachParentElement).FindAll(
                                x => x.GUID != confirmedAttach.GUID
                                && x.GrammarInfo.PartOfSpeech.Value == PartOfSpeech.Noun.Value
                                && x.GrammarInfo.Case.Value == confirmedAttach.GrammarInfo.Case.Value);

                    if (parentChildren.Count > 0)
                    {
                        foreach (var child in parentChildren)
                        {
                            Log.InfoFormat("    Добавляем потомка-существительного с падежом {0} к результирующему массиву", confirmedAttach.GrammarInfo.Case.Value);
                            var childWithHelperInfo = new QuasiUPAttachmentHelperObject(child)
                            {
                                SourceNr = -1,
                                Type1Confirmed = confirmedAttach.Type1Confirmed,
                                Type2Confirmed = confirmedAttach.Type2Confirmed,
                                IsInitiallyType1 = confirmedAttach.IsInitiallyType1,
                                IsInitiallyType2 = confirmedAttach.IsInitiallyType2,
                                IsAdditional = true,
                                AddedChildForParent =  true,
                                NewNr = confirmedAttach.SourceNr
                            };
                            additionalAttachments.Add(childWithHelperInfo);
                        }
                    }
                    else
                        Log.InfoFormat("  У родителя с PartOfSpeech = {0} не найдены потомки-существительные в падеже {1}, кроме текущего активного элемента. Ничего не делаем", attachParentElement.GrammarInfo.PartOfSpeech.Value, confirmedAttach.GrammarInfo.Case.Value);
                }
            }
            else
                Log.Error("Для данного ТЭ не найден синтаксический родитель!");
        }
        private void _processAttachments(List<QuasiUPAttachmentHelperObject> attachments, Sentence sentence, QuasiUniformPartsAttachmentMainHelperData resultHelpData)
        {
            if (!attachments.Any(x => x.IsInitiallyType2))
                Log.InfoFormat("ТЭ Квази ОЧ-Приложение Тип2 не найдено. Переходим к обработке КвазиОЧ с типом 1.");

            foreach (var attach in attachments.FindAll(x => x.IsInitiallyType2))
            {
                Log.InfoFormat("Рассматриваем ТЭ Квази ОЧ-Приложение Тип2 с Id: '{0}' и текстом '{1}' ", attach.Id, attach.Text);

                var attachCase = attach.GrammarInfo.Case.Value;
                Log.InfoFormat("  Значение тега <case> у рассматриваемого ТЭ: {0}", attachCase);

                var attachParentElement = sentence.SyntacticParent(attach);
                if (attachParentElement != null)
                {
                    var attachParentPartOfSpeech = attachParentElement.GrammarInfo.PartOfSpeech.Value;
                    var attachParentCase = attachParentElement.GrammarInfo.Case.Value;
                    Log.InfoFormat(
                        "  Синтаксический родитель ТЭ: Id: {0}, Text: {1}, PartOfSpeech: {2}, Case: {3}",
                        attachParentElement.Id, attachParentElement.Text, attachParentPartOfSpeech, attachParentCase);

                    var parentHasRightPartOfSpeech = false;
                    if (attachParentPartOfSpeech == PartOfSpeech.Noun.Value ||
                        attachParentPartOfSpeech == PartOfSpeech.Pronoun.Value)
                    {
                        Log.InfoFormat("  Нашли нужное значение тега. [П6 Т4.1] OK.");
                        parentHasRightPartOfSpeech = true;
                    }

                    if ((attachParentCase == attachCase) && parentHasRightPartOfSpeech)
                    {
                        Log.InfoFormat("  Подтвердили Тип 2.");
                        attach.Type2Confirmed = true;
                    }
                    else
                    {
                        Log.InfoFormat("  Подтвердили Тип 1 (изначально Тип 2).");
                        attach.Type2TransofrmedToType1 = true;
                        attach.Type1Confirmed = true;
                    }
                }
                else
                    Log.Error("  Для данного ТЭ не найден синтаксический родитель!");
            }

            // все ОЧ с типом 1 подтверждаем автоматически
            attachments.FindAll(x => x.IsInitiallyType1).ForEach(x => x.Type1Confirmed = x.IsInitiallyType1);

            Debug.Assert(attachments.All(x => x.Type1Confirmed || x.Type2Confirmed));

            Log.InfoFormat("Обрабатываем подтвержденные квази ОЧ и ищем дополнительные Квази ОЧ.");
            var additionalAttachments = new List<QuasiUPAttachmentHelperObject>();
            foreach (var confirmedAttach in attachments)
            {
                _processConfirmedAttach(confirmedAttach, additionalAttachments, sentence, resultHelpData);
            }

            var finalAttachments = attachments.Concat(additionalAttachments);
            foreach (var attach in finalAttachments)
            {
                resultHelpData.AddOrUpdateCustomRow(attach.GUID
                    , attach.Id //3.2 + 3.6
                    , attach.IsInitiallyType1 // входит ли в 3.6
                    , attach.IsInitiallyType2 // входит ли в 3.2
                    , attach.SourceNr // 102

                    , (attach.Type2Confirmed && !attach.IsAdditional) ? attach.Id : -1 // 3.3
                    , (attach.Type2Confirmed && !attach.IsAdditional) ? attach.SourceNr : -1 // 102.3
                    , (attach.Type2TransofrmedToType1 && !attach.IsAdditional) ? attach.Id : -1 // 3.4
                    , (attach.Type2TransofrmedToType1 && !attach.IsAdditional) ? attach.SourceNr : -1 //102.4

                    , (attach.Type2Confirmed && attach.AddedParent && attach.IsAdditional) ? attach.Id : -1 //9.9
                    , (attach.Type2Confirmed && attach.AddedParent && attach.IsAdditional) ? attach.NewNr : -1 // 108.9
                    , (attach.Type2Confirmed && attach.AddedChildForParent && attach.IsAdditional) ? attach.Id : -1 // 10.9
                    , (attach.Type2Confirmed && attach.AddedChildForParent && attach.IsAdditional) ? attach.NewNr : -1 //109.9

                    , (attach.Type1Confirmed && attach.AddedParent && attach.IsAdditional) ? attach.Id : -1 //9.8
                    , (attach.Type1Confirmed && attach.AddedParent && attach.IsAdditional) ? attach.NewNr : -1 //108.8
                    , (attach.Type1Confirmed && attach.AddedChildForParent && attach.IsAdditional) ? attach.Id : -1 //10.8
                    , (attach.Type1Confirmed && attach.AddedChildForParent && attach.IsAdditional) ? attach.NewNr : -1 //109.8

                    );
            }
        }