| ItemQuery.java |
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;
/**
* @author Prathab K
*
*/
public class ItemQuery implements Query {
/** Type table having the information of types in concept-net */
private ItemTable<String, Short, Type> typeTable;
/** Instance table having the information about the instances in concept-net */
private ItemTable<Short, Integer, InstanceMetaItem> instanceTable;
/** Relation table having the information about the relations in concept-net */
private RelationTable relationTable;
/** Instance Serializer */
private ItemSerializer<Instance> instanceSerializer;
/** Instance reader to read the instances from concept-net */
private ItemReader<Instance> instanceReader;
/** MRU query cache */
private MRUCache<String> queryCache;
/** MRU instance cache */
private MRUCache<Integer> instanceCache;
/**
* Constructs the ItemQuery object and initializes with meta-information of concept-net
* @param cnetDirName concept-net directory name
* @param typeTable type table reference
* @param instanceTable instance table reference
* @throws FileNotFoundException if concept-net file not found
* @throws IOException if file operation fails
*/
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);
}
//Type or Instance Id Retrieval
/**
* Returns the type id of the specified instance
* @param instanceId instance id
* @return type id if exists, else returns -1
*/
public short getTypeId(int instanceId) {
InstanceMetaItem item = instanceTable.get(instanceId);
if(item != null)
return item.typeId;
return -1;
}
/**
* Returns the type id of the specified type name
* @param typeName type name
* @return type id if exists, else returns -1
*/
public short getTypeId(String typeName) {
Type t = typeTable.get(typeName, null);
if(t != null)
return t.id;
return -1;
}
/**
* Returns the type name for the specified type id
* @param typeId Type id
* @return type name if exists, else <tt>null</tt>
* @see Type
*/
public String getTypeName(short typeId) {
Type t = typeTable.get(typeId);
if(t != null)
return t.name;
return null;
}
/**
* Returns all type ids
* @return type ids as list
*/
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;
}
/**
* Returns all entity type ids
* @return type ids as list
*/
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;
}
/**
* Returns all relation type ids
* @return type ids as list
*/
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;
}
/**
* Returns the instance ids for the specified <tt>Type</tt> id
* @param typeId type id
* @return instance ids of the relevant type
*/
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;
}
/**
* Returns the instance ids for the specified <tt>Type</tt> name
* @param typeName type name
* @return instance ids of the relevant type
*/
public List<Integer> getInstanceIds(String typeName) {
return getInstanceIds(getTypeId(typeName));
}
/**
* Returns the existing <code>Instance</code> ids from
* the concept-nets.<br>
* The instance id is retrieved based on the type with the
* specified attribute name and its value. <br>
* Returns <code>NULL</code>, if <code>Instance</code> does not exists.
* @param typeName type name
* @param attributeName instance's attribute name
* @param value the attribute value
* @return instance ids as list
*/
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; // 8 is approx size TODO: calculate actual size
}
}else {
K attrValue = (K)val;
if(value.compareTo(attrValue) == 0){
instanceIdList.add(item.instanceId);
}
valSize +=8; // 8 is approx size
}
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;
}
/**
* Returns the left associated entity id of the given relation id
* @param relationInstanceId relation instance id
* @return entity instance id if exists, else returns -1
*/
public int getLeftEntityId(int relationInstanceId) {
return relationTable.getLeftEntityId(relationInstanceId);
}
/**
* Returns the right associated entity id of the given relation id
* @param relationInstanceId relation instance id
* @return entity instance id if exists, else returns -1
*/
public int getRightEntityId(int relationInstanceId) {
return relationTable.getRightEntityId(relationInstanceId);
}
/**
* Returns the instance ids based on the relation association of the specified instance
* @param instanceId entity instance id
* @return entity instance ids which have relations with the specified instance
*/
public List<Integer> getRelatedInstanceIds(int instanceId) {
List<Integer> result = new ArrayList<Integer>();
Unbound2DIntArray instanceIds = relationTable.getRelationTuplesByEntityId(instanceId);
if(instanceIds != null) { // this approach is followed for better performance
for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
result.add(a[RelationTable.RIGHT_ENTITY_IDX]);
}
}
return result;
}
/**
* Returns the related Instance ids for the specified entity instance id and
* filtered by relation type name
* @param instanceId entity instance id whose relations are to be fetched
* @param relationTypeName relation type name to filter the instance's relations
* @return Instance's relations Id as <tt>Integer List</tt>
*/
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;
}
/**
* Returns the associated relations Ids of an entity instance id
* @param instanceId entity instance id whose relations are to be fetched
* @return Instance's relations Id as <tt>Integer List</tt>
*/
public List<Integer> getRelationIds(int instanceId) {
List<Integer> result = new ArrayList<Integer>();
Unbound2DIntArray instanceIds = relationTable.getRelationTuplesByEntityId(instanceId);
if(instanceIds != null) { // this approach is followed for better performance
for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
result.add(a[RelationTable.RELATION_IDX]); // index '1' indicates the relation id in the tuple
}
}
return result;
}
/**
* Returns the associated relations Ids of an entity instance id and
* filtered by relation type name
* @param instanceId entity instance id whose relations are to be fetched
* @param relationTypeName relation type name to filter the instance's relations
* @return Instance's relations Id as <tt>Integer List</tt>
*/
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;
}
/**
* Returns all the Entity and Relation Instances Id
* @return Instance Ids as <tt>List</tt>
*/
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;
}
/**
* Returns all the Entity Instances Id
* @return Instance Ids as <tt>List</tt>
*/
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;
}
/**
* Returns all the Relation Instances Id
* @return Instance Ids as <tt>List</tt>
*/
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;
}
//Type retrieval
/**
* Returns <tt>Type<tt> for the specified type name
* @return {@link Type} if exists, else <tt>null</tt>
*/
public Type getType(String typeName) {
return typeTable.get(typeName, null);
}
//Instance retrieval
/**
* Returns the instance for the specified instance id
* @param instanceId instance id
* @return @link{Instance}
*/
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;
}
/**
* Returns the existing <code>Instance</code> from
* the concept-nets.<br>
* The instance is retrieved based on the type with the
* specified attribute name and its value. <br>
* Returns <code>NULL</code>, if <code>Instance</code> does not exists.
* @param typeName type name
* @param attributeName instance's attribute name
* @param value the attribute value
* @return {@link iitb.con.core.Instance} list
*/
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;
}
/**
* Returns the instances for the specified instance id
* @param idList list of instance ids
* @return @link{Instance}
*/
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;
}
/**
* Returns all the instances for the specified <tt>Type</tt>
* @param typeId type id
* @return instance list of the given type
* @see Instance
*/
public List<Instance> getInstances(Short typeId) {
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getInstances(idList);
}
return null;
}
/**
* Returns all the instances for the specified <tt>Type</tt>
* @param typeName type name
* @return instance list of the given type
* @see Instance
*/
public List<Instance> getInstances(String typeName) {
Type type = getType(typeName);
return getInstances(type.id);
}
/**
* Returns all the entity instances of specified <tt>Type</tt>
* @param typeId type id
* @return Entity instance list of the given type
* @see EntityInstance
*/
public List<EntityInstance> getEntityInstances(Short typeId){
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getEntityInstances(idList);
}
return null;
}
/**
* Returns all the entity instances of specified <tt>Type</tt>
* @param typeName type name
* @return Entity instance list of the given type
* @see EntityInstance
*/
public List<EntityInstance> getEntityInstances(String typeName){
return getEntityInstances(getTypeId(typeName));
}
/**
* Returns all the relation instances of specified <tt>Type</tt>
* @param typeId type id
* @return Relation instance list of the given type
* @see RelationInstance
*/
public List<RelationInstance> getRelationInstances(Short typeId){
List<Integer> idList = getInstanceIds(typeId);
if(idList != null) {
return getRelationInstances(idList);
}
return null;
}
/**
* Returns all the relation instances of specified <tt>Type</tt>
* @param typeName type name
* @return Relation instance list of the given type
* @see RelationInstance
*/
public List<RelationInstance> getRelationInstances(String typeName){
return getRelationInstances(getTypeId(typeName));
}
/**
* Returns all the <tt>EntitiyInstances</tt> in the concept-net
* @return entity instance list
* @see EntityInstance
*/
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;
}
/**
* Returns all the <tt>RelationInstances</tt> in the concept-net
* @return relation instance list
* @see RelationInstance
*/
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;
}
//low-level access methods
/**
* Returns the instance meta item of specified instance id
* @param instanceId instance's id
* @return {@link InstanceMetaItem}
*/
public InstanceMetaItem getInstanceMetaItem(int instanceId) {
return instanceTable.get(instanceId);
}
//non query methods
/**
* Closes the files that associated with the query object
* @throws IOException if file operation fails
*/
public void close() throws IOException {
instanceReader.close();
IndexCache.getInstance().clear();
}
//private methods
/**
* Returns the instances for the specified type id
* @param typeId type id
* @return Instance Table Items with instance id key as Map
*@see InstanceMetaItem
*/
private Map<Integer,InstanceMetaItem> getMetaInstances(Short typeId) {
return (Map<Integer,InstanceMetaItem>) instanceTable.getObject(typeId);
}
/**
* Reads the instance from the file
* @param item {@link InstanceMetaItem}
* @return instance
* @throws IOException on file error
*/
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 Instance readInstance(InstanceMetaItem item) throws IOException {
Instance instance = instanceCache.get(item.instanceId);
if(instance == null) {
//System.out.println("Miss");
instance = instanceReader.getItem(item.location, item.size);
if(instance != null)
instance.id = item.instanceId;
if(item.clusterId > 0) instanceCache.put(instance, item);
//preFetchInstances(item.instanceId);
} else {
//System.out.println("Hit");
}
return instance;
}*/
/*
private Instance readInstance(InstanceMetaItem item) throws IOException {
Instance instance = lruCache.get(item.instanceId);
if(instance == null) {
System.out.println("Miss");
instance = instanceReader.getItem(item.location, item.size);
if(instance != null)
instance.id = item.instanceId;
}else {
System.out.println("Hit");
}
lruCache.put(instance.id, instance);
return instance;
}*/
/*private Instance readInstance(InstanceMetaItem item) throws IOException {
Instance instance = instanceReader.getItem(item.location, item.size);
if(instance != null)
instance.id = item.instanceId;
return instance;
}*/
/*private Instance readInstance(InstanceMetaItem item) throws IOException {
Instance instance = instanceCache.get(item.instanceId);
if(instance == null) {
instance = instanceReader.getItem(item.location, item.size);
if(instance != null)
instance.id = item.instanceId;
if(item.clusterId > 0) instanceCache.put(instance, item);
}
//lruCache.put(instance.id, instance);
return instance;
}*/
/*private void preFetchInstances(Integer instanceId) throws IOException {
Unbound2DIntArray instanceIds = relationTable.getRelatedInstanceIds(instanceId);
if(instanceIds != null) {
for(int i = 0; i < instanceIds.length; i++) {
int[] a = instanceIds.get(i);
int rid = a[RelationTable.RIGHT_ENTITY_IDX];
long freeSpace = instanceCache.freeSpace() / 2;
InstanceMetaItem item = instanceTable.get(rid);
Instance instance = instanceReader.getItem(item.location, item.size);
if(instance != null) {
instance.id = item.instanceId;
instanceCache.put(instance, item);
}
}
}
}*/
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;
}
}