package org.radrails.rails.internal.ui.text;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jruby.ast.ArrayNode;
import org.jruby.ast.CallNode;
import org.jruby.ast.FCallNode;
import org.jruby.ast.Node;
import org.rubypeople.rdt.internal.core.parser.InOrderVisitor;
import org.rubypeople.rdt.internal.core.util.ASTUtil;
class MigrationVisitor extends InOrderVisitor {
private Map<String, Set<String>> tableToFields = new HashMap<String, Set<String>>();
private Set<String> fields = new HashSet<String>();
private String tableName;
/**
* Names of methods which mark defining a column in a migration
*/
private static Set<String> columnMethodNames = new HashSet<String>();
static {
columnMethodNames.add("column");
columnMethodNames.add("integer");
columnMethodNames.add("string");
columnMethodNames.add("text");
columnMethodNames.add("float");
columnMethodNames.add("decimal");
columnMethodNames.add("datetime");
columnMethodNames.add("timestamp");
columnMethodNames.add("time");
columnMethodNames.add("date");
columnMethodNames.add("binary");
columnMethodNames.add("boolean");
}
public Set<String> getFieldNames(String string) {
if (tableToFields.containsKey(string.toLowerCase()))
return tableToFields.get(string.toLowerCase());
return new HashSet<String>();
}
@Override
public Object visitFCallNode(FCallNode iVisited) {
String name = iVisited.getName();
if (name.equals("create_table")) {
ArrayNode args = (ArrayNode) iVisited.getArgsNode();
Node firstArg = args.get(0);
tableName = ASTUtil.stringRepresentation(firstArg);
Object ins = super.visitFCallNode(iVisited);
// Add all the fields to table in tableToFields
Set<String> temp = tableToFields.get(tableName);
if (temp == null) temp = new HashSet<String>();
temp.addAll(fields);
tableToFields.put(tableName, temp);
fields = new HashSet<String>();
tableName = null;
return ins;
} else if (name.equals("add_column")) {
ArrayNode args = (ArrayNode) iVisited.getArgsNode();
Node firstArg = args.get(0);
String aTableName = ASTUtil.stringRepresentation(firstArg);
Node secondArg = args.get(1);
String field = ASTUtil.stringRepresentation(secondArg);
Set<String> temp = tableToFields.get(aTableName);
if (temp == null) temp = new HashSet<String>();
temp.add(field);
tableToFields.put(aTableName, temp);
}
return super.visitFCallNode(iVisited);
}
@Override
public Object visitCallNode(CallNode iVisited) {
if (columnMethodNames.contains(iVisited.getName())) {
ArrayNode args = (ArrayNode) iVisited.getArgsNode();
Node firstArg = args.get(0);
String fieldName = ASTUtil.stringRepresentation(firstArg);
fields.add(fieldName);
} else if (iVisited.getName().equals("timestamps")) {
fields.add("created_at");
fields.add("updated_at");
} else if (iVisited.getName().equals("references")) {
ArrayNode args = (ArrayNode) iVisited.getArgsNode();
Node firstArg = args.get(0);
String fieldName = ASTUtil.stringRepresentation(firstArg);
// fields.add(fieldName); // t.references :tag => tag field
fields.add(fieldName + "_id"); // t.references :tag => 'tag_id' field
}
return super.visitCallNode(iVisited);
}
public Collection<? extends String> getTableNames() {
return tableToFields.keySet();
}
}