View Javadoc

1   package sharin.sql.formatter;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   import java.util.regex.Matcher;
6   import java.util.regex.Pattern;
7   
8   import sharin.util.PropertyUtils;
9   
10  class BasicFormatCommand {
11  
12      private enum Type {
13          NOOP, PRINTE, PRINTD, BEGIN, END, PREPEND;
14  
15          private static final Map<String, Type> nameMap = new HashMap<String, Type>();
16  
17          static {
18  
19              for (Type type : values()) {
20                  nameMap.put(type.name().toLowerCase(), type);
21              }
22          }
23  
24          public static Type find(String name) {
25              return nameMap.get(name);
26          }
27      }
28  
29      private static final Pattern linePattern = Pattern
30              .compile("^(.*)--\\s*([$&#]?)(.*)$");
31  
32      private final Type type;
33  
34      private final String body;
35  
36      private final String expr;
37  
38      private final String escapeChars;
39  
40      public BasicFormatCommand(String line, String escapeChars) {
41          Type type = Type.NOOP;
42          String body = null;
43          String expr = null;
44          Matcher matcher = linePattern.matcher(line);
45  
46          if (matcher.matches()) {
47              body = matcher.group(1).trim();
48              String group2 = matcher.group(2);
49              String group3 = matcher.group(3);
50  
51              if (group2 != null && group2.length() > 0) {
52                  char ch = group2.charAt(0);
53  
54                  if (ch == '$') {
55                      type = Type.PRINTE;
56                      expr = group3.trim();
57  
58                  } else if (ch == '&') {
59                      type = Type.PRINTD;
60                      expr = group3.trim();
61  
62                  } else if (ch == '#') {
63                      String[] typeExpr = group3.split("\\s", 2);
64                      Type t = Type.find(typeExpr[0]);
65  
66                      if (t != null) {
67                          type = t;
68  
69                          if (typeExpr.length > 1) {
70                              expr = typeExpr[1];
71                          }
72                      }
73                  }
74              }
75  
76          } else {
77              body = line.trim();
78          }
79  
80          this.type = type;
81          this.body = body;
82          this.expr = expr;
83          this.escapeChars = escapeChars;
84      }
85  
86      public void execute(Object context, BasicResultBuffer resultBuffer) {
87          String line = null;
88          Object value = null;
89  
90          switch (type) {
91          case PRINTE:
92              value = PropertyUtils.getNestedPropertyValue(context, expr);
93  
94              if (value != null) {
95                  resultBuffer.flush();
96              }
97  
98              if (value == null
99                      && !PropertyUtils.hasNestedProperty(context, expr)) {
100                 line = body;
101 
102             } else {
103                 line = convertValue(value);
104             }
105 
106             break;
107 
108         case PRINTD:
109             Object token = PropertyUtils.getNestedPropertyValue(context, expr);
110 
111             if (token != null) {
112                 resultBuffer.flush();
113             }
114 
115             if (token == null
116                     && !PropertyUtils.hasNestedProperty(context, expr)) {
117                 line = body;
118 
119             } else {
120 
121                 if (token instanceof Object[]) {
122                     Object[] tokens = (Object[]) token;
123                     Object[] values = new Object[tokens.length];
124 
125                     for (int i = 0; i < tokens.length; i++) {
126                         values[i] = new Direct(tokens[i]);
127                     }
128 
129                     value = values;
130 
131                 } else {
132                     value = new Direct(token);
133                 }
134 
135                 line = convertValue(value);
136             }
137 
138             break;
139 
140         case BEGIN:
141             resultBuffer.begin();
142             resultBuffer.append(body);
143             break;
144 
145         case END:
146             resultBuffer.append(body);
147             resultBuffer.end();
148             break;
149 
150         case PREPEND:
151             resultBuffer.prepend(body);
152             break;
153 
154         default:
155             line = body;
156             break;
157         }
158 
159         if (line != null && line.length() > 0) {
160             resultBuffer.append(line);
161         }
162     }
163 
164     private String convertValue(Object value) {
165 
166         if (value == null) {
167             return "null";
168 
169         } else if (value instanceof String) {
170             return convertString((String) value);
171 
172         } else if (value instanceof Number) {
173             return value.toString();
174 
175         } else if (value instanceof Direct) {
176             return value.toString();
177 
178         } else if (value instanceof Object[]) {
179             Object[] values = (Object[]) value;
180             StringBuilder builder = new StringBuilder();
181             int len = values.length;
182 
183             if (len > 0) {
184                 builder.append(convertValue(values[0]));
185 
186                 for (int i = 1; i < len; i++) {
187                     builder.append(", ");
188                     builder.append(convertValue(values[i]));
189                 }
190             }
191 
192             return builder.toString();
193         }
194 
195         return convertString(value.toString());
196     }
197 
198     private String convertString(String s) {
199         StringBuilder builder = new StringBuilder();
200         builder.append('\'');
201 
202         for (int i = 0; i < s.length(); i++) {
203             char ch = s.charAt(i);
204 
205             if (escapeChars.indexOf(ch) != -1) {
206                 builder.append(ch);
207             }
208 
209             builder.append(ch);
210         }
211 
212         builder.append('\'');
213         return builder.toString();
214     }
215 }