package iitb.con.query;
import iitb.con.caching.CacheObject;
import iitb.con.caching.MRUCache;
import iitb.con.core.Attribute;
import iitb.con.core.ConStoreConstants;
import iitb.con.core.Entity;
import iitb.con.core.EntityInstance;
import iitb.con.core.Instance;
import iitb.con.core.Relation;
import iitb.con.core.RelationInstance;
import iitb.con.core.Type;
import iitb.con.ds.InstanceMetaItem;
import iitb.con.ds.InstanceSerializer;
import iitb.con.ds.ItemSerializer;
import iitb.con.ds.ItemTable;
import iitb.con.ds.RelationTable;
import iitb.con.indexing.IndexBuilder;
import iitb.con.indexing.IndexCache;
import iitb.con.util.Unbound2DIntArray;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ItemQuery implements Query {
private ItemTable<String, Short, Type> typeTable;
private ItemTable<Short, Integer, InstanceMetaItem> instanceTable;
private RelationTable relationTable;
private ItemSerializer<Instance> instanceSerializer;
private ItemReader<Instance> instanceReader;
private MRUCache<String> queryCache;
private MRUCache<Integer> instanceCache;
public ItemQuery(String cnetDirName,
ItemTable<String, Short, Type> typeTable,
ItemTable<Short, Integer, InstanceMetaItem> instanceTable,
RelationTable relationTable)
throws FileNotFoundException, IOException{
this.typeTable = typeTable;
this.instanceTable = instanceTable;
this.relationTable = relationTable;
instanceSerializer = new InstanceSerializer(typeTable);
instanceReader = new ItemReader<Instance>(cnetDirName + ConStoreConstants.NET_FILE,
instanceSerializer);
queryCache = new MRUCache<String>(ConStoreConstants.QUERY_CACHE_SIZE);
instanceCache = new MRUCache<Integer>(ConStoreConstants.INSTANCE_CACHE_SIZE);
}
public short getTypeId(int instanceId) {
InstanceMetaItem item = instanceTable.get(instanceId);
if(item != null)
return item.typeId;
return -1;
}
public short getTypeId(String typeName) {
Type t = typeTable.get(typeName, null);
if(t != null)
return t.id;
return -1;
}
public String getTypeName(short typeId) {
Type t = typeTable.get(typeId);
if(t != null)
return t.name;
return null;
}
public List<Short> getAllTypeIds(){
List<Short> idList = new ArrayList<Short>();
List<Type> types = typeTable.getAllItems();
for(Type type : types) {
idList.add(type.id);
}
return idList;
}
public List<Short> getAllEntityTypeIds(){
List<Short> idList = new ArrayList<Short>();
List<Type> types = typeTable.getAllItems();
for(Type type : types) {
if(type instanceof Entity)
idList.add(type.id);
}
return idList;
}
public List<Short> getAllRelationTypeIds(){
List<Short> idList = new ArrayList<Short>();
List<Type> types = typeTable.getAllItems();
for(Type type : types) {
if(type instanceof Relation)
idList.add(type.id);
}
return idList;
}
public List<Integer> getInstanceIds(short typeId) {
Map<Integer,InstanceMetaItem> metaItems = getMetaInstances(typeId);
List<Integer> result = new ArrayList<Integer>();
if(metaItems != null) {
for(InstanceMetaItem item : metaItems.values()) {
result.add(item.instanceId);
}
}
return result;
}
public List<Integer> getInstanceIds(String typeName) {
return getInstanceIds(getTypeId(typeName));
}
public <K extends Comparable<K>> List<Integer> getInstanceIds(String typeName,
String attributeName, K value) {
Type type = typeTable.get(typeName, null);
if(type == null)
return null;
Attribute attribute = type.getAttribute(attributeName);
if(attribute == null)
return null;
List<Integer> instanceIdList = new ArrayList<Integer>();
int[] indexedInstanceIds = null;
if(IndexBuilder.hasIndex(type.id, attributeName)) {
IndexCache indexCache = IndexCache.getInstance();
indexedInstanceIds = indexCache.getInstancesIds(type.id, attributeName, value);
if(indexedInstanceIds != null) {
for(int i=0 ; i < indexedInstanceIds.length; i++) {
InstanceMetaItem item = instanceTable.get(indexedInstanceIds[i]);
if(item != null) {
instanceIdList.add(item.instanceId);
}
}
}
}else {
List<Integer> instanceIds = getInstanceIds(type.id);
if(instanceIds != null) {
for(Integer id : instanceIds) {
InstanceMetaItem item = instanceTable.get(id);
if(item != null) {
boolean toBeCached = false;
Object val = null;
CacheObject cacheObj = queryCache.get(new String(id + attributeName));
try {
if(cacheObj == null) {
val = instanceReader.getItemAttributeValue(item.location,
item.size, attributeName);
toBeCached = true;
}else {
val = cacheObj.object;
}
}catch(IOException ie) {
ie.printStackTrace();
return null;
}
int valSize = 0;
if(val != null) {
if(attribute.repeating) {
List<K> valList = (List<K>) val;
for(K v : valList) {
if(value.compareTo(v) == 0) {
instanceIdList.add(item.instanceId);
}
valSize +=8; }
}else {
K attrValue = (K)val;
if(value.compareTo(attrValue) == 0){
instanceIdList.add(item.instanceId);
}
valSize +=8; }
if(toBeCached) {
cacheObj = new CacheObject(val, valSize);
queryCache.put(new String(item.instanceId + attributeName), cacheObj);
}
}else {
if(value == null){
instanceIdList.add(item.instanceId);
}
}
}
}
}
}
return instanceIdList;
}
public int getLeftEntityId(int relationInstanceId) {
return relationTable.getLeftEntityId(relationInstanceId);
}
public int getRightEntityId(int relationInstanceId) {
return relationTable.getRightEntityId(relationInstanceId);
}
public List<Integer> getRelatedInstanceIds(int instanceId) {
List<Integer> result = new ArrayList<Integer>();
Unbound2DIntArray instanceIds = relationTable.getRelationTuplesByEntityId(instanceId);
if(instanceIds != null) { for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
result.add(a[RelationTable.RIGHT_ENTITY_IDX]);
}
}
return result;
}
public List<Integer> getRelatedInstanceIds(int instanceId, String relationTypeName) {
List<Integer> result = new ArrayList<Integer>();
Unbound2DIntArray instanceIds = relationTable.getRelationTuplesByEntityId(instanceId);
Map<Integer, InstanceMetaItem> instanceMap =
instanceTable.get(getTypeId(relationTypeName));
if(instanceIds != null && instanceMap != null) {
for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
InstanceMetaItem item = instanceMap.get(a[RelationTable.RELATION_IDX]);
if(item != null)
result.add(a[RelationTable.RIGHT_ENTITY_IDX]);
}
}
return result;
}
public List<Integer> getRelationIds(int instanceId) {
List<Integer> result = new ArrayList<Integer>();
Unbound2DIntArray instanceIds = relationTable.getRelationTuplesByEntityId(instanceId);
if(instanceIds != null) { for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
result.add(a[RelationTable.RELATION_IDX]); }
}
return result;
}
public List<Integer> getRelationIds(int instanceId, String relationTypeName) {
List<Integer> idList = new ArrayList<Integer>();
Map<Integer, InstanceMetaItem> instanceMap =
instanceTable.get(getTypeId(relationTypeName));
List<Integer> relIds = getRelationIds(instanceId);
if(instanceMap != null) {
for(Integer id : relIds) {
InstanceMetaItem item = instanceMap.get(id);
if(item != null)
idList.add(id);
}
}
return idList;
}
public List<Integer> getAllInstanceIds() {
List<Integer> result = new ArrayList<Integer>();
List<InstanceMetaItem> metaItems = instanceTable.getAllItems();
if(metaItems != null) {
for(InstanceMetaItem item : metaItems)
result.add(item.instanceId);
}
return result;
}
public List<Integer> getAllEntityInstanceIds() {
List<Integer> idList = new ArrayList<Integer>();
List<Short> typeIds = getAllEntityTypeIds();
if(typeIds != null) {
for(Short id : typeIds) {
List<Integer> instanceIds = getInstanceIds(id);
if(instanceIds != null) {
for(Integer i : instanceIds)
idList.add(i);
}
}
}
return idList;
}
public List<Integer> getAllRelationInstanceIds() {
List<Integer> idList = new ArrayList<Integer>();
List<Short> typeIds = getAllRelationTypeIds();
if(typeIds != null) {
for(Short id : typeIds) {
List<Integer> instanceIds = getInstanceIds(id);
if(instanceIds != null) {
for(Integer i : instanceIds)
idList.add(i);
}
}
}
return idList;
}
public Type getType(String typeName) {
return typeTable.get(typeName, null);
}
public Instance getInstance(int instanceId) {
InstanceMetaItem item = instanceTable.get(instanceId);
try {
if(item != null) {
Instance instance = readInstance(item);
return instance;
}
}catch(IOException ie) {
ie.printStackTrace();
}
return null;
}
public <K extends Comparable<K>> List<Instance> getInstances(String typeName,
String attributeName, K value) {
List<Integer> idList = getInstanceIds(typeName, attributeName, value);
if(idList != null)
return getInstances(idList);
return null;
}
public List<Instance> getInstances(List<Integer> idList) {
List<Instance> instanceList = new ArrayList<Instance>();
try {
for(Integer id : idList) {
InstanceMetaItem item = instanceTable.get(id);
Instance instance = readInstance(item);
if(instance != null)
instanceList.add(instance);
}
}catch(IOException ie) {
ie.printStackTrace();
return null;
}
return instanceList;
}
public List<Instance> getInstances(Short typeId) {
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getInstances(idList);
}
return null;
}
public List<Instance> getInstances(String typeName) {
Type type = getType(typeName);
return getInstances(type.id);
}
public List<EntityInstance> getEntityInstances(Short typeId){
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getEntityInstances(idList);
}
return null;
}
public List<EntityInstance> getEntityInstances(String typeName){
return getEntityInstances(getTypeId(typeName));
}
public List<RelationInstance> getRelationInstances(Short typeId){
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getRelationInstances(idList);
}
return null;
}
public List<RelationInstance> getRelationInstances(String typeName){
return getRelationInstances(getTypeId(typeName));
}
public List<EntityInstance> getAllEntityInstances(){
List<EntityInstance> entityInstances = new ArrayList<EntityInstance>();
List<Short> entityIds = getAllEntityTypeIds();
for(Short id : entityIds) {
Map<Integer,InstanceMetaItem> instances = getMetaInstances(id);
try {
if(instances != null) {
for(InstanceMetaItem item : instances.values()) {
Instance instance = readInstance(item);
if(instance instanceof EntityInstance) {
entityInstances.add((EntityInstance) instance);
}
}
}
}catch(IOException io) {
io.printStackTrace();
}
}
return entityInstances;
}
public List<RelationInstance> getAllRelationInstances(){
List<RelationInstance> relationInstances = new ArrayList<RelationInstance>();
List<Short> relationIds = getAllRelationTypeIds();
for(Short id : relationIds) {
Map<Integer,InstanceMetaItem> instances = getMetaInstances(id);
try {
if(instances != null) {
for(InstanceMetaItem item : instances.values()) {
Instance instance = readInstance(item);
if(instance instanceof RelationInstance) {
relationInstances.add((RelationInstance) instance);
}
}
}
}catch(IOException io) {
io.printStackTrace();
}
}
return relationInstances;
}
public InstanceMetaItem getInstanceMetaItem(int instanceId) {
return instanceTable.get(instanceId);
}
public void close() throws IOException {
instanceReader.close();
IndexCache.getInstance().clear();
}
private Map<Integer,InstanceMetaItem> getMetaInstances(Short typeId) {
return (Map<Integer,InstanceMetaItem>) instanceTable.getObject(typeId);
}
private Instance readInstance(InstanceMetaItem item) throws IOException {
Instance instance = null;
CacheObject cacheObj = instanceCache.get(item.instanceId);
if(cacheObj == null) {
instance = instanceReader.getItem(item.location, item.size);
if(instance != null)
instance.id = item.instanceId;
cacheObj = new CacheObject(instance, item.size);
instanceCache.put(item.instanceId, cacheObj);
}
instance = (Instance) cacheObj.object;
return instance;
}
private List<EntityInstance> getEntityInstances(List<Integer> idList) {
List<EntityInstance> instanceList = new ArrayList<EntityInstance>();
try {
for(Integer id : idList) {
InstanceMetaItem item = instanceTable.get(id);
Instance instance = readInstance(item);
if(instance != null && instance instanceof EntityInstance)
instanceList.add((EntityInstance)instance);
}
}catch(IOException ie) {
ie.printStackTrace();
return null;
}
return instanceList;
}
private List<RelationInstance> getRelationInstances(List<Integer> idList) {
List<RelationInstance> instanceList = new ArrayList<RelationInstance>();
try {
for(Integer id : idList) {
InstanceMetaItem item = instanceTable.get(id);
Instance instance = readInstance(item);
if(instance != null && instance instanceof RelationInstance)
instanceList.add((RelationInstance)instance);
}
}catch(IOException ie) {
ie.printStackTrace();
return null;
}
return instanceList;
}
}