public List<String> searchByKeywords(String str) throws IOException {
        Keywords keywords = new Keywords(str);

        Node root = openRoot().getRootNode();
        
        StringBuilder prefix = new StringBuilder();
        
        for (int i = 0; i < keywords.size();) {
            Integer num = null;
            String joinedTerms = null;
            String joinedTermsLowerCase = null;
            
            for (int numTerms = keywords.size() - i; numTerms > 0; --numTerms) {
                joinedTerms = keywords.join(i, numTerms);
                joinedTermsLowerCase = joinedTerms.toLowerCase();
                if (root.hasWeightInChilds(joinedTermsLowerCase, 0)) {
                    num = numTerms;
                    break;
                }
            }
            
            int matched = 0;
            
            if (num == null) {
                joinedTerms = keywords.join(i, 1);
                joinedTermsLowerCase = joinedTerms.toLowerCase();
                matched = 1;
            }
            else {
                matched = num;
            }

            if (i + matched >= keywords.size()) {
                int prefixLength = prefix.length();
                List<String> lowerCaseResult = root.search(joinedTermsLowerCase, 0);
                List<String> result = new ArrayList<String>(lowerCaseResult.size());
                for (String lowerCaseName : lowerCaseResult) {
                    if (prefixLength > 0) {
                        prefix.append(' ');
                    }
                    prefix.append(root.getTopOriginalName(lowerCaseName, 0));
                    result.add(prefix.toString());
                    prefix.delete(prefixLength, prefix.length());
                }
                return result;
            }
            else {
                if (prefix.length() > 0) {
                    prefix.append(' ');
                }            
                if (num != null) {
                    prefix.append(root.getTopOriginalName(joinedTermsLowerCase, 0));
                }
                else {
                    prefix.append(joinedTerms);
                }
            }
            i += matched;
        }

        return Collections.emptyList();
    }