View Javadoc

1   /*
2    * $Id: CommandParserIterator.java,v 1.18 2011/06/16 09:29:41 jbmeslin Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.util;
6   
7   import java.util.ArrayList;
8   import java.util.Iterator;
9   import java.util.LinkedList;
10  import java.util.List;
11  
12  import javax.faces.FacesException;
13  
14  import org.rcfaces.core.validator.IParameter;
15  
16  /**
17   * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
18   * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:41 $
19   */
20  public class CommandParserIterator implements Iterator {
21      private static final String REVISION = "$Revision: 1.18 $";
22  
23      private static final IParameter[] EMPTY_PARAMETERS = new IParameter[0];
24  
25      private final Iterator iterator;
26  
27      public CommandParserIterator(String validatorCommand)
28              throws SyntaxException {
29          this.iterator = parseCommand(validatorCommand);
30      }
31  
32      public boolean hasNext() {
33          return iterator.hasNext();
34      }
35  
36      public Object next() {
37          return nextCommand();
38      }
39  
40      public ICommand nextCommand() {
41          return (ICommand) iterator.next();
42      }
43  
44      public void remove() {
45          iterator.remove();
46      }
47  
48      private Iterator parseCommand(String validatorCommand)
49              throws SyntaxException {
50          char command[] = validatorCommand.toCharArray();
51  
52          List list = new ArrayList();
53  
54          Command cmd = null;
55  
56          for (int i = 0; i < command.length;) {
57              char ch = command[i];
58  
59              if (Character.isJavaIdentifierStart(ch)) {
60                  cmd = new Command();
61                  list.add(cmd);
62  
63                  i = startCommandString(cmd, command, i);
64  
65              } else if (ch == '(') {
66                  if (cmd == null) {
67                      throw new SyntaxException(
68                              "Debut des parametres avant nom de fonction.",
69                              command, i);
70                  }
71                  i = startParameterString(cmd, command, i + 1);
72                  cmd = null;
73  
74              } else if (ch == ';') {
75                  cmd = null;
76                  i++;
77  
78              } else if (Character.isWhitespace(ch)) {
79                  i++;
80  
81              } else {
82                  throw new SyntaxException("Caractere non prevu (ascii="
83                          + ((int) ch) + ") '" + ch + "'.", command, i);
84              }
85          }
86  
87          return list.iterator();
88      }
89  
90      private int startParameterString(Command cmd, char[] command, int i)
91              throws SyntaxException {
92          int start = i;
93          boolean nextParameter = false;
94  
95          for (; i < command.length;) {
96              char ch = command[i];
97  
98              if (ch == ')') {
99                  return i + 1;
100 
101             } else if (Character.isWhitespace(ch)) {
102                 i++;
103                 continue;
104 
105             } else if (ch == '"' || ch == '\'') {
106                 if (nextParameter) {
107                     throw new SyntaxException(
108                             "Mauvais separateur de parametres.", command, i);
109                 }
110 
111                 nextParameter = true;
112 
113                 i = startLitteralString(cmd, command, i);
114 
115             } else if (Character.isDigit(ch)) {
116                 if (nextParameter) {
117                     throw new SyntaxException(
118                             "Mauvais separateur de parametres.", command, i);
119                 }
120                 nextParameter = true;
121                 i = startNumberString(cmd, command, i);
122 
123             } else if (Character.isJavaIdentifierStart(ch)) {
124                 if (nextParameter) {
125                     throw new SyntaxException(
126                             "Mauvais separateur de parametres.", command, i);
127                 }
128                 nextParameter = true;
129                 i = startIdentifierString(cmd, command, i);
130 
131             } else if (ch == ',') {
132                 nextParameter = false;
133                 i++;
134             } else {
135 
136                 throw new SyntaxException("Caractere non prevu.", command, i);
137             }
138 
139         }
140         throw new SyntaxException("Pas de fermeture des parametres.", command,
141                 start);
142     }
143 
144     private int startIdentifierString(Command cmd, char[] command, int i)
145             throws SyntaxException {
146         int start = i;
147 
148         for (; i < command.length; i++) {
149             char ch = command[i];
150 
151             if (Character.isWhitespace(ch) || ch == ',') {
152                 cmd.addParameter(new String(command, start, i - start));
153                 return i;
154             }
155 
156             if (Character.isJavaIdentifierPart(ch)) {
157                 continue;
158             }
159 
160             throw new SyntaxException("Mauvaise syntaxe du nombre.", command,
161                     start);
162         }
163 
164         throw new SyntaxException("La chaine de caractere ne se ferme pas.",
165                 command, start);
166     }
167 
168     private int startNumberString(Command cmd, char[] command, int i)
169             throws SyntaxException {
170         int start = i;
171 
172         for (; i < command.length; i++) {
173             char ch = command[i];
174 
175             if (Character.isDigit(ch) || ch == '.') {
176                 continue;
177             }
178 
179             break;
180         }
181 
182         cmd.addParameter(new String(command, start, i - start));
183         return i;
184     }
185 
186     private int startLitteralString(Command cmd, char[] command, int i)
187             throws SyntaxException {
188         char end = command[i++];
189         int start = i;
190 
191         for (; i < command.length; i++) {
192             char ch = command[i];
193 
194             if (ch == end) {
195                 cmd.addParameter(new String(command, start, i - start));
196                 return i + 1;
197             }
198             if (ch == '\\') {
199                 i++; // ignore le prochain caractere !
200             }
201         }
202 
203         throw new SyntaxException("La chaine de caractere ne se ferme pas.",
204                 command, start);
205     }
206 
207     private int startCommandString(Command cmd, char[] command, int i) {
208         int start = i;
209 
210         for (; i < command.length; i++) {
211             char ch = command[i];
212 
213             if (Character.isJavaIdentifierPart(ch) == false && ch != '.') {
214                 break;
215             }
216         }
217 
218         // meme si c'est la fin: pas d'erreur
219         cmd.setName(new String(command, start, i - start));
220 
221         return i;
222     }
223 
224     /**
225      * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
226      * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:41 $
227      */
228     public interface ICommand {
229         String getName();
230 
231         IParameter[] listParameters();
232     }
233 
234     private static class Command implements ICommand {
235         private static final String REVISION = "$Revision: 1.18 $";
236 
237         private String name;
238 
239         private List parameters;
240 
241         public String getName() {
242             return name;
243         }
244 
245         public void setName(String name) {
246             this.name = name;
247         }
248 
249         public void addParameter(String parameterValue) {
250             if (parameters == null) {
251                 parameters = new LinkedList();
252             }
253             parameters.add(parameterValue);
254         }
255 
256         public IParameter[] listParameters() {
257             if (parameters == null || parameters.size() < 1) {
258                 return EMPTY_PARAMETERS;
259             }
260 
261             IParameter ps[] = new IParameter[parameters.size()];
262             int i = 0;
263             for (Iterator it = parameters.iterator(); it.hasNext();) {
264                 String value = (String) it.next();
265 
266                 ps[i++] = new Parameter(i, value);
267             }
268 
269             return ps;
270         }
271     }
272 
273     private static class Parameter implements IParameter {
274         private static final String REVISION = "$Revision: 1.18 $";
275 
276         private final String name;
277 
278         private final String value;
279 
280         public Parameter(int index, String value) {
281             this.name = "param" + index;
282             this.value = value;
283         }
284 
285         public String getName() {
286             return name;
287         }
288 
289         public String getValue() {
290             return value;
291         }
292 
293     }
294 
295     /**
296      * 
297      * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
298      * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:41 $
299      */
300     public static class SyntaxException extends FacesException {
301 
302         private static final String REVISION = "$Revision: 1.18 $";
303 
304         private static final long serialVersionUID = 2866070330212947352L;
305 
306         private String command;
307 
308         private int position;
309 
310         SyntaxException(String message, char command[], int position) {
311             this(message, new String(command), position);
312         }
313 
314         SyntaxException(String message, String command, int position) {
315             super(message + " [message='" + command + "' position='" + position
316                     + "']", null);
317 
318             this.command = command;
319             this.position = position;
320         }
321 
322         public final String getCommand() {
323             return command;
324         }
325 
326         public final int getPosition() {
327             return position;
328         }
329     }
330 
331 }