package org.openedit.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.entermedia.locks.LockManager;
import org.openedit.Data;
import org.openedit.xml.XmlArchive;
import com.openedit.BeanNameLoader;
import com.openedit.ModuleManager;
import com.openedit.OpenEditRuntimeException;
import com.openedit.hittracker.HitTracker;
import com.openedit.util.Replacer;
public class SearcherManager
{
private static final Log log = LogFactory.getLog(SearcherManager.class);
protected ModuleManager fieldModuleManager;
protected Map fieldCache;
//A fieldName can be product or orderstatus. If there is no orderstatus searcher then we use an XML lookup for this catalog.
public Searcher getSearcher(String inCatalogId, String inFieldName)
{
if( inCatalogId == null)
{
throw new OpenEditRuntimeException("Catalog id is required");
}
if ( inFieldName == null )
{
return null;
}
//look in map for existing
String id = inCatalogId + "|" + inFieldName;
Searcher searcher = (Searcher)getCache().get(id);
if( searcher == null )
{
synchronized (this)
{
searcher = (Searcher)getCache().get(id);
if( searcher == null )
{
String finalcatalogid = resolveCatalogId(inCatalogId, inFieldName);
if( !finalcatalogid.equals(inCatalogId))
{
searcher = (Searcher)getCache().get(finalcatalogid + "|" + inFieldName);
if( searcher != null )
{
return searcher;
}
}
//TODO: Look in the cache again for the target Searcher
PropertyDetailsArchive newarchive = getPropertyDetailsArchive(finalcatalogid);
// if( inFieldName == null)
// {
// return null;
// }
searcher = loadSearcher(newarchive, inFieldName);
searcher.setCatalogId(finalcatalogid);
searcher.setSearchType(inFieldName); //This may be product or orderstatus
//set the data
searcher.setPropertyDetailsArchive(newarchive);
searcher.setSearcherManager(this);
if(log.isDebugEnabled())
{
log.debug("Created New Searcher: Catalog = " + searcher.getCatalogId() + "SearchType = " + searcher.getSearchType() + "Searcher = " + searcher.getClass() );
}
getCache().put(id, searcher);
if( !finalcatalogid.equals(inCatalogId))
{
getCache().put(finalcatalogid + "|" + inFieldName, searcher); //make sure we store both versions since they are the same searcher
}
}
}
}
//log.debug("return " + id + " " + searcher);
return searcher;
}
protected synchronized Searcher loadSearcher(PropertyDetailsArchive newarchive, String inFieldName)
{
String inCatalogId = newarchive.getCatalogId();
Searcher searcher;
//Check the properites
PropertyDetails details = newarchive.getPropertyDetails(inFieldName);
String beanName = null;
if( getModuleManager().contains(inCatalogId,inFieldName + "Searcher") ) //this might be a lookup
{
beanName = inFieldName + "Searcher";
}
else
{
beanName = details.getBeanName(); //Once item is saved it always uses dataSearcher for the type
if( beanName == null)
{
if( inFieldName.endsWith("Log"))
{
beanName = "dynamicLogSearcher";
}
else
{
beanName = "listSearcher";
}
}
}
searcher = (Searcher)getModuleManager().getBean(inCatalogId, beanName, false);
if(log.isDebugEnabled())
{
log.debug("Searcher not found creating dynamic instance ");
}
// if( inCatalogId.length() == 0 && "catalogs".equals(inFieldName))
// {
// XmlSearcher xml = (XmlSearcher)searcher;
// }
//log.info("Loaded " + inFieldName + " with " + beanName);
return searcher;
}
public PropertyDetailsArchive getPropertyDetailsArchive(String inCatalogId)
{
PropertyDetailsArchive newarchive = (PropertyDetailsArchive)getModuleManager().getBean(inCatalogId, "propertyDetailsArchive"); //Not a singleton
return newarchive;
}
public Searcher getSearcher(String inCatalogId, String inExternalCatalogId, String inFieldName)
{
if( inExternalCatalogId != null)
{
inCatalogId = inExternalCatalogId;
}
return getSearcher(inCatalogId, inFieldName);
}
/**
*
* @param inCatalogId
* @param inDetail
* @return
*/
public Searcher getSearcher(String inCatalogId, PropertyDetail inDetail)
{
//We may get passed in an external catalog and field
String field = inDetail.getId();
if( inDetail.getExternalId() != null)
{
field = inDetail.getExternalId();
}
return getSearcher(inDetail.getListCatalogId(), field);
}
public Searcher getListSearcher(PropertyDetail inDetail)
{
//We may get passed in an external catalog and field
return getSearcher(inDetail.getListCatalogId(), inDetail.getListId() );
}
public Object getListData(PropertyDetail inDetail, String inValue)
{
return getData(inDetail.getListCatalogId(), inDetail.getListId(), inValue);
}
public String getValue(Data inParent,PropertyDetail inDetail)
{
if(inParent == null){
return null;
}
String mask = inDetail.get("render");
String val = null;
if( mask != null)
{
val = getValue(inDetail.getCatalogId(),mask,inParent.getProperties());
}
else
{
val = inParent.get(inDetail.getId());
}
return val;
}
public String getLabel(Searcher inSearcher, Data inData)
{
if(inData == null){
return null;
}
String val = null;
String mask = inSearcher.getPropertyDetails().getRender();
if( mask != null)
{
val = getValue(inSearcher.getCatalogId(),mask,inData.getProperties());
}
else
{
String name = inData.getName();
if(name != null)
{
val = name;
}
else
{
val = inData.getId();
}
}
return val;
}
public String getLabel(PropertyDetail inDetail, Data inData)
{
if(inData == null){
return null;
}
String mask = inDetail.get("render");
String val = null;
if( mask != null)
{
val = getValue(inDetail.getCatalogId(),mask,inData.getProperties());
}
else
{
Searcher listsearcher = getSearcher(inDetail.getListCatalogId(),inDetail.getListId() );
mask = listsearcher.getPropertyDetails().getRender();
if( mask != null)
{
val = getValue(inDetail.getCatalogId(),mask,inData.getProperties());
}
else
{
String name = inData.getName();
if(name != null)
{
val = name;
}
else
{
val = inData.getId();
}
}
}
return val;
}
public String getValue(String inCatalogId, String inMask,Map inValues)
{
if( inMask == null)
{
return null;
}
Replacer replacer = getReplacer(inCatalogId);
String val = replacer.replace(inMask, inValues);
if( val.startsWith("$") && val.equals(inMask) )
{
return "";
}
return val;
}
public Replacer getReplacer(String inCatalogId)
{
return (Replacer)getModuleManager().getBean(inCatalogId, "replacer");
}
public Data getData(String inCatalogId, String inSearchType, String inId)
{
if( inId == null)
{
return null;
}
Searcher searcher = getSearcher(inCatalogId, inSearchType);
Object data = searcher.searchById(inId);
return (Data)data;
}
public Data getData(PropertyDetail inDetail, String inId)
{
if( inId == null)
{
return null;
}
Searcher searcher = getSearcher(inDetail.getListCatalogId(), inDetail.getListId());
Object data = searcher.searchById(inId);
return (Data)data;
}
public HitTracker getList(PropertyDetail inDetail)
{
return getList(inDetail.getListCatalogId(), inDetail.getListId());
}
public HitTracker getList(String inCatalogId, String inFieldName)
{
if( inFieldName == null)
{
return null;
}
//If this is not my searcher type then use the manager to get the correct search
Searcher searcher = getSearcher(inCatalogId, inFieldName);
HitTracker found = searcher.getAllHits();
return found;
}
public ModuleManager getModuleManager()
{
return fieldModuleManager;
}
public void setModuleManager(ModuleManager inModuleManager)
{
fieldModuleManager = inModuleManager;
}
public void clear()
{
for (Iterator iterator = getCache().keySet().iterator(); iterator.hasNext();)
{
String key = (String) iterator.next();
String[] vals = key.split("|");
getModuleManager().clearBean(vals[0], vals[1]);
}
getCache().clear();
}
protected Map getCache()
{
if( fieldCache == null)
{
fieldCache = new HashMap();
}
return fieldCache;
}
public FilteredTracker makeFilteredTracker()
{
return new CompositeFilteredTracker();
}
public void removeFromCache(String inCatalogId, String inFieldName)
{
getCache().remove(inCatalogId + "|" + inFieldName);
String beanName = null;
if( getModuleManager().contains(inCatalogId,inFieldName + "Searcher") )
{
beanName = inFieldName + "Searcher";
}
else
{
if( inFieldName.endsWith("Log"))
{
beanName = "dynamicLogSearcher";
}
else
{
PropertyDetails details = getPropertyDetailsArchive(inCatalogId).getPropertyDetails(inFieldName);
beanName = details.getBeanName();
if( beanName == null )
{
beanName = "dynamicSearcher";
}
}
}
getModuleManager().clearBean(inCatalogId, beanName);
}
public Collection<Searcher> listLoadedSearchers(String inCatalogId)
{
List<Searcher> loaded = new ArrayList<Searcher>();
for (Iterator iterator = getCache().values().iterator(); iterator.hasNext();)
{
Searcher searcher = (Searcher) iterator.next();
if( searcher.getCatalogId().equals(inCatalogId))
{
loaded.add(searcher);
}
}
return loaded;
}
/*
public Collection getCatalogs()
{
XmlFile file = getCatalogXml();
XmlSearcher searcher = (XmlSearcher)getSearcher("", "catalogs");
searcher.setXmlFile(file);
return searcher.getAllHits();
}
protected XmlFile getCatalogXml()
{
XmlFile file = getXmlArchive().getXml("/WEB-INF/data/catalogs.xml");
if( !file.isExist() )
{
file = getXmlArchive().getXml("/WEB-INF/data/media/lists/catalogs.xml"); //legacy
}
return file;
}
public Element getCatalog(String inId)
{
XmlFile file = getCatalogXml();
Element element = file.getElementById(inId);
return element;
}
public void saveCatalog(String inId, String inName)
{
XmlFile file = getCatalogXml();
Element element = file.getElementById(inId);
if( element == null )
{
element = file.createElement();
file.add(element);
}
element.addAttribute("id", inId);
element.setText(inName);
getXmlArchive().saveXml(file, null);
}
*/
public String resolveCatalogId(String inCatalogId, String inSearchType)
{
if("searchtypes".equals(inSearchType)){
return inCatalogId;
}
if(inSearchType == null){
return inCatalogId;
}
Searcher typeSearcher = getSearcher(inCatalogId, "searchtypes");
if( typeSearcher.getPropertyDetails().size() == 0) //Not used in the system catalog
{
if( inSearchType.equals("user") || inSearchType.equals("group"))
{
return "system";
}
return inCatalogId;
}
Data catalogdata = (Data)typeSearcher.searchById(inSearchType);
if(catalogdata != null)
{
return catalogdata.get("catalogid");
}
else
{
if( inSearchType.equals("user") || inSearchType.equals("group"))
{
return "system";
}
}
return inCatalogId;
}
public QueryBuilder query(String inCatalogId, String inSearchType)
{
Searcher searcher = getSearcher(inCatalogId, inSearchType);
if( searcher == null)
{
return null;
}
return searcher.query();
}
public LockManager getLockManager(String inCatalogId)
{
LockManager manager = (LockManager)getModuleManager().getBean(inCatalogId,"lockManager");
return manager;
}
}