1 package org.apache.onami.configuration.variables;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static java.lang.String.format;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class AntStyleParser
51 implements Parser
52 {
53
54
55 static final String VAR_START = "${";
56
57 static final int VAR_START_LEN = VAR_START.length();
58
59 static final char VAR_CLOSE = '}';
60
61 static final int VAR_CLOSE_LEN = 1;
62
63 static final char PIPE_SEPARATOR = '|';
64
65 static final int PIPE_SEPARATOR_LEN = 1;
66
67
68
69
70 public Appender parse( String pattern )
71 {
72 List<Appender> appenders = new ArrayList<Appender>();
73 int prev = 0;
74 int pos = 0;
75 while ( ( pos = pattern.indexOf( VAR_START, pos ) ) >= 0 )
76 {
77
78 if ( pos > prev )
79 {
80 appenders.add( new TextAppender( pattern.substring( prev, pos ) ) );
81 }
82
83
84 pos += VAR_START_LEN;
85
86
87
88 int endVariable = pattern.indexOf( VAR_CLOSE, pos );
89 if ( endVariable < 0 )
90 {
91 throw new IllegalArgumentException( format( "Syntax error in property value '%s', missing close bracket '%s' for variable beginning at col %s: '%s'",
92 pattern, VAR_CLOSE, pos - VAR_START_LEN, pattern.substring( pos - VAR_START_LEN ) ) );
93 }
94
95
96 int nextVariable = pattern.indexOf( VAR_START, pos );
97
98 int lastEndVariable = endVariable;
99 boolean hasNested = false;
100 while ( nextVariable >= 0 && nextVariable < endVariable )
101 {
102 hasNested = true;
103 endVariable = pattern.indexOf( VAR_CLOSE, endVariable + VAR_CLOSE_LEN );
104
105 if ( endVariable < 0 )
106 {
107 throw new IllegalArgumentException( format( "Syntax error in property value '%s', missing close bracket '%s' for variable beginning at col %s: '%s'",
108 pattern, VAR_CLOSE, nextVariable, pattern.substring( nextVariable, lastEndVariable ) ) );
109 }
110 nextVariable = pattern.indexOf( VAR_START, nextVariable + VAR_START_LEN );
111 lastEndVariable = endVariable;
112 }
113
114 final String rawKey = pattern.substring( pos - VAR_START_LEN, endVariable + VAR_CLOSE_LEN );
115
116 final String key = pattern.substring( pos, endVariable );
117
118 int pipeIndex = key.indexOf( PIPE_SEPARATOR );
119
120 boolean hasKeyVariables = false;
121 boolean hasDefault = false;
122 boolean hasDefaultVariables = false;
123
124
125 if ( pipeIndex >= 0 )
126 {
127
128 if ( !hasNested )
129 {
130 hasDefault = true;
131 hasDefaultVariables = false;
132 }
133
134
135
136 else
137 {
138 int nextStartKeyVariable = key.indexOf( VAR_START );
139 hasKeyVariables = pipeIndex > nextStartKeyVariable;
140 if ( hasKeyVariables )
141 {
142
143 int nextEndKeyVariable = key.indexOf( VAR_CLOSE, nextStartKeyVariable + VAR_START_LEN );
144 pipeIndex = key.indexOf( PIPE_SEPARATOR, pipeIndex + PIPE_SEPARATOR_LEN );
145 while ( pipeIndex >= 0 && pipeIndex > nextStartKeyVariable )
146 {
147 pipeIndex = key.indexOf( PIPE_SEPARATOR, nextEndKeyVariable + VAR_CLOSE_LEN );
148 nextStartKeyVariable = key.indexOf( VAR_START, nextStartKeyVariable + VAR_START_LEN );
149
150 if ( nextStartKeyVariable < 0 )
151 {
152 break;
153 }
154 nextEndKeyVariable = key.indexOf( VAR_CLOSE, nextEndKeyVariable + VAR_CLOSE_LEN );
155 if ( nextEndKeyVariable < 0 )
156 {
157 throw new IllegalArgumentException( format( "Syntax error in property value '%s', missing close bracket '%s' for variable beginning at col %s: '%s'",
158 pattern, VAR_CLOSE, nextStartKeyVariable, key.substring( nextStartKeyVariable ) ) );
159 }
160 }
161 }
162
163
164
165 if ( pipeIndex >= 0 )
166 {
167 hasDefault = true;
168 hasDefaultVariables = key.indexOf( VAR_START, pipeIndex ) >= 0;
169 }
170
171 }
172 }
173
174
175 else
176 {
177 hasKeyVariables = hasNested;
178 }
179
180
181 String keyPart = null;
182 String defaultPart = null;
183 if ( hasDefault )
184 {
185 keyPart = key.substring( 0, pipeIndex ).trim();
186 defaultPart = key.substring( pipeIndex + PIPE_SEPARATOR_LEN ).trim();
187 }
188 else
189 {
190 keyPart = key.trim();
191 }
192
193 appenders.add( new KeyAppender( this,
194 rawKey,
195 hasKeyVariables ? parse( keyPart ) : new TextAppender( keyPart ),
196 !hasDefault ? null : ( hasDefaultVariables ? parse( defaultPart ) : new TextAppender( defaultPart ) ) ) );
197
198 prev = endVariable + VAR_CLOSE_LEN;
199 pos = prev;
200 }
201
202 if ( prev < pattern.length() )
203 {
204 appenders.add( new TextAppender( pattern.substring( prev ) ) );
205 }
206
207 return appenders.size() == 1 ? appenders.get( 0 ) : new MixinAppender( pattern, appenders );
208 }
209
210 }