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 }