/**
*
*/
package outputter.search;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.jdom.Element;
import outputter.Utilities;
import outputter.data.CompositeEntity;
import outputter.data.Entity;
import outputter.data.EntityProposals;
import outputter.data.FormalConcept;
import outputter.data.FormalRelation;
import outputter.data.REntity;
import outputter.data.SimpleEntity;
import outputter.knowledge.Dictionary;
/**
* @author Hong Cui
* = EntitySearcher4
* anterior maxilla => anterior region part of maxilla
* anterior process of maxilla => process part of anterior region part of maxilla
*
*
*/
public class SpatialModifiedEntityStrategy implements SearchStrategy {
private static final Logger LOGGER = Logger.getLogger(SpatialModifiedEntityStrategy.class);
ArrayList<EntityProposals> entities;
private String entityphrase;
private String elocatorphrase;
private Element root;
private String structid;
private String prep;
private String originalentityphrase;
//search results:
private ArrayList<EntityProposals> entityls;
private ArrayList<EntityProposals> sentityps;
private static Hashtable<String, ArrayList<EntityProposals>> cache = new Hashtable<String, ArrayList<EntityProposals>>();
private static ArrayList<String> nomatchcache = new ArrayList<String>();
public static Pattern spatialptn = Pattern.compile("^("+Dictionary.spatialtermptn+")\\b\\s*\\b("+Dictionary.allSpatialHeadNouns()+")?\\b");
/**
* [the expression is a query expanded with syn rings,
* for example, '(?:anterior|front) (?:maxilla|maxillary)'] --not yet
*/
public SpatialModifiedEntityStrategy(Element root, String structid,
String entityphrase, String elocatorphrase,
String originalentityphrase, String prep) {
this.entityphrase = entityphrase;
this.elocatorphrase = elocatorphrase;
this.root = root;
this.structid = structid;
this.prep = prep;
this.originalentityphrase = originalentityphrase;
LOGGER.debug("SpatialModifiedEntityStrategy: search '"+entityphrase+"[orig="+originalentityphrase+"]'");
}
/* (non-Javadoc)
* @see outputter.AnnotationStrategy#handle()
*/
@Override
public void handle() {
//search cache
if(SpatialModifiedEntityStrategy.nomatchcache.contains(entityphrase+"+"+elocatorphrase)){
entities = null;
return;
}
if(SpatialModifiedEntityStrategy.cache.get(entityphrase+"+"+elocatorphrase)!=null){
entities = SpatialModifiedEntityStrategy.cache.get(entityphrase+"+"+elocatorphrase);
return;
}
//ArrayList<EntityProposals> entityls = new ArrayList<EntityProposals>();
//entityl.setString(elocatorphrase);
if(elocatorphrase.length()>0) {
//ArrayList<FormalConcept> results = new TermSearcher().searchTerm(elocatorphrase, "entity"); //change this to EntitySearcherOriginal?
ArrayList<EntityProposals> results = new EntitySearcherOriginal().searchEntity(root, structid, elocatorphrase, "",originalentityphrase, prep);
if(results!=null){
LOGGER.debug("SME...searched locator '"+elocatorphrase+"' found match: ");
for(EntityProposals result: results){
if(entityls==null) entityls = new ArrayList<EntityProposals>();
entityls.add(result);
LOGGER.debug(".." +result.toString());
}
}else{
LOGGER.debug("SME...not match for locator '"+elocatorphrase+"'");
}
}
Matcher m = spatialptn.matcher(entityphrase);
if(m.find()){
String spatialterm = entityphrase.substring(m.start(), m.end()).trim();
String newentity = entityphrase.substring(m.end()).trim();
if(spatialterm.indexOf(" ")<0) spatialterm += " region";
//take synonyms into account
spatialterm = synVariation(spatialterm);
LOGGER.debug("SME...formed spatial term '"+spatialterm+"'");
//entityphrase='ventral surface'
//if(entityphrasetokens[0].matches("("+Dictionary.spatialtermptn+")")){
//String newentity = Utilities.join(entityphrasetokens, 1, entityphrasetokens.length-1, " "); //anything after the spatial term
//SimpleEntity sentity = (SimpleEntity)new TermSearcher().searchTerm(newentity, "entity");
//ArrayList<EntityProposals> sentityps = null;
if(newentity.length()<=0){//e.g. search for 'ventral surface'
//entityls => sentityps
if(entityls!=null && entityls.size()>0){
sentityps = entityls;
//create a empty entityls
//entityls = new ArrayList<EntityProposals>();
entityls = null;
}
}else{
LOGGER.debug("SME...calls EntitySearcherOriginal for newentity '"+newentity/*+","+elocatorphrase*/+"'");
//sentityps = new EntitySearcherOriginal().searchEntity(root, structid, newentity, elocatorphrase, originalentityphrase, prep); //advanced search
sentityps = new EntitySearcherOriginal().searchEntity(root, structid, newentity, "", originalentityphrase, prep); //advanced search
}
LOGGER.debug("SME...now search for spatial term '"+spatialterm+"'");
//SimpleEntity sentity1 = (SimpleEntity)new TermSearcher().searchTerm(spatialterm, "entity");
//ArrayList<FormalConcept> spatialentities = TermSearcher.regexpSearchTerm(spatialterm, "entity");//anterior + region: simple search
ArrayList<FormalConcept> spatialentities = new TermSearcher().searchTerm(spatialterm, "entity");//anterior + region: simple search
if(spatialentities!=null) LOGGER.debug("...found match");
else{
//create phrase-based spatialentities
SimpleEntity spatial = new SimpleEntity();
spatial.setSearchString(spatialterm);
spatial.setString(spatialterm);
spatial.setConfidenceScore(1f);
spatialentities = new ArrayList<FormalConcept>();
spatialentities.add(spatial);
}
boolean found = false;
EntityProposals centityp = new EntityProposals();
if(sentityps==null){ //standalone spatial term such as 'ventral region'
//if(spatialentities!=null){
//TODO consider partial results?
found = true;
for(FormalConcept spatialentity: spatialentities){
SimpleEntity sentity1 = (SimpleEntity) spatialentity;
if(sentity1!=null){
centityp.add(sentity1);
centityp.setPhrase(originalentityphrase);
}
}
//}
}else{
centityp.setPhrase(this.originalentityphrase);
for(EntityProposals sentityp: sentityps){
for(Entity sentity: sentityp.getProposals()){
for(FormalConcept spatialentity: spatialentities){
SimpleEntity sentity1 = (SimpleEntity) spatialentity;
if(sentity1!=null){//ventral region
//nested part_of relation
if(entityls!=null && entityls.size()>0 || sentity instanceof CompositeEntity){ //anterior process of maxilla
//relation & entity locator: inner
FormalRelation rel = Dictionary.partof;
rel.setConfidenceScore((float)1.0);
ArrayList<REntity> rentities = new ArrayList<REntity>();
REntity re = null;
//TODO: what if both conditions are true?
if(entityls!=null && entityls.size()>0){
for(EntityProposals ep: entityls){
for(Entity entityl: ep.getProposals()){
re = new REntity(rel, entityl);
rentities.add(re);
}
}
}else if(sentity instanceof CompositeEntity){//entitylocator is in sentity
//sentity should not have any post-composed quality
re = ((CompositeEntity) sentity).getEntityLocator();
rentities.add(re);
sentity = ((CompositeEntity) sentity).getTheSimpleEntity();
}
for(REntity rentity: rentities){
//composite entity = entity locator for sentity
CompositeEntity centity = new CompositeEntity(); //anterior region^part_of(maxilla)
centity.addEntity(sentity1); //anterior region
centity.addEntity(rentity); //^part_of(maxilla)
//relation & entity locator:outer
rel = Dictionary.partof;
rel.setConfidenceScore((float)1.0);
REntity rentity2 = new REntity(rel, centity);
centity = new CompositeEntity(); //process^part_of(anterior region^part_of(maxilla))
centity.addEntity(sentity); //process
centity.addEntity(rentity2); //^part_of(anterior region^part_of(maxilla))
centity.setString(this.originalentityphrase);
centityp.add(centity);
found = true;
//LOGGER.debug("with entity locator, SME form a composite entity proposals: "+centity.toString());
//entities.add(centityp);
}
}else{//anterior maxilla
//corrected 6/1/13 [basal scutes]: sentity1 be the entity; sentity is the entity locator
//relation & entity locator:
FormalRelation rel = Dictionary.partof;
rel.setConfidenceScore((float)1.0);
REntity rentity = new REntity(rel, sentity);
//composite entity = entity locator for sentity
CompositeEntity centity = new CompositeEntity();
centity.addEntity(sentity1);
centity.addEntity(rentity);
centity.setString(this.originalentityphrase);
centityp.add(centity);
found = true;
//LOGGER.debug("without entity locator, SME form a composite entity proposals: "+centityp.toString());
}
}else{
LOGGER.debug("SME search for spatial term '"+spatialterm+"' found no match");
}
}
}
}
}
if(found){
if(entities==null) entities = new ArrayList<EntityProposals>();
Utilities.addEntityProposals(entities, centityp);
LOGGER.debug("SpatialModifiedEntityStrategy completed, returns");
for(EntityProposals ep: entities){
LOGGER.debug(".."+ep.toString());
}
}
//caching
if(entities==null) SpatialModifiedEntityStrategy.nomatchcache.add(entityphrase+"+"+elocatorphrase);
else SpatialModifiedEntityStrategy.cache.put(entityphrase+"+"+elocatorphrase, entities);
}
}
/**
* ventral portion => ventral region as portion is a syn of region
* @param spatialterm
* @return replace spatial term head noun synonyms with the head noun.
*/
private String synVariation(String spatialterm) {
spatialterm = spatialterm.trim();
if(spatialterm.indexOf(" ")>0){
String result = spatialterm.substring(0, spatialterm.lastIndexOf(" ")).trim();
String syn = spatialterm.substring(spatialterm.lastIndexOf(" ")).trim();
if(Dictionary.headnounsyns.get(syn)!=null) return spatialterm; //already with the headnoun
Enumeration<String> terms = Dictionary.headnounsyns.keys();
String matches = "";
while(terms.hasMoreElements()){
String term = terms.nextElement();
if(term.trim().length()>0){
String syns = Dictionary.headnounsyns.get(term);
if(syns.length()>0 && syn.matches("\\b"+syns+"\\b")){
matches = term+"|";
}
}
}
if(matches.length()>0){
matches = matches.replaceAll("\\|$", "");
result +=" "+matches; //ventral region
return result;
}else{
return spatialterm;
}
}else{
return spatialterm;
}
}
/**
* search result for entity
* @return
*/
public ArrayList<EntityProposals> getEntityResult() {
return this.sentityps;
}
/**
* search result for entity locator
* @return
*/
public ArrayList<EntityProposals> getEntityLocatorResult() {
return this.entityls;
}
public ArrayList<EntityProposals> getEntities() {
return this.entities;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}