package org.aksw.sparqlify.core.sql.schema; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.aksw.sparqlify.core.TypeToken; /** * A simple schema which keeps track of column names and column datatypes. * * In the future we might also keep track of indexes and stuff, * just like the H2 schema object. * * * * @author Claus Stadler <cstadler@informatik.uni-leipzig.de> * */ public class SchemaImpl implements Schema { private List<String> names; private Map<String, TypeToken> nameToType; private Set<String> nullableNames; /** * An empty schema without any columns. * FIXME If zero-columns schema cause troubles, we will change the behaviour * of this ctor to create a single dummy column * */ public SchemaImpl() { this(new ArrayList<String>(), new HashMap<String, TypeToken>(), new HashSet<String>()); } public SchemaImpl(List<String> names, Map<String, TypeToken> nameToType) { this(names, nameToType, new HashSet<String>()); } public SchemaImpl(List<String> names, Map<String, TypeToken> nameToType, Set<String> nullableNames) { validateNames(names); this.names = names; this.nameToType = nameToType; this.nullableNames = nullableNames; } public static void validateNames(List<String> names) { Set<String> dups = new HashSet<String>(); Set<String> visited = new HashSet<String>(); for(String name : names) { if(visited.contains(name)) { dups.add(name); } visited.add(name); } if(!dups.isEmpty()) { throw new RuntimeException("Multiple column names: " + dups); } } public static SchemaImpl create(List<String> names, Map<String, TypeToken> nameToType) { validateNames(names); return new SchemaImpl(names, nameToType); } @Override public int getColumnCount() { return names.size(); } @Override public String getColumnName(int index) { return names.get(index); } @Override public TypeToken getColumnType(int index) { String name = names.get(index); TypeToken result = nameToType.get(name); return result; } @Override public List<String> getColumnNames() { return names; } @Override public TypeToken getColumnType(String name) { TypeToken result = nameToType.get(name); return result; } @Override public Map<String, TypeToken> getTypeMap() { return nameToType; } @Override public String toString() { String result = "["; boolean isFirst = true; for(String name : names) { TypeToken type = nameToType.get(name); if(isFirst) { isFirst = false; } else { result += ", "; } result += name + ": " + type; } result += "]"; return result; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((nameToType == null) ? 0 : nameToType.hashCode()); result = prime * result + ((names == null) ? 0 : names.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; SchemaImpl other = (SchemaImpl) obj; if (nameToType == null) { if (other.nameToType != null) return false; } else if (!nameToType.equals(other.nameToType)) return false; if (names == null) { if (other.names != null) return false; } else if (!names.equals(other.names)) return false; return true; } @Override public boolean isNullable(String columnName) { boolean result = nullableNames.contains(columnName); return result; } @Override public Schema createSubSchema(List<String> columnNames) { Map<String, TypeToken> tm = new HashMap<String, TypeToken>(); Set<String> nulls = new HashSet<String>(); for(String colName : columnNames) { TypeToken type = nameToType.get(colName); if(type == null) { throw new RuntimeException("Column " + colName + " does not exist."); } tm.put(colName, type); if(isNullable(colName)) { nulls.add(colName); } } SchemaImpl result = new SchemaImpl(columnNames, tm, nulls); return result; } // @Override // public boolean isNullable(boolean assumption) { // // TODO Auto-generated method stub // return false; // } }