001    package org.apache.maven.scm.provider.accurev.util;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *    http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.HashMap;
023    import java.util.Map;
024    
025    /**
026     * @author ggardner
027     */
028    public final class QuotedPropertyParser
029    {
030    
031        private QuotedPropertyParser()
032        {
033    
034        }
035    
036        public static Map<String, String> parse( CharSequence seq )
037        {
038            Map<String, String> hashMap = new HashMap<String, String>();
039    
040            parse( seq, hashMap );
041            return hashMap;
042        }
043    
044        public static void parse( CharSequence string, Map<? super String, ? super String> propertyMap )
045        {
046    
047            QuotedParseState state = QuotedParseState.KEY;
048            char quote = '\0';
049            StringBuilder buffer = new StringBuilder();
050            String propertyKey = "";
051    
052            int i = 0; // where we are up to in the scan
053            int pos = 0; // where we have consumed into the buffer
054            while ( i < string.length() )
055            {
056                char current = string.charAt( i );
057                switch ( state )
058                {
059                    case KEY:
060                        switch ( current )
061                        {
062                            case '"':
063                            case '\'':
064                                quote = current;
065                                state = QuotedParseState.IN_QUOTED_KEY;
066                                if ( i >= pos )
067                                {
068                                    buffer.append( string.subSequence( pos, i ) );
069                                }
070                                pos = i + 1;
071                                break;
072                            case '=':
073                                if ( i >= pos )
074                                {
075                                    buffer.append( string.subSequence( pos, i ) );
076                                }
077                                propertyKey = buffer.toString();
078                                buffer = new StringBuilder();
079                                state = QuotedParseState.VALUE;
080                                pos = i + 1;
081                                break;
082                        }
083                        break;
084    
085                    case VALUE:
086                        switch ( current )
087                        {
088                            case '"':
089                            case '\'':
090                                quote = current;
091                                state = QuotedParseState.IN_QUOTED_VALUE;
092                                if ( i >= pos )
093                                {
094                                    buffer.append( string.subSequence( pos, i ) );
095                                }
096                                pos = i + 1;
097                                break;
098                            case '&':
099                                if ( i >= pos )
100                                {
101                                    buffer.append( string.subSequence( pos, i ) );
102                                }
103                                propertyMap.put( propertyKey, buffer.toString() );
104                                pos = i + 1;
105                                buffer = new StringBuilder();
106                                state = QuotedParseState.KEY;
107                                break;
108                            default:
109                        }
110    
111                        break;
112                    case IN_QUOTED_KEY:
113                    case IN_QUOTED_VALUE:
114                        if ( current == quote )
115                        {
116                            state =
117                                ( state == QuotedParseState.IN_QUOTED_KEY ) ? QuotedParseState.KEY : QuotedParseState.VALUE;
118                            if ( i >= pos )
119                            {
120                                buffer.append( string.subSequence( pos, i ) );
121                            }
122                            pos = i + 1;
123                        }
124                        break;
125                    default:
126                        break;
127                }
128    
129                i++;
130            }
131    
132            if ( state == QuotedParseState.VALUE )
133            {
134                if ( i >= pos )
135                {
136                    buffer.append( string.subSequence( pos, i ) );
137                }
138                propertyMap.put( propertyKey, buffer.toString() );
139            }
140        }
141    
142        // Has to be down here to avoid a QDOX exception
143        public static enum QuotedParseState
144        {
145            KEY, IN_QUOTED_KEY, IN_QUOTED_VALUE, VALUE
146        }
147    
148    }