package io.ebeaninternal.server.deploy; import java.util.Set; /** * Converts logical property names to database columns. */ public abstract class DeployParser { /** * used to identify sql literal. */ protected static final char SINGLE_QUOTE = '\''; /** * used to identify query named parameters. */ protected static final char COLON = ':'; /** * Used to determine when a column name terminates. */ protected static final char UNDERSCORE = '_'; /** * Used to determine when a column name terminates. */ protected static final char PERIOD = '.'; protected boolean encrypted; protected String source; protected StringBuilder sb; protected int sourceLength; protected int pos; protected String word; protected char wordTerminator; protected abstract String convertWord(); public abstract String getDeployWord(String expression); /** * Return the join includes. */ public abstract Set<String> getIncludes(); public void setEncrypted(boolean encrypted) { this.encrypted = encrypted; } public String parse(String source) { if (source == null) { return null; } pos = -1; this.source = source; this.sourceLength = source.length(); this.sb = new StringBuilder(source.length() + 20); while (nextWord()) { String deployWord = convertWord(); sb.append(deployWord); if (pos < sourceLength) { sb.append(wordTerminator); if (wordTerminator == SINGLE_QUOTE) { readLiteral(); } } } return sb.toString(); } private boolean nextWord() { if (!findWordStart()) { return false; } StringBuilder wordBuffer = new StringBuilder(); wordBuffer.append(source.charAt(pos)); while (++pos < sourceLength) { char ch = source.charAt(pos); if (isWordPart(ch)) { wordBuffer.append(ch); } else { wordTerminator = ch; break; } } word = wordBuffer.toString(); return true; } private boolean findWordStart() { while (++pos < sourceLength) { char ch = source.charAt(pos); if (ch == SINGLE_QUOTE) { // read a literal value and just // append to string builder sb.append(ch); readLiteral(); } else if (ch == COLON) { // read a named parameter // just append to string builder sb.append(ch); readNamedParameter(); } else if (isWordStart(ch)) { // its the start of a word that could // be translated return true; } else { sb.append(ch); } } return false; } /** * Read the rest of a literal value. These do not get translated so are just * read and appended to the string builder. */ private void readLiteral() { while (++pos < sourceLength) { char ch = source.charAt(pos); sb.append(ch); if (ch == SINGLE_QUOTE) { break; } } } /** * Read a named parameter. These are not translated. They will be replaced * by positioned parameters later. */ private void readNamedParameter() { while (++pos < sourceLength) { char ch = source.charAt(pos); sb.append(ch); if (Character.isWhitespace(ch)) { break; } else if (ch == ',') { break; } } } /** * return true if the char is a letter, digit or underscore. */ private boolean isWordPart(char ch) { return Character.isLetterOrDigit(ch) || ch == UNDERSCORE || ch == PERIOD; } private boolean isWordStart(char ch) { return Character.isLetter(ch); } }