public Template create(String template) {
        if (cache.containsKey(template)) {
            return cache.get(template);
        } else {
            Matcher m = elementPattern.matcher(template);
            final List<Element> elements = new ArrayList<>();
            int end = 0;
            while (m.find()) {
                if (m.start() > end) {
                    elements.add(new Template.StaticText(template.substring(end, m.start())));
                }
                String premodifiers = m.group(1).toLowerCase(Locale.ENGLISH);
                int index = Integer.parseInt(m.group(2));
                String postmodifiers = m.group(6).toLowerCase(Locale.ENGLISH);
                boolean asString = false;
                Function<Object, Object> transformer = null;
                switch (premodifiers.length()) {
                    case 1:
                        transformer = toEndsWithViaLike;
                        break;
                    case 2:
                        transformer = toEndsWithViaLikeLower;
                        break;
                }
                switch (postmodifiers.length()) {
                    case 1:
                        switch (postmodifiers.charAt(0)) {
                            case '%':
                                if (transformer == null) {
                                    transformer = toStartsWithViaLike;
                                } else {
                                    transformer = toContainsViaLike;
                                }
                                break;
                            case 'l':
                                transformer = toLowerCase;
                                break;
                            case 'u':
                                transformer = toUpperCase;
                                break;
                            case 's':
                                asString = true;
                                break;
                        }
                        break;
                    case 2:
                        if (transformer == null) {
                            transformer = toStartsWithViaLikeLower;
                        } else {
                            transformer = toContainsViaLikeLower;
                        }
                        break;
                }
                if (m.group(4) != null) {
                    Operator operator = OPERATORS.get(m.group(3));
                    int index2 = Integer.parseInt(m.group(4));
                    elements.add(new Template.Operation(index, index2, operator, asString));
                } else if (m.group(5) != null) {
                    Operator operator = OPERATORS.get(m.group(3));
                    Number number;
                    if (m.group(5).contains(".")) {
                        number = new BigDecimal(m.group(5));
                    } else {
                        number = Integer.valueOf(m.group(5));
                    }
                    elements.add(new Template.OperationConst(index, number, operator, asString));
                } else if (asString) {
                    elements.add(new Template.AsString(index));
                } else if (transformer != null) {
                    elements.add(new Template.Transformed(index, transformer));
                } else {
                    elements.add(new Template.ByIndex(index));
                }
                end = m.end();
            }
            if (end < template.length()) {
                elements.add(new Template.StaticText(template.substring(end)));
            }
            Template rv = new Template(template, CollectionUtils.unmodifiableList(elements));
            cache.put(template, rv);
            return rv;
        }
    }
{@code TemplateFactory} is a factory for {@link Template} instances

@author tiwe
querydsl-core/src/main/java/com/querydsl/core/types/TemplateFactory.java