# SimpleStringExpression.java

    /*
    *  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
    *
    *  WSO2 Inc. licenses this file to you under the Apache License,
    *  Version 2.0 (the "License"); you may not use this file except
    *  in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *    http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing,
    * software distributed under the License is distributed on an
    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    * KIND, either express or implied.  See the License for the
    * specific language governing permissions and limitations
    * under the License.
    */

    package org.apache.synapse.commons.templates.uri.parser;

    import org.apache.commons.lang.StringUtils;
    import org.apache.synapse.commons.templates.uri.URITemplateException;

    import java.util.Map;
    import java.util.regex.Pattern;

    public class SimpleStringExpression extends Expression {

        private static final String ESCAPE_GEN_DELIMS_ONLY = "synapse.allow.subdelims";
        private static final char[] reserved;

        static {
            String genDelimsOnly = System.getProperty(ESCAPE_GEN_DELIMS_ONLY);
            if (!StringUtils.isEmpty(genDelimsOnly) && (Boolean.parseBoolean(genDelimsOnly))) {
                reserved = new char[]{':', '/', '?', '#', '[', ']', '@'};
            } else {
                reserved = new char[]{
                        ':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='
                };
            }
        }

        public SimpleStringExpression(String token) throws URITemplateException {
            super(token);
        }

        @Override
        String expand(Map<String, String> variables) {
            boolean emptyString = false;
            StringBuffer buffer = new StringBuffer();
            for (Variable var : variableList) {
                String name = var.getName();
                if (variables.containsKey(name)) {
                    if (buffer.length() > 0) {
                        buffer.append(getSeparator());
                    }
                    String value = var.modify(variables.get(name));
                    if ("".equals(value)) {
                        emptyString = true;
                    }
                    buffer.append(encodeValue(value));
                }
            }

            if (buffer.length() == 0 && !emptyString) {
                return null;
            }
            return buffer.toString();
        }

        protected char getSeparator() {
            return ',';
        }

        @Override
        int match(String uriFragment, Map<String, String> variables) {
            int length = uriFragment.length();
            for (int i = 0; i < length; i++) {
                char ch = uriFragment.charAt(i);
                if (isReserved(ch) || (next != null && ch == next.getFirstCharacter())) {
                    if (ch == getSeparator() && variableList.size() > 1) {
                        continue;
                    }

                    if (!setVariables(uriFragment.substring(0, i), variables)) {
                        return -1;
                    }
                    return i;
                } else if (i == length - 1) {
                    if (!setVariables(uriFragment, variables)) {
                        return -1;
                    }
                    return length;
                }
            }
            return 0;
        }

        protected boolean setVariables(String expressionValue, Map<String,String> variables) {
            String separator = Pattern.quote(String.valueOf(getSeparator()));
            String[] values = expressionValue.split(separator);
            int length = values.length;
            if (length > variableList.size()) {
                return false;
            }

            for (int i = 0; i < length; i++) {
                Variable var = variableList.get(i);
                String name = var.getName();
                String finalValue = decodeValue(values[i]);
                if (variables.containsKey(name) && !finalValue.equals(variables.get(name))) {
                    return false;
                }

                if (var.checkModifier(finalValue)) {
                    variables.put(name, finalValue);
                } else {
                    return false;
                }
            }

            if (variableList.size() > length) {
                for (int i = length; i < variableList.size(); i++) {
                    Variable var = variableList.get(i);
                    String name = var.getName();
                    String finalValue = "";
                    if (variables.containsKey(name) && !finalValue.equals(variables.get(name))) {
                        return false;
                    }

                    if (var.checkModifier(finalValue)) {
                        variables.put(name, finalValue);
                    } else {
                        return false;
                    }
                }
            }
            return true;
        }

        @Override
        char getFirstCharacter() {
            return '\u0001';
        }

        protected boolean isReserved(char ch) {
            for (char reservedChar : reserved) {
                if (ch == reservedChar) {
                    return true;
                }
            }
            return false;
        }
    }