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 }