I am building a mini SQL parser that reads and converts SELECT, INSERT, UPDATE and DELETE statements into an AST. My current design is as follows:
Statement.java:
public interface Statement {
String getOperation();
String getTable();
Map<String, Object> getColumns();
String getConditions();
}
Select.java, Insert.java, Update.java and Delete.java are all POJO's that implement this interface, with varying attributes (for example, different toString() implementations). I have a separate utility class that defines a method called parse(String query) as follows:
public Statement parse(String query) {
String operation = getOperation(query);
if (operation.equals("insert")) {
String table = getTable();
Map<String, Object> keyValues = getColumns();
return new InsertStatement(table, keyValues);
} else if ...
}
I'm wondering if it makes sense to have a separate utility class for defining the parse method or if it may be a better idea to change Statement to an abstract class and move the parse method inside it. That way, someone could call Statement.parse("INSERT INTO ...") and get an InsertStatement object back:
public abstract class Statement {
String getOperation();
String getTable();
Map<String, Object> getColumns();
String getConditions();
public Statement parse(String query) {
String operation = getOperation(query);
if (operation.equals("insert")) {
return parseInsert(query);
} else if ...
}
private InsertStatement parseInsert(String query) {
// parse and return InsertStatement instance
}
}
Is there a general good practice recommended here?