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;
// }
}