public pattern(XElement patternNode, FlatChainRule ownerRule)
            {
                OwnerRule = ownerRule;

                var nodes = patternNode.GetMultiNodes("./*").ToArray();

                if (nodes.Length < 2)
                {
                    throw (new ArgumentException("Pattern element contains less than 2 items (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                }

                Items = (from node in nodes
                         select new item(node)
                         ).ToArray();
            }
            public action(XElement actionNode, pattern[] patterns, FlatChainRule ownerRule) : base(actionNode)
            {
                OwnerRule = ownerRule;

                SNT = actionNode.AttributeValue2Enum <TonalityType>("SNT");
                CreateNewElementType = actionNode.AttributeValue2Enum <TypeOfXmlElement>("createnewelement");

                ROLE = actionNode.GetAttributeROLE("setattribute_ROLE");
                if (!ROLE.HasValue)
                {
                    var role = actionNode.GetAttribute("determineattribute_ROLE");
                    if (!role.IsEmptyOrNull())
                    {
                        determineattribute_ROLE = role.ToEnum <determine_attribute>();
                    }
                }
                TYPE = actionNode.GetAttributeTYPE("setattribute_TYPE");
                if (!TYPE.HasValue)
                {
                    var type = actionNode.GetAttribute("determineattribute_TYPE");
                    if (!type.IsEmptyOrNull())
                    {
                        determineattribute_TYPE = type.ToEnum <determine_attribute>();
                    }
                }

                foreach (var condition in actionNode.GetMultiNodes("condition")
                         .RevealConfigNodes()
                         )
                {
                    //var a_attributes = condition.GetMultiNodes( "@*[ starts-with( local-name(), 'a' ) ]" ).Cast< XAttribute >().ToArray();
                    var a_attributes = condition.GetAttributeNodes("@*[ starts-with( local-name(), 'a' ) ]").ToArray();

                    if (a_attributes.Except(condition.Attributes()).Any())
                    {
                        throw (new ArgumentException("Action-element has not only a[1,2,3..] attributes (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                    }

                    //for check
                    foreach (var a in a_attributes)
                    {
                        var number = 0;
                        if (!int.TryParse(a.Name.LocalName.Substring(1), out number))
                        {
                            throw (new ArgumentException("Action-element has wrong name-format a[1,2,3..] attribute (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                        }

                        var type = a.Value.TryConvert2Enum <TonalityType>();
                        if (!type.HasValue)
                        {
                            throw (new ArgumentException("Action-element has wrong value in a[1,2,3..] attribute (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                        }
                    }


                    var a_type = from a in a_attributes
                                 let number = int.Parse(a.Name.LocalName.Substring(1))
                                              orderby number
                                              select new
                    {
                        index = number - 1,
                        value = a.Value.ToEnum <TonalityType>()
                    };

                    var sb = new StringBuilder();
                    foreach (var a_ in a_type)
                    {
                        sb.Append(a_.value.ToText() + '|');
                    }
                    _ConditionHashset.Add(sb.ToString());

                    if (Indexies4GettingSNT == null)
                    {
                        Indexies4GettingSNT = a_type.Select(_ => _.index).ToArray();
                    }
                    else
                    {
                        if (Indexies4GettingSNT.Except(a_type.Select(_ => _.index)).Any())
                        {
                            throw (new ArgumentException("Action-element has condition-element with different a[1,2,3..] attributes sets (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                        }
                    }

                    //check corresponding patterns & action @SNT-attribute indexies
                    foreach (var pattern in patterns)
                    {
                        foreach (var i in Indexies4GettingSNT)
                        {
                            if (pattern.Items.Length <= i)
                            {
                                throw (new ArgumentException("a[1,2,3..] has index length more than pattern-item-count (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }

                            var item = pattern.Items[i];
                            switch (item.TypeOfXmlElement)
                            {
                            case TypeOfXmlElement.U:
                            case TypeOfXmlElement.CET:
                                throw (new ArgumentException("U-element & CET-element can't have @SNT-attribute (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }
                        }


                        if (determineattribute_ROLE.HasValue)
                        {
                            var index = extensions.ToIndex(determineattribute_ROLE.Value);
                            if (pattern.Items.Length < index)
                            {
                                throw (new ArgumentException("@determineattribute_ROLE-attribute point to not exists element (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }

                            switch (pattern.Items[index].TypeOfXmlElement)
                            {
                            case TypeOfXmlElement.U:
                            case TypeOfXmlElement.CET:
                                throw (new ArgumentException("@determineattribute_ROLE-attribute can't point on U-element | CET-element (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }
                        }
                        if (determineattribute_TYPE.HasValue)
                        {
                            var index = extensions.ToIndex(determineattribute_TYPE.Value);
                            if (pattern.Items.Length < index)
                            {
                                throw (new ArgumentException("@determineattribute_TYPE-attribute point to not exists element (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }

                            switch (pattern.Items[index].TypeOfXmlElement)
                            {
                            case TypeOfXmlElement.U:
                            case TypeOfXmlElement.CET:
                                throw (new ArgumentException("@determineattribute_TYPE-attribute can't point on U-element | CET-element (rule " + OwnerRule.Id.InSingleQuote() + ')'));
                            }
                        }
                    }
                }
            }