chatterbox-imap/chatterbox-imap-impl/src/main/java/org/apache/tomee/chatterbox/imap/adapter/Template.java [28:383]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class Template {

    public static final String LIMITED_REGEX_SUFFIX = "(/.*)?";
    public static final String FINAL_MATCH_GROUP = "FINAL_MATCH_GROUP";
    private static final String DEFAULT_PATH_VARIABLE_REGEX = "([^/]+?)";
    private static final String CHARACTERS_TO_ESCAPE = ".*+$()";

    private final String template;
    private final List<String> variables = new ArrayList<String>();
    private final List<String> customVariables = new ArrayList<String>();
    private final Pattern templateRegexPattern;
    private final String literals;
    private final List<UriChunk> uriChunks;

    public Template(final String theTemplate) {
        template = theTemplate;
        final StringBuilder literalChars = new StringBuilder();
        final StringBuilder patternBuilder = new StringBuilder();
        final CurlyBraceTokenizer tok = new CurlyBraceTokenizer(template);
        uriChunks = new ArrayList<>();
        while (tok.hasNext()) {
            final String templatePart = tok.next();
            final UriChunk chunk = UriChunk.createUriChunk(templatePart);
            uriChunks.add(chunk);
            if (chunk instanceof Literal) {
                final String substr = escapeCharacters(chunk.getValue());
                literalChars.append(substr);
                patternBuilder.append(substr);
            } else if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                variables.add(var.getName());
                if (var.getPattern() != null) {
                    customVariables.add(var.getName());
                    patternBuilder.append('(');
                    patternBuilder.append(var.getPattern());
                    patternBuilder.append(')');
                } else {
                    patternBuilder.append(DEFAULT_PATH_VARIABLE_REGEX);
                }
            }
        }
        literals = literalChars.toString();

        final int endPos = patternBuilder.length() - 1;
        final boolean endsWithSlash = (endPos >= 0) && patternBuilder.charAt(endPos) == '/';
        if (endsWithSlash) {
            patternBuilder.deleteCharAt(endPos);
        }
        patternBuilder.append(LIMITED_REGEX_SUFFIX);

        templateRegexPattern = Pattern.compile(patternBuilder.toString());
    }

    private static String escapeCharacters(final String expression) {
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < expression.length(); i++) {
            final char ch = expression.charAt(i);
            sb.append(isReservedCharacter(ch) ? "\\" + ch : ch);
        }
        return sb.toString();
    }

    private static boolean isReservedCharacter(final char ch) {
        return CHARACTERS_TO_ESCAPE.indexOf(ch) != -1;
    }

    public String getLiteralChars() {
        return literals;
    }

    public String getValue() {
        return template;
    }

    public String getPatternValue() {
        return templateRegexPattern.toString();
    }

    public List<String> getVariables() {
        return Collections.unmodifiableList(variables);
    }

    public List<String> getCustomVariables() {
        return Collections.unmodifiableList(customVariables);
    }

    public boolean match(final String uri, final Map<String, List<String>> templateVariableToValue) {

        if (uri == null) {
            return (templateRegexPattern == null);
        }

        if (templateRegexPattern == null) {
            return false;
        }

        Matcher m = templateRegexPattern.matcher(uri);
        if (!m.matches()) {
            return false;
        }

        // Assign the matched template values to template variables
        final int groupCount = m.groupCount();

        int i = 1;
        for (final String name : variables) {
            while (i <= groupCount) {
                final String value = m.group(i++);
                if ((value == null || value.length() == 0 && i < groupCount)
                        && variables.size() + 1 < groupCount) {
                    continue;
                }

                if (templateVariableToValue.get(name) == null) {
                    templateVariableToValue.put(name, new ArrayList<>());
                }

                templateVariableToValue.get(name).add(value);
                break;
            }
        }
        // The right hand side value, might be used to further resolve
        // sub-resources.

        String finalGroup = m.group(groupCount);
        if (finalGroup == null) {
            finalGroup = "";
        }

        templateVariableToValue.put(FINAL_MATCH_GROUP, Collections.singletonList(finalGroup));
        return true;
    }

    public String substitute(final List<String> values) throws IllegalArgumentException {
        if (values == null) {
            throw new IllegalArgumentException("values is null");
        }
        final Iterator<String> iter = values.iterator();
        final StringBuilder sb = new StringBuilder();
        for (final UriChunk chunk : uriChunks) {
            if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                if (iter.hasNext()) {
                    final String value = iter.next();
                    if (!var.matches(value)) {
                        throw new IllegalArgumentException("Value '" + value + "' does not match variable "
                                + var.getName() + " with value "
                                + var.getPattern());
                    }
                    sb.append(value);
                } else {
                    sb.append(var);
                }
            } else {
                sb.append(chunk);
            }
        }
        return sb.toString();
    }

    String substitute(final Map<String, ?> valuesMap) throws IllegalArgumentException {
        return this.substitute(valuesMap, Collections.<String>emptySet(), false);
    }

    public String substitute(final Map<String, ?> valuesMap,
                             final Set<String> encodePathSlashVars,
                             final boolean allowUnresolved) throws IllegalArgumentException {
        if (valuesMap == null) {
            throw new IllegalArgumentException("valuesMap is null");
        }
        final StringBuilder sb = new StringBuilder();
        for (final UriChunk chunk : uriChunks) {
            if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                final Object value = valuesMap.get(var.getName());
                if (value != null) {
                    String sval = value.toString();
                    if (!var.matches(sval)) {
                        throw new IllegalArgumentException("Value '" + sval + "' does not match variable "
                                + var.getName() + " with value "
                                + var.getPattern());
                    }
                    if (encodePathSlashVars.contains(var.getName())) {
                        sval = sval.replaceAll("/", "%2F");
                    }
                    sb.append(sval);
                } else if (allowUnresolved) {
                    sb.append(chunk);
                } else {
                    throw new IllegalArgumentException("Template variable " + var.getName()
                            + " has no matching value");
                }
            } else {
                sb.append(chunk);
            }
        }
        return sb.toString();
    }

    private abstract static class UriChunk {
        public static UriChunk createUriChunk(final String uriChunk) {
            if (uriChunk == null || "".equals(uriChunk)) {
                throw new IllegalArgumentException("uriChunk is empty");
            }
            UriChunk uriChunkRepresentation = Variable.create(uriChunk);
            if (uriChunkRepresentation == null) {
                uriChunkRepresentation = Literal.create(uriChunk);
            }
            return uriChunkRepresentation;
        }

        public abstract String getValue();

        @Override
        public String toString() {
            return getValue();
        }
    }

    private static final class Literal extends UriChunk {
        private String value;

        private Literal() {
            // empty constructor
        }

        public static Literal create(final String uriChunk) {
            if (uriChunk == null || "".equals(uriChunk)) {
                throw new IllegalArgumentException("uriChunk is empty");
            }
            final Literal literal = new Literal();
            literal.value = uriChunk;
            return literal;
        }

        @Override
        public String getValue() {
            return value;
        }

    }

    private static final class Variable extends UriChunk {
        private static final Pattern VARIABLE_PATTERN = Pattern.compile("(\\w[-\\w\\.]*[ ]*)(\\:(.+))?");
        private String name;
        private Pattern pattern;

        private Variable() {
            // empty constructor
        }

        public static Variable create(String uriChunk) {
            final Variable newVariable = new Variable();
            if (uriChunk == null || "".equals(uriChunk)) {
                return null;
            }
            if (CurlyBraceTokenizer.insideBraces(uriChunk)) {
                uriChunk = CurlyBraceTokenizer.stripBraces(uriChunk).trim();
                final Matcher matcher = VARIABLE_PATTERN.matcher(uriChunk);
                if (matcher.matches()) {
                    newVariable.name = matcher.group(1).trim();
                    if (matcher.group(2) != null && matcher.group(3) != null) {
                        final String patternExpression = matcher.group(3).trim();
                        newVariable.pattern = Pattern.compile(patternExpression);
                    }
                    return newVariable;
                }
            }
            return null;
        }

        public String getName() {
            return name;
        }

        public String getPattern() {
            return pattern != null ? pattern.pattern() : null;
        }

        public boolean matches(final String value) {
            if (pattern == null) {
                return true;
            } else {
                return pattern.matcher(value).matches();
            }
        }

        @Override
        public String getValue() {
            if (pattern != null) {
                return "{" + name + ":" + pattern + "}";
            } else {
                return "{" + name + "}";
            }
        }
    }

    static class CurlyBraceTokenizer {

        private final List<String> tokens = new ArrayList<String>();
        private int tokenIdx;

        CurlyBraceTokenizer(final String string) {
            boolean outside = true;
            int level = 0;
            int lastIdx = 0;
            int idx;
            for (idx = 0; idx < string.length(); idx++) {
                if (string.charAt(idx) == '{') {
                    if (outside) {
                        if (lastIdx < idx) {
                            tokens.add(string.substring(lastIdx, idx));
                        }
                        lastIdx = idx;
                        outside = false;
                    } else {
                        level++;
                    }
                } else if (string.charAt(idx) == '}' && !outside) {
                    if (level > 0) {
                        level--;
                    } else {
                        if (lastIdx < idx) {
                            tokens.add(string.substring(lastIdx, idx + 1));
                        }
                        lastIdx = idx + 1;
                        outside = true;
                    }
                }
            }
            if (lastIdx < idx) {
                tokens.add(string.substring(lastIdx, idx));
            }
        }

        public static boolean insideBraces(final String token) {
            return token.charAt(0) == '{' && token.charAt(token.length() - 1) == '}';
        }

        public static String stripBraces(final String token) {
            if (insideBraces(token)) {
                return token.substring(1, token.length() - 1);
            } else {
                return token;
            }
        }

        public boolean hasNext() {
            return tokens.size() > tokenIdx;
        }

        public String next() {
            if (hasNext()) {
                return tokens.get(tokenIdx++);
            } else {
                throw new IllegalStateException("no more elements");
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



chatterbox-xmpp/chatterbox-xmpp-impl/src/main/java/org/apache/tomee/chatterbox/xmpp/impl/Template.java [28:383]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class Template {

    public static final String LIMITED_REGEX_SUFFIX = "(/.*)?";
    public static final String FINAL_MATCH_GROUP = "FINAL_MATCH_GROUP";
    private static final String DEFAULT_PATH_VARIABLE_REGEX = "([^/]+?)";
    private static final String CHARACTERS_TO_ESCAPE = ".*+$()";

    private final String template;
    private final List<String> variables = new ArrayList<String>();
    private final List<String> customVariables = new ArrayList<String>();
    private final Pattern templateRegexPattern;
    private final String literals;
    private final List<UriChunk> uriChunks;

    public Template(final String theTemplate) {
        template = theTemplate;
        final StringBuilder literalChars = new StringBuilder();
        final StringBuilder patternBuilder = new StringBuilder();
        final CurlyBraceTokenizer tok = new CurlyBraceTokenizer(template);
        uriChunks = new ArrayList<>();
        while (tok.hasNext()) {
            final String templatePart = tok.next();
            final UriChunk chunk = UriChunk.createUriChunk(templatePart);
            uriChunks.add(chunk);
            if (chunk instanceof Literal) {
                final String substr = escapeCharacters(chunk.getValue());
                literalChars.append(substr);
                patternBuilder.append(substr);
            } else if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                variables.add(var.getName());
                if (var.getPattern() != null) {
                    customVariables.add(var.getName());
                    patternBuilder.append('(');
                    patternBuilder.append(var.getPattern());
                    patternBuilder.append(')');
                } else {
                    patternBuilder.append(DEFAULT_PATH_VARIABLE_REGEX);
                }
            }
        }
        literals = literalChars.toString();

        final int endPos = patternBuilder.length() - 1;
        final boolean endsWithSlash = (endPos >= 0) && patternBuilder.charAt(endPos) == '/';
        if (endsWithSlash) {
            patternBuilder.deleteCharAt(endPos);
        }
        patternBuilder.append(LIMITED_REGEX_SUFFIX);

        templateRegexPattern = Pattern.compile(patternBuilder.toString());
    }

    private static String escapeCharacters(final String expression) {
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < expression.length(); i++) {
            final char ch = expression.charAt(i);
            sb.append(isReservedCharacter(ch) ? "\\" + ch : ch);
        }
        return sb.toString();
    }

    private static boolean isReservedCharacter(final char ch) {
        return CHARACTERS_TO_ESCAPE.indexOf(ch) != -1;
    }

    public String getLiteralChars() {
        return literals;
    }

    public String getValue() {
        return template;
    }

    public String getPatternValue() {
        return templateRegexPattern.toString();
    }

    public List<String> getVariables() {
        return Collections.unmodifiableList(variables);
    }

    public List<String> getCustomVariables() {
        return Collections.unmodifiableList(customVariables);
    }

    public boolean match(final String uri, final Map<String, List<String>> templateVariableToValue) {

        if (uri == null) {
            return (templateRegexPattern == null);
        }

        if (templateRegexPattern == null) {
            return false;
        }

        Matcher m = templateRegexPattern.matcher(uri);
        if (!m.matches()) {
            return false;
        }

        // Assign the matched template values to template variables
        final int groupCount = m.groupCount();

        int i = 1;
        for (final String name : variables) {
            while (i <= groupCount) {
                final String value = m.group(i++);
                if ((value == null || value.length() == 0 && i < groupCount)
                        && variables.size() + 1 < groupCount) {
                    continue;
                }

                if (templateVariableToValue.get(name) == null) {
                    templateVariableToValue.put(name, new ArrayList<>());
                }

                templateVariableToValue.get(name).add(value);
                break;
            }
        }
        // The right hand side value, might be used to further resolve
        // sub-resources.

        String finalGroup = m.group(groupCount);
        if (finalGroup == null) {
            finalGroup = "";
        }

        templateVariableToValue.put(FINAL_MATCH_GROUP, Collections.singletonList(finalGroup));
        return true;
    }

    public String substitute(final List<String> values) throws IllegalArgumentException {
        if (values == null) {
            throw new IllegalArgumentException("values is null");
        }
        final Iterator<String> iter = values.iterator();
        final StringBuilder sb = new StringBuilder();
        for (final UriChunk chunk : uriChunks) {
            if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                if (iter.hasNext()) {
                    final String value = iter.next();
                    if (!var.matches(value)) {
                        throw new IllegalArgumentException("Value '" + value + "' does not match variable "
                                + var.getName() + " with value "
                                + var.getPattern());
                    }
                    sb.append(value);
                } else {
                    sb.append(var);
                }
            } else {
                sb.append(chunk);
            }
        }
        return sb.toString();
    }

    String substitute(final Map<String, ?> valuesMap) throws IllegalArgumentException {
        return this.substitute(valuesMap, Collections.<String>emptySet(), false);
    }

    public String substitute(final Map<String, ?> valuesMap,
                             final Set<String> encodePathSlashVars,
                             final boolean allowUnresolved) throws IllegalArgumentException {
        if (valuesMap == null) {
            throw new IllegalArgumentException("valuesMap is null");
        }
        final StringBuilder sb = new StringBuilder();
        for (final UriChunk chunk : uriChunks) {
            if (chunk instanceof Variable) {
                final Variable var = (Variable) chunk;
                final Object value = valuesMap.get(var.getName());
                if (value != null) {
                    String sval = value.toString();
                    if (!var.matches(sval)) {
                        throw new IllegalArgumentException("Value '" + sval + "' does not match variable "
                                + var.getName() + " with value "
                                + var.getPattern());
                    }
                    if (encodePathSlashVars.contains(var.getName())) {
                        sval = sval.replaceAll("/", "%2F");
                    }
                    sb.append(sval);
                } else if (allowUnresolved) {
                    sb.append(chunk);
                } else {
                    throw new IllegalArgumentException("Template variable " + var.getName()
                            + " has no matching value");
                }
            } else {
                sb.append(chunk);
            }
        }
        return sb.toString();
    }

    private abstract static class UriChunk {
        public static UriChunk createUriChunk(final String uriChunk) {
            if (uriChunk == null || "".equals(uriChunk)) {
                throw new IllegalArgumentException("uriChunk is empty");
            }
            UriChunk uriChunkRepresentation = Variable.create(uriChunk);
            if (uriChunkRepresentation == null) {
                uriChunkRepresentation = Literal.create(uriChunk);
            }
            return uriChunkRepresentation;
        }

        public abstract String getValue();

        @Override
        public String toString() {
            return getValue();
        }
    }

    private static final class Literal extends UriChunk {
        private String value;

        private Literal() {
            // empty constructor
        }

        public static Literal create(final String uriChunk) {
            if (uriChunk == null || "".equals(uriChunk)) {
                throw new IllegalArgumentException("uriChunk is empty");
            }
            final Literal literal = new Literal();
            literal.value = uriChunk;
            return literal;
        }

        @Override
        public String getValue() {
            return value;
        }

    }

    private static final class Variable extends UriChunk {
        private static final Pattern VARIABLE_PATTERN = Pattern.compile("(\\w[-\\w\\.]*[ ]*)(\\:(.+))?");
        private String name;
        private Pattern pattern;

        private Variable() {
            // empty constructor
        }

        public static Variable create(String uriChunk) {
            final Variable newVariable = new Variable();
            if (uriChunk == null || "".equals(uriChunk)) {
                return null;
            }
            if (CurlyBraceTokenizer.insideBraces(uriChunk)) {
                uriChunk = CurlyBraceTokenizer.stripBraces(uriChunk).trim();
                final Matcher matcher = VARIABLE_PATTERN.matcher(uriChunk);
                if (matcher.matches()) {
                    newVariable.name = matcher.group(1).trim();
                    if (matcher.group(2) != null && matcher.group(3) != null) {
                        final String patternExpression = matcher.group(3).trim();
                        newVariable.pattern = Pattern.compile(patternExpression);
                    }
                    return newVariable;
                }
            }
            return null;
        }

        public String getName() {
            return name;
        }

        public String getPattern() {
            return pattern != null ? pattern.pattern() : null;
        }

        public boolean matches(final String value) {
            if (pattern == null) {
                return true;
            } else {
                return pattern.matcher(value).matches();
            }
        }

        @Override
        public String getValue() {
            if (pattern != null) {
                return "{" + name + ":" + pattern + "}";
            } else {
                return "{" + name + "}";
            }
        }
    }

    static class CurlyBraceTokenizer {

        private final List<String> tokens = new ArrayList<String>();
        private int tokenIdx;

        CurlyBraceTokenizer(final String string) {
            boolean outside = true;
            int level = 0;
            int lastIdx = 0;
            int idx;
            for (idx = 0; idx < string.length(); idx++) {
                if (string.charAt(idx) == '{') {
                    if (outside) {
                        if (lastIdx < idx) {
                            tokens.add(string.substring(lastIdx, idx));
                        }
                        lastIdx = idx;
                        outside = false;
                    } else {
                        level++;
                    }
                } else if (string.charAt(idx) == '}' && !outside) {
                    if (level > 0) {
                        level--;
                    } else {
                        if (lastIdx < idx) {
                            tokens.add(string.substring(lastIdx, idx + 1));
                        }
                        lastIdx = idx + 1;
                        outside = true;
                    }
                }
            }
            if (lastIdx < idx) {
                tokens.add(string.substring(lastIdx, idx));
            }
        }

        public static boolean insideBraces(final String token) {
            return token.charAt(0) == '{' && token.charAt(token.length() - 1) == '}';
        }

        public static String stripBraces(final String token) {
            if (insideBraces(token)) {
                return token.substring(1, token.length() - 1);
            } else {
                return token;
            }
        }

        public boolean hasNext() {
            return tokens.size() > tokenIdx;
        }

        public String next() {
            if (hasNext()) {
                return tokens.get(tokenIdx++);
            } else {
                throw new IllegalStateException("no more elements");
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



