/*
* Copyright (C) 2004 Paul Browne, http://www.firstpartners.net,
* built with the help of Fast-Soft (fastsoftdev@yahoo.com)
*
* released under terms of the GPL license
* http://www.opensource.org/licenses/gpl-license.php
*
* This product includes software developed by the
* Apache Software Foundation (http://www.apache.org)."
*
* This product includes software developed by the
* Spring Framework Project (http://www.springframework.org)."
*
*/
package net.fp.rp.search.mid.category;
import java.io.File;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.fp.rp.common.exception.RpException;
import net.fp.rp.search.back.datastore.BasicFeedbackDataStore;
import net.fp.rp.search.back.struct.CategoryStruct;
import net.fp.rp.search.common.AddInfo;
import net.fp.rp.search.common.util.Util;
import net.fp.rp.search.mid.global.PluginManager;
import net.fp.rp.search.plugins.ICategoryManager;
import net.fp.rp.search.plugins.IDataExtractor;
import net.fp.rp.search.plugins.INewInformation;
import net.fp.rp.search.plugins.events.IInterestedInAdd;
import net.fp.rp.search.plugins.events.IInterestedInFeedback;
import org.apache.log4j.Logger;
/**
* A Category is one set of data within the link KnowledgeSphere.
*
* When use Simple Category Manager, we do not subdivde the knowledgebase (like we
* can with @see CategoryManager)
*
* The Category is responsible for managing the Lucene Index.
*
* It does not use threading
*
* @author brownpa
* @author Firstpartners.net
* @version 1.3
* Copyright @link www.firstpartners.net/red
*/
public class SimpleCategoryManager implements IInterestedInAdd, ICategoryManager {
/** Logger for this class and subclasses */
protected final Logger logger = Logger.getLogger(getClass());
/** Category root */
private String root;
/** Default category name */
private String defaultCategName;
/** Maxim length for the category name */
private int maxLengthCategName;
/** Pattern for generation of the category name */
private String patternCategName;
/** List of the category struct objects */
private LinkedList categoryList;
/** The default system extraction depth */
private int systemDepthLevel;
/**
* Whether we use threading or not
*/
private boolean useThreading =false;
/**
* Creates a new CategoryManager object.
*/
private SimpleCategoryManager() {
categoryList = new LinkedList();
}
/**
* Called by the PluginManager on each plugin when this class is first
* loaded
*/
public void onLoad() {
logger.info("Category Manager start the onLoad process ");
//1. get the list of categories
//2. get the original location for each category (category location from
//the first model inside the caetgory
//3. add the information from original locations in separate thread
//iterate in the directory and load all the category data
File categFolders = new File(root);
if (categFolders.isDirectory() && categFolders.exists()) {
File[] list = categFolders.listFiles();
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
//found it a category
String categName = list[i].getName();
if (! categName.equalsIgnoreCase( BasicFeedbackDataStore.DEFAULT_SPECIAL_DATA)) {
//Trick get the original location from one node
try {
String location = PluginManager.getCategoryStores()
.getOriginalLocation(list[i].getPath());
//add the information from original location to the system using the system depth level
AddInfo info = new AddInfo(location, location,systemDepthLevel);
//go in background
PluginManager.addPluginThread(this, info,useThreading);
} catch (RpException e) {
logger.warn("Category original url cannot be read it ",
e);
}
}
}
}
}
// //notify BasicInteligence to rescore
// //background process to see if exists running plugins, if not ->
// //activate the the ready for feedback process
// logger.info("Mark the feedback plugins as ready for feedback recalculation process");
// Thread t = new Thread(new Runnable() {
// public void run() {
// //till the PluginManager is in add process wait,
// //the InterestedInFeedbackPlugins will wait;
// while (PluginManager.isInAddProcess());
//
// logger.info("Add.Plugins - are terminated. The feedback background score recalculation can be started");
// //mark the plugins as ready for feedback;
// try {
// IInterestedInFeedback[] feedbackPlugins = PluginManager.getInterestedInFeedback();
// for (int i = 0; i < feedbackPlugins.length; i++) {
// feedbackPlugins[i].setReadyForFeedbackCalculation( true );
// }
// } catch (RpException e) {
// //Exception in getting the FeedbackDataStore
// logger.warn("Exception in getting the feedbackdatastore " +
// e.getMessage(), e);
// }
// }
// });
// t.setPriority(Thread.MIN_PRIORITY);
// t.start();
//no need to notify BasicIndex to reindex (because the addInfo already did it)
logger.info("CategoryManager finished the onload process");
}
/**
* Add a new piece of information to the system
*
* @param info Information to be added to the system
*
* @throws RpException Error occur in process the information
*/
public void addInformation(INewInformation info) throws RpException {
logger.info("CategoryManager add a new piece of information to the system :" +
info.getUri());
//detect which data extractor is more apropiate to handle the data
IDataExtractor extractor = PluginManager.getBestExtractor( info) ;
if (extractor != null) {
logger.debug("Extractor " + extractor.getClass().getName() +
" will handle the information " + info.getUri());
//validate if the name is specified
String defaultCategName = info.getCategoryName();
if (Util.isEmpty(defaultCategName)) {
logger.debug(
"Name of the category was not specified .. generate new one using the original location");
defaultCategName = getCategoryName(info.getCategoryLocation());
}
//validate location to be unique
String uniqueName = getAndAddUniqueCategoryName(defaultCategName,
info.getCategoryLocation());
//create a basic category
BasicCategory basic = new BasicCategory(info.getCategoryLocation(),
uniqueName, info.getUri(), extractor); // new BasicCategoryStore(),PluginManager.getIndexManager());
basic.generateCategoryData(this);
} else {
logger.warn("No extractor can handle the specified information " +
info.getUri());
throw new RpException("categorymanager.add.nohandler",
new Object[] { info.getUri() });
}
}
/**
* Generate the name for the category using a preselected one . The name of
* the category should be unique in the system. In case of the category
* name already exists, a new generation will occur using the default
* Category Name specified in the global property file.
*
* @param name Name of the category generated upon the information name
* @param location DOCUMENT ME!
*
* @return Unique name in the system for the category name
*/
private String getAndAddUniqueCategoryName(final String name,
final String location) {
String uniqueName;
int count = 0;
for (int i = 0; i < categoryList.size(); i++) {
CategoryStruct category = (CategoryStruct) categoryList.get(i);
if (category.getName().startsWith(name)) {
count++;
}
}
if (count != 0) {
uniqueName = defaultCategName + count;
} else {
uniqueName = name;
}
//add to the list
categoryList.add(new CategoryStruct(uniqueName, location));
return uniqueName;
}
/**
* Get the location name upon the info data (specified uri location)
*
* @param location Uri location
*
* @return Location name for the specified uri location
*/
private String getCategoryName(final String location) {
StringBuffer categName = new StringBuffer();
Pattern pattern = Pattern.compile(patternCategName);
for (int i = 0; i < location.length(); i++) {
char c = location.charAt(i);
Matcher m = pattern.matcher(String.valueOf(c));
if (m.matches()) {
categName.append(c);
}
}
//return only the specified maxim length
if (categName.toString().length() > maxLengthCategName) {
return categName.toString().substring(0, maxLengthCategName);
} else {
return categName.toString();
}
}
/**
* Get the category list
*
* @return Category list
*/
public LinkedList getCategoryList() {
return categoryList;
}
/**
* Set the category list
*
* @param categoryList Category list to set
*/
public void setCategoryList(LinkedList categoryList) {
this.categoryList = categoryList;
}
/**
* Get the default category name
*
* @return Default category name
*/
public String getDefaultCategName() {
return defaultCategName;
}
/**
* Set the default category name
*
* @param defaultCategName Default category name to set
*/
public void setDefaultCategName(String defaultCategName) {
this.defaultCategName = defaultCategName;
}
/**
* Get the maxim length for the category name
*
* @return Maxim length for the category name
*/
public int getMaxLengthCategName() {
return maxLengthCategName;
}
/**
* Set the maxim length for the category name
*
* @param maxCategLength Maxim length for category to set
*/
public void setMaxLengthCategName(int maxCategLength) {
this.maxLengthCategName = maxCategLength;
}
/**
* Get the pattern of the category name
*
* @return Category name pattern
*/
public String getPatternCategName() {
return patternCategName;
}
/**
* Set the category name pattern
*
* @param patternCategName Category name pattern to be used
*/
public void setPatternCategName(String patternCategName) {
this.patternCategName = patternCategName;
}
/**
* Get the root folder of the category manager
*
* @return root folder of the category manager
*/
public String getRoot() {
return root;
}
/**
* Set the root folder of the plugin manager.
*
* @param root Root folder of the plugin manager ti set.
*/
public void setRoot(String root) {
this.root = root;
}
/**
* @return Returns the systemDepthLevel.
*/
public int getSystemDepthLevel() {
return systemDepthLevel;
}
/**
* @param systemDepthLevel The systemDepthLevel to set.
*/
public void setSystemDepthLevel(int systemDepthLevel) {
this.systemDepthLevel = systemDepthLevel;
}
}