string getExactCandidate(ContractNoteTemplateFieldCandidate fieldCandidate, string valueCandidate)
        {
            string[] values     = valueCandidate.Split((string[])null, StringSplitOptions.RemoveEmptyEntries);
            int      startIndex = fieldCandidate.startIndex < 0 ? values.Length + fieldCandidate.startIndex : fieldCandidate.startIndex;
            int      endIndex   = fieldCandidate.endIndex < 0 ? values.Length + fieldCandidate.endIndex : fieldCandidate.endIndex;

            if (startIndex < 0 || startIndex >= values.Length || endIndex < 0 || endIndex >= values.Length || startIndex > endIndex)
            {
                return(null);
            }

            string candidate = values[startIndex];

            for (int i = startIndex + 1; i <= endIndex; i++)
            {
                candidate += " " + values[i];
            }
            return(candidate);
        }
        public string getCandidate(ContractNoteTemplateFieldCandidate fieldCandidate, List <Word> wordList)
        {
            if (!ContractNote.isEqual(fieldCandidate.key, word))
            {
                return(null);
            }

            string referenceWord = findAdjacencyWord(fieldCandidate, wordList, fieldCandidate.referenceDirection);

            if (referenceWord == null)
            {
                return(null);
            }
            if (!referenceWord.Equals("NULL") && !ContractNote.isPrefix(fieldCandidate.referenceFieldPrefix, referenceWord))
            {
                return(null);
            }

            return(findAdjacencyWord(fieldCandidate, wordList, fieldCandidate.valueDirection, false));
        }
        string findAdjacencyWord(ContractNoteTemplateFieldCandidate fieldCandidate, List <Word> wordList, string route, bool isReferenceWord = true)
        {
            if (route.Length == 0)
            {
                if (isReferenceWord)
                {
                    return(word);
                }
                string exactCandidate = getExactCandidate(fieldCandidate, word);
                return(ContractNoteTemplateField.isValidCandidate(exactCandidate) ? exactCandidate : null);
            }
            char direction = route[0];
            int  repeatCount = 0, adjacencyNo;

            for (int i = 0; i < route.Length; i++)
            {
                if (direction != route[i])
                {
                    break;
                }
                repeatCount++;
            }
            for (int i = 1; i <= repeatCount; i++)
            {
                switch (direction)
                {
                case 'I':
                    return("NULL");

                case 'U':
                    if (i > upList.Count)
                    {
                        continue;
                    }
                    adjacencyNo = upList[i - 1]; break;

                case 'L':
                    if (i > leftList.Count)
                    {
                        continue;
                    }
                    adjacencyNo = leftList[i - 1]; break;

                case 'D':
                    if (i > downList.Count)
                    {
                        continue;
                    }
                    adjacencyNo = downList[i - 1]; break;

                case 'R':
                    if (i > rightList.Count)
                    {
                        continue;
                    }
                    adjacencyNo = rightList[i - 1]; break;

                case 'S':
                    adjacencyNo = -1; break;

                default:
                    continue;
                }
                if (adjacencyNo == -1)
                {
                    return(word);
                }
                string adjacencyWord = wordList[adjacencyNo].findAdjacencyWord(fieldCandidate, wordList, route.Substring(i), isReferenceWord);
                if (adjacencyWord != null)
                {
                    return(adjacencyWord);
                }
            }
            return(null);
        }