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 }