public ExchangeAttribute parse(final String valueString) {
        final List<ExchangeAttribute> attributes = new ArrayList<>();
        int pos = 0;
        int state = 0; //0 = literal, 1 = %, 2 = %{, 3 = $, 4 = ${
        for (int i = 0; i < valueString.length(); ++i) {
            char c = valueString.charAt(i);
            switch (state) {
                case 0: {
                    if (c == '%' || c == '$') {
                        if (pos != i) {
                            attributes.add(wrap(parseSingleToken(valueString.substring(pos, i))));
                            pos = i;
                        }
                        if (c == '%') {
                            state = 1;
                        } else {
                            state = 3;
                        }
                    }
                    break;
                }
                case 1: {
                    if (c == '{') {
                        state = 2;
                    } else if (c == '%') {
                        //literal percent
                        attributes.add(wrap(new ConstantExchangeAttribute("%")));
                        pos = i + 1;
                        state = 0;
                    } else {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 2: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 3: {
                    if (c == '{') {
                        state = 4;
                    } else if (c == '$') {
                        //literal dollars
                        attributes.add(wrap(new ConstantExchangeAttribute("$")));
                        pos = i + 1;
                        state = 0;
                    } else {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 4: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }

            }
        }
        switch (state) {
            case 0:
            case 1:
            case 3:{
                if(pos != valueString.length()) {
                    attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
                }
                break;
            }
            case 2:
            case 4: {
                throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
            }
        }
        if(attributes.size() == 1) {
            return attributes.get(0);
        }
        return new CompositeExchangeAttribute(attributes.toArray(new ExchangeAttribute[attributes.size()]));
    }
public ExchangeAttribute parse ( final String valueString ) { final List < ExchangeAttribute > attributes = new ArrayList < > ( ) ; int pos = 0 ; int state = 0 ; for ( int i = 0 ; i < valueString . length ( ) ; ++ i ) { char c = valueString . charAt ( i ) ; switch ( state ) { case 0 : { if ( c == '%' || c == '$' ) { if ( pos != i ) { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos , i ) ) ) ) ; pos = i ; } if ( c == '%' ) { state = 1 ; } else { state = 3 ; } } break ; } case 1 : { if ( c == '{' ) { state = 2 ; } else if ( c == '%' ) { attributes . add ( wrap ( new ConstantExchangeAttribute ( "%" ) ) ) ; pos = i + 1 ; state = 0 ; } else { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos , i + 1 ) ) ) ) ; pos = i + 1 ; state = 0 ; } break ; } case 2 : { if ( c == '}' ) { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos , i + 1 ) ) ) ) ; pos = i + 1 ; state = 0 ; } break ; } case 3 : { if ( c == '{' ) { state = 4 ; } else if ( c == '$' ) { attributes . add ( wrap ( new ConstantExchangeAttribute ( "$" ) ) ) ; pos = i + 1 ; state = 0 ; } else { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos , i + 1 ) ) ) ) ; pos = i + 1 ; state = 0 ; } break ; } case 4 : { if ( c == '}' ) { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos , i + 1 ) ) ) ) ; pos = i + 1 ; state = 0 ; } break ; } } } switch ( state ) { case 0 : case 1 : case 3 : { if ( pos != valueString . length ( ) ) { attributes . add ( wrap ( parseSingleToken ( valueString . substring ( pos ) ) ) ) ; } break ; } case 2 : case 4 : { throw UndertowMessages . MESSAGES . mismatchedBraces ( valueString ) ; } } if ( attributes . size ( ) == 1 ) { return attributes . get ( 0 ) ; } return new CompositeExchangeAttribute ( attributes . toArray ( new ExchangeAttribute [ attributes . size ( ) ] ) ) ; }
Parses the provided value string, and turns it into a list of exchange attributes.
<p>
Tokens are created according to the following rules:
<p>
%a - % followed by single character. %% is an escape for a literal %
%{.*}a? - % plus curly braces with any amount of content inside, followed by an optional character
${.*} - $ followed by a curly braces to reference an item from the predicate context

@param valueString
@return