You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by si...@apache.org on 2012/01/26 16:37:08 UTC

svn commit: r1236246 [2/7] - in /incubator/stanbol/trunk: cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/mapping/ cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/mapping/ contenthub/ contenthub/bundlelist/src/main/bundl...

Added: incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDPathUtils.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDPathUtils.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDPathUtils.java (added)
+++ incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDPathUtils.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,337 @@
+package org.apache.stanbol.contenthub.ldpath.solr;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import nu.xom.Attribute;
+import nu.xom.Builder;
+import nu.xom.Document;
+import nu.xom.Element;
+import nu.xom.Nodes;
+import nu.xom.ParsingException;
+import nu.xom.Serializer;
+import nu.xom.ValidityException;
+
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.stanbol.contenthub.ldpath.backend.clerezza.ClerezzaBackend;
+import org.apache.stanbol.contenthub.servicesapi.Constants;
+import org.apache.stanbol.contenthub.servicesapi.ldpath.LDPathException;
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.model.fields.FieldMapping;
+import at.newmedialab.ldpath.model.programs.Program;
+import at.newmedialab.ldpath.parser.ParseException;
+import at.newmedialab.ldpath.parser.RdfPathParser;
+
+/**
+ * @author anil.sinaci
+ * 
+ */
+public class LDPathUtils {
+    private static final Logger logger = LoggerFactory.getLogger(LDPathUtils.class);
+
+    public static final String NS_XSD = "http://www.w3.org/2001/XMLSchema#";
+
+    private static final String SOLR_CORE_PATH = "solr/core/";
+    private static final String SOLR_TEMPLATE_NAME = "template";
+    private static final String SOLR_TEMPLATE_ZIP = SOLR_TEMPLATE_NAME + ".zip";
+    private static final String SOLR_TEMPLATE_SCHEMA = SOLR_TEMPLATE_NAME + "/conf/schema-template.xml";
+    private static final String SOLR_SCHEMA = "/conf/schema.xml";
+
+    private static final int BUFFER_SIZE = 8024;
+
+    private static final Set<String> SOLR_FIELD_OPTIONS;
+    static {
+        HashSet<String> opt = new HashSet<String>();
+        opt.add("default");
+        opt.add("indexed");
+        opt.add("stored");
+        opt.add("compressed");
+        opt.add("compressThreshold");
+        opt.add("multiValued");
+        opt.add("omitNorms");
+        opt.add("omitTermFreqAndPositions");
+        opt.add("termVectors");
+        opt.add("termPositions");
+        opt.add("termOffsets");
+
+        SOLR_FIELD_OPTIONS = Collections.unmodifiableSet(opt);
+    }
+    private static final String SOLR_COPY_FIELD_OPTION = "copy";
+
+    /**
+     * A map mapping from XSD types to SOLR types.
+     */
+    private static final Map<String,String> xsdSolrTypeMap;
+    static {
+        Map<String,String> typeMap = new HashMap<String,String>();
+
+        typeMap.put(NS_XSD + "decimal", "long");
+        typeMap.put(NS_XSD + "integer", "int");
+        typeMap.put(NS_XSD + "long", "long");
+        typeMap.put(NS_XSD + "short", "int");
+        typeMap.put(NS_XSD + "double", "double");
+        typeMap.put(NS_XSD + "float", "float");
+        typeMap.put(NS_XSD + "dateTime", "date");
+        typeMap.put(NS_XSD + "date", "date");
+        typeMap.put(NS_XSD + "time", "date");
+        typeMap.put(NS_XSD + "boolean", "boolean");
+        typeMap.put(NS_XSD + "anyURI", "uri");
+        typeMap.put(NS_XSD + "string", "string");
+
+        xsdSolrTypeMap = Collections.unmodifiableMap(typeMap);
+    }
+
+    private Bundle bundle;
+
+    public LDPathUtils(Bundle bundle) {
+        this.bundle = bundle;
+    }
+
+    /**
+     * Return the SOLR field type for the XSD type passed as argument. The xsdType needs to be a fully
+     * qualified URI. If no field type is defined, will return null.
+     * 
+     * @param xsdType
+     *            a URI identifying the XML Schema datatype
+     * @return
+     */
+    public String getSolrFieldType(String xsdType) {
+        String result = xsdSolrTypeMap.get(xsdType);
+        if (result == null) {
+            logger.error("Could not find SOLR field type for type " + xsdType);
+            return null;
+        } else {
+            return result;
+        }
+    }
+
+    public static Reader constructReader(String program) throws LDPathException {
+        try {
+            return new InputStreamReader(new ByteArrayInputStream(
+                    program.getBytes(Constants.DEFAULT_ENCODING)), Constants.DEFAULT_ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            String msg = String.format("Encoding {} should be supported by the system",
+                Constants.DEFAULT_ENCODING);
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+    }
+
+    private Program<Resource> getLDPathProgram(String ldPathProgram) throws LDPathException {
+        if (ldPathProgram == null || ldPathProgram.isEmpty()) {
+            String msg = "LDPath Program cannot be null.";
+            logger.error(msg);
+            throw new LDPathException(msg);
+        }
+        MGraph mGraph = new SimpleMGraph();
+        RDFBackend<Resource> rdfBackend = new ClerezzaBackend(mGraph);
+        RdfPathParser<Resource> LDparser = new RdfPathParser<Resource>(rdfBackend,
+                constructReader(ldPathProgram));
+        Program<Resource> program = null;
+        try {
+            program = LDparser.parseProgram();
+        } catch (ParseException e) {
+            String msg = "Cannot parse LDPath Program";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        return program;
+    }
+
+    public ArchiveInputStream createSchemaArchive(String coreName, String ldPathProgram) throws LDPathException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
+        ArchiveStreamFactory asf = new ArchiveStreamFactory();
+        TarArchiveOutputStream tarOutputStream = null;
+        try {
+            tarOutputStream = (TarArchiveOutputStream) asf.createArchiveOutputStream("tar", out);
+        } catch (ArchiveException e) {
+            String msg = "Cannot create an empty tar archive";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+
+        try {
+            InputStream is = getSolrTemplateStream();
+            ZipArchiveInputStream zis = new ZipArchiveInputStream(is);
+            ZipArchiveEntry ze = null;
+            byte[] schemaFile = null;
+            while ((ze = zis.getNextZipEntry()) != null) {
+                if (SOLR_TEMPLATE_SCHEMA.equals(ze.getName())) {
+                    schemaFile = createSchemaXML(coreName, getLDPathProgram(ldPathProgram),
+                        IOUtils.toByteArray(zis));
+                    TarArchiveEntry te = new TarArchiveEntry(coreName + SOLR_SCHEMA);
+                    te.setSize(schemaFile.length);
+                    tarOutputStream.putArchiveEntry(te);
+                    tarOutputStream.write(schemaFile);
+                    tarOutputStream.closeArchiveEntry();
+                } else {
+                    TarArchiveEntry te = new TarArchiveEntry(ze.getName().replaceAll(SOLR_TEMPLATE_NAME,
+                        coreName));
+                    te.setSize(ze.getSize());
+                    tarOutputStream.putArchiveEntry(te);
+                    tarOutputStream.write(IOUtils.toByteArray(zis));
+                    tarOutputStream.closeArchiveEntry();
+                }
+
+            }
+            if (schemaFile == null) {
+                throw new LDPathException("Schema template ZIP should include: " + SOLR_TEMPLATE_SCHEMA);
+            }
+            tarOutputStream.finish();
+            tarOutputStream.close();
+        } catch (IOException e) {
+            logger.error("", e);
+            throw new LDPathException(e);
+        }
+
+        ArchiveInputStream ret;
+        try {
+            ret = asf.createArchiveInputStream(new ByteArrayInputStream(out.toByteArray()));
+        } catch (ArchiveException e) {
+            String msg = "Cannot create a final tar archive while creating an ArchiveInputStream to create a Solr core";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        return ret;
+    }
+
+    private InputStream getSolrTemplateStream() throws LDPathException {
+        String solrCorePath = SOLR_CORE_PATH;
+        if (!solrCorePath.endsWith(File.separator)) solrCorePath += File.separator;
+        String templateZip = solrCorePath + SOLR_TEMPLATE_ZIP;
+
+        URL resource = bundle.getEntry(templateZip);
+        InputStream is = null;
+        try {
+            is = resource != null ? resource.openStream() : null;
+        } catch (IOException e) {
+            String msg = "Cannot open input stream on URL resource gathered from bundle.getEntry()";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        if (is == null) {
+            String msg = "Solr Template ZIP cannot be found in:" + templateZip;
+            logger.error(msg);
+            throw new LDPathException(msg);
+        }
+        return is;
+    }
+
+    private byte[] createSchemaXML(String coreName, Program<Resource> program, byte[] template) throws LDPathException {
+
+        Builder xmlParser = new Builder();
+        ByteArrayInputStream is = new ByteArrayInputStream(template);
+        Document doc = null;
+        try {
+            doc = xmlParser.build(is);
+        } catch (ValidityException e) {
+            String msg = "SOLR schema-template is not a valid XML";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        } catch (ParsingException e) {
+            String msg = "SOLR schema-template cannot be parsed";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        } catch (IOException e) {
+            logger.error("", e);
+            throw new LDPathException(e);
+        }
+        Nodes fieldsNodes = doc.query("/schema/fields");
+        if (fieldsNodes.size() != 1) {
+            throw new LDPathException("Template is an invalid SOLR schema. It should be a valid a byte array");
+        }
+        Element fieldsNode = (Element) fieldsNodes.get(0);
+        Element schemaNode = (Element) fieldsNode.getParent();
+
+        for (FieldMapping<?,Resource> fieldMapping : program.getFields()) {
+            String fieldName = fieldMapping.getFieldName();
+            String solrType = getSolrFieldType(fieldMapping.getFieldType());
+
+            if (solrType == null) {
+                logger.error("field {} has an invalid field type; ignoring field definition", fieldName);
+            } else {
+                Element fieldElement = new Element("field");
+                fieldElement.addAttribute(new Attribute("name", fieldName));
+                fieldElement.addAttribute(new Attribute("type", solrType));
+                // Set the default properties
+                fieldElement.addAttribute(new Attribute("stored", "true"));
+                fieldElement.addAttribute(new Attribute("indexed", "true"));
+                fieldElement.addAttribute(new Attribute("multiValued", "true"));
+
+                // Handle extra field configuration
+                final Map<String,String> fieldConfig = fieldMapping.getFieldConfig();
+                if (fieldConfig != null) {
+                    for (String attr : fieldConfig.keySet()) {
+                        if (SOLR_FIELD_OPTIONS.contains(attr)) {
+                            fieldElement.addAttribute(new Attribute(attr, fieldConfig.get(attr)));
+                        }
+                    }
+                }
+                fieldsNode.appendChild(fieldElement);
+
+                if (fieldConfig != null && fieldConfig.keySet().contains(SOLR_COPY_FIELD_OPTION)) {
+                    String[] copyFields = fieldConfig.get(SOLR_COPY_FIELD_OPTION).split(",\\s*");
+                    for (String copyField : copyFields) {
+                        Element copyElement = new Element("copyField");
+                        copyElement.addAttribute(new Attribute("source", fieldName));
+                        copyElement.addAttribute(new Attribute("dest", copyField));
+                        schemaNode.appendChild(copyElement);
+                    }
+                } else {
+                    Element copyElement = new Element("copyField");
+                    copyElement.addAttribute(new Attribute("source", fieldName));
+                    copyElement.addAttribute(new Attribute("dest", "text_all"));
+                    schemaNode.appendChild(copyElement);
+                }
+
+            }
+        }
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
+        Serializer serializer = null;
+        try {
+            serializer = new Serializer(out, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            String msg = "Unsupported encoding exception for UTF-8 while serializing constructed schema.xml for Solr";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        serializer.setIndent(4);
+        try {
+            serializer.write(doc);
+            out.close();
+        } catch (IOException e) {
+            logger.error("", e);
+            throw new LDPathException(e);
+        }
+
+        return out.toByteArray();
+    }
+
+}

Added: incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDProgramManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDProgramManagerImpl.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDProgramManagerImpl.java (added)
+++ incubator/stanbol/trunk/contenthub/ldpath/src/main/java/org/apache/stanbol/contenthub/ldpath/solr/LDProgramManagerImpl.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,232 @@
+package org.apache.stanbol.contenthub.ldpath.solr;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.stanbol.commons.solr.managed.ManagedSolrServer;
+import org.apache.stanbol.contenthub.ldpath.backend.clerezza.ClerezzaBackend;
+import org.apache.stanbol.contenthub.servicesapi.ldpath.LDPathException;
+import org.apache.stanbol.contenthub.servicesapi.ldpath.LDProgramCollection;
+import org.apache.stanbol.contenthub.servicesapi.ldpath.LDProgramManager;
+import org.apache.stanbol.contenthub.servicesapi.store.StoreException;
+import org.apache.stanbol.contenthub.store.solr.manager.SolrCoreManager;
+import org.apache.stanbol.enhancer.servicesapi.rdf.Properties;
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.newmedialab.ldpath.LDPath;
+import at.newmedialab.ldpath.exception.LDPathParseException;
+
+/**
+ * Implementation of the LDProgramManager which managed the LDPath Programs submitted to the system. This
+ * manager creates Solr core for every uploaded program and manages them along with their programs.
+ * 
+ * @author anil.pacaci
+ * @author anil.sinaci
+ * 
+ */
+
+@Component(immediate = false)
+@Service
+public class LDProgramManagerImpl implements LDProgramManager {
+
+    private final Logger logger = LoggerFactory.getLogger(LDProgramManagerImpl.class);
+
+    private final static String DEFAULT_ROOT_PATH = "datafiles/contenthub";
+    private final static String DEFAULT_FOLDER_NAME = "ldpath";
+
+    private File managedProgramsDir;
+
+    private Map<String,String> nameProgramMap = new HashMap<String,String>();
+
+    private LDPathUtils ldPathUtils;
+
+    private Bundle bundle;
+
+    @Reference
+    private ManagedSolrServer managedSolrServer;
+
+    @Activate
+    public void activator(ComponentContext cc) throws LDPathException, IOException {
+        bundle = cc.getBundleContext().getBundle();
+        ldPathUtils = new LDPathUtils(bundle);
+
+        String slingHome = cc.getBundleContext().getProperty("sling.home");
+        if (!slingHome.endsWith(File.separator)) slingHome += File.separator;
+        managedProgramsDir = new File(slingHome + DEFAULT_ROOT_PATH, DEFAULT_FOLDER_NAME);
+
+        // if directory for programs does not exist, create it
+        if (!managedProgramsDir.exists()) {
+            if (managedProgramsDir.mkdirs()) {
+                logger.info("Directory for programs created succesfully");
+            } else {
+                logger.error("Directory for programs COULD NOT be created");
+                throw new LDPathException("Directory : " + managedProgramsDir.getAbsolutePath()
+                                          + " cannot be created");
+            }
+        }
+
+        // means that directory for programs created succesfully or it already exists
+        // now need to get all programs to the memory
+        File[] programs = managedProgramsDir.listFiles();
+        for (File programFile : programs) {
+            if (SolrCoreManager.getInstance(bundle.getBundleContext(), managedSolrServer).isManagedSolrCore(
+                programFile.getName())) {
+                // consider only if the corresponding solr core exists
+                String program = FileUtils.readFileToString(programFile);
+                nameProgramMap.put(programFile.getName(), program);
+            } else {
+                programFile.delete();
+            }
+        }
+    }
+
+    @Override
+    public void submitProgram(String programName, String ldPathProgram) throws LDPathException {
+        if (programName == null || programName.isEmpty()) {
+            String msg = "Program name cannot be null or empty";
+            logger.error(msg);
+            throw new LDPathException(msg);
+        }
+
+        if (ldPathProgram == null || ldPathProgram.isEmpty()) {
+            String msg = "LDPath program cannot be null or empty";
+            logger.error(msg);
+            throw new LDPathException(msg);
+        }
+
+        // Checks whether there is already a program with the same name
+        if (nameProgramMap.containsKey(programName)) {
+            String msg = String.format("There is already an LDProgram with name :  " + programName);
+            logger.error(msg);
+            throw new LDPathException(msg);
+        }
+
+        try {
+            SolrCoreManager.getInstance(bundle.getBundleContext(), managedSolrServer).createSolrCore(
+                programName, ldPathUtils.createSchemaArchive(programName, ldPathProgram));
+        } catch (LDPathException e) {
+            logger.error("Solr Core Service could NOT initialize Solr core with name : {}", programName);
+            throw e;
+        } catch (StoreException e) {
+            throw new LDPathException(e.getMessage(), e);
+        }
+
+        String programFilePath = managedProgramsDir.getAbsolutePath() + File.separator + programName;
+        try {
+            FileUtils.writeStringToFile(new File(programFilePath), ldPathProgram);
+        } catch (IOException e) {
+            String msg = "Cannot write the LDPath program to file. The state is inconsistent now. "
+                         + "The Solr core is created, but corresponding LDPath program does not exist.";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        nameProgramMap.put(programName, ldPathProgram);
+
+        logger.info("SolrCore for the {} created succesfully and corresponding LDPath program saved ",
+            programName);
+    }
+
+    @Override
+    public void submitProgram(String programName, Reader ldPathProgramReader) throws LDPathException {
+        String ldPathProgram = null;
+        try {
+            ldPathProgram = IOUtils.toString(ldPathProgramReader);
+        } catch (IOException e) {
+            String msg = "Cannot convert to String from Reader (ldPathProgramReader) in submitProgram";
+            logger.error(msg, e);
+            throw new LDPathException(msg, e);
+        }
+        submitProgram(programName, ldPathProgram);
+    }
+
+    @Override
+    public String getProgramByName(String programName) {
+        if (programName == null || programName.isEmpty()) {
+            logger.error("Should be given a valid program name");
+            throw new IllegalArgumentException("Program name cannot be null or empty");
+        }
+
+        if (!nameProgramMap.containsKey(programName)) {
+            logger.warn("No program named {}", programName);
+            return null;
+        }
+
+        return nameProgramMap.get(programName);
+    }
+
+    @Override
+    public void deleteProgram(String programName) {
+        if (isManagedProgram(programName)) {
+            SolrCoreManager.getInstance(bundle.getBundleContext(), managedSolrServer).deleteSolrCore(programName);
+            nameProgramMap.remove(programName);
+            String programFilePath = managedProgramsDir.getAbsolutePath() + File.separator + programName;
+            File programFile = new File(programFilePath);
+            programFile.delete();
+        }
+    }
+
+    @Override
+    public boolean isManagedProgram(String programName) {
+        if (nameProgramMap.containsKey(programName)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public LDProgramCollection retrieveAllPrograms() {
+        return new LDProgramCollection(nameProgramMap);
+    }
+
+    @Override
+    public Map<String,Collection<?>> executeProgram(String programName, MGraph graph) throws LDPathException {
+        Map<String,Collection<?>> results = new HashMap<String,Collection<?>>();
+        LDPath<Resource> ldpath = new LDPath<Resource>(new ClerezzaBackend(graph));
+        String ldPathProgram = getProgramByName(programName);
+        Iterator<Triple> it = graph.filter(null, Properties.ENHANCER_ENTITY_REFERENCE, null);
+        while(it.hasNext()) {
+            try {
+                Map<String,Collection<?>> entityResults = ldpath.programQuery(it.next().getObject(), LDPathUtils.constructReader(ldPathProgram));
+                for(Entry<String,Collection<?>> entry : entityResults.entrySet()) {
+                    if(results.containsKey(entry.getKey())) {
+                        @SuppressWarnings("unchecked")
+                        Collection<Object> resultCollection = (Collection<Object>) results.get(entry.getKey());
+                        @SuppressWarnings("unchecked")
+                        Collection<Object> tmpCol = (Collection<Object>) entry.getValue();
+                        for(Object o : tmpCol) {
+                            resultCollection.add(o);
+                        }
+                    } else {
+                        results.put(entry.getKey(), new ArrayList<Object>(entry.getValue()));
+                    }
+                }
+            } catch (LDPathParseException e) {
+                logger.error("Should never happen!!!!!", e);
+            } catch (ClassCastException e) {
+                logger.error("Cannot cast result collection to Collection<Object>", e);
+            }
+        }
+        return results;
+        
+    }
+
+}

Added: incubator/stanbol/trunk/contenthub/ldpath/src/main/resources/solr/core/template.zip
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/ldpath/src/main/resources/solr/core/template.zip?rev=1236246&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/stanbol/trunk/contenthub/ldpath/src/main/resources/solr/core/template.zip
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: incubator/stanbol/trunk/contenthub/parent/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/parent/pom.xml?rev=1236246&r1=1236245&r2=1236246&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/parent/pom.xml (original)
+++ incubator/stanbol/trunk/contenthub/parent/pom.xml Thu Jan 26 15:37:02 2012
@@ -40,6 +40,11 @@
     <url>http://incubator.apache.org/stanbol</url>
   </scm>
 
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <stanbol-version>0.9.0-incubating-SNAPSHOT</stanbol-version>
+  </properties>
+
   <build>
     <pluginManagement>
       <plugins>
@@ -56,92 +61,4 @@
     </pluginManagement>
   </build>
 
-  <dependencyManagement>
-    <dependencies>
-
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>org.apache.stanbol.contenthub.core</artifactId>
-        <version>0.9.0-incubating-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>org.apache.stanbol.contenthub.store.solr</artifactId>
-        <version>0.9.0-incubating-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>org.apache.stanbol.contenthub.web</artifactId>
-        <version>0.9.0-incubating-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>org.apache.stanbol.contenthub.search.engines.wordnet</artifactId>
-        <version>0.9.0-incubating-SNAPSHOT</version>
-      </dependency>
-
-      <!-- Search External -->
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>edu.smu.tspell.jaws</artifactId>
-        <version>1.2</version>
-      </dependency>
-      <!-- Search Helper -->
-      <dependency>
-        <groupId>org.apache.stanbol</groupId>
-        <artifactId>org.apache.stanbol.contenthub.helper.cnn</artifactId>
-        <version>0.9.0-incubating-SNAPSHOT</version>
-      </dependency>
-
-      <!-- Clerezza -->
-      <dependency>
-        <groupId>org.apache.clerezza</groupId>
-        <artifactId>rdf.jena.facade</artifactId>
-        <version>0.12-incubating-SNAPSHOT</version>
-      </dependency>
-
-      <!-- Wordnet -->
-      <dependency>
-        <groupId>edu.smu.tspell</groupId>
-        <artifactId>jaws</artifactId>
-        <version>1.2</version>
-        <type>jar</type>
-        <scope>compile</scope>
-      </dependency>
-
-      <!-- JTidy -->
-      <dependency>
-        <groupId>jtidy</groupId>
-        <artifactId>jtidy</artifactId>
-        <version>4aug2000r7-dev</version>
-        <type>jar</type>
-        <scope>compile</scope>
-      </dependency>
-
-      <!-- JAXB (Although jaxb is part of Java 6 at runtime on Felix ClassNotFoundExceptions 
-        of jaxb classes are thrown) -->
-      <dependency>
-        <groupId>com.sun.xml.bind</groupId>
-        <artifactId>jaxb-impl</artifactId>
-        <version>2.2.2</version>
-      </dependency>
-
-      <!-- Jersey -->
-      <dependency>
-        <groupId>com.sun.jersey</groupId>
-        <artifactId>jersey-client</artifactId>
-        <version>${jersey-version}</version>
-        <scope>provided</scope>
-      </dependency>
-
-    </dependencies>
-  </dependencyManagement>
-
-  <repositories>
-    <repository>
-      <id>at.newmedialab</id>
-      <name>KiWi Project Snapshot Repository</name>
-      <url>http://devel.kiwi-project.eu:8080/nexus/content/repositories/snapshots/</url>
-    </repository>
-  </repositories>
 </project>

Modified: incubator/stanbol/trunk/contenthub/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/pom.xml?rev=1236246&r1=1236245&r2=1236246&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/pom.xml (original)
+++ incubator/stanbol/trunk/contenthub/pom.xml Thu Jan 26 15:37:02 2012
@@ -1,28 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to 
+  You under the Apache License, Version 2.0 (the "License"); you may not use 
+  this file except in compliance with the License. You may obtain a copy of 
+  the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+  by applicable law or agreed to in writing, software distributed under the 
+  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific 
+  language governing permissions and limitations under the License. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
 
+  <parent>
+    <groupId>org.apache.stanbol</groupId>
+    <artifactId>org.apache.stanbol.contenthub.parent</artifactId>
+    <version>0.9.0-incubating-SNAPSHOT</version>
+    <relativePath>./parent</relativePath>
+  </parent>
+
   <groupId>org.apache.stanbol</groupId>
   <artifactId>org.apache.stanbol.contenthub.reactor</artifactId>
-  <version>0.9.0-incubating-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>Apache Stanbol Contenthub Reactor</name>
@@ -34,21 +34,21 @@
 
   <scm>
     <connection>
-    scm:svn:http://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/
+		scm:svn:http://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/
     </connection>
     <developerConnection>
-    scm:svn:https://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/
+		scm:svn:https://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/
     </developerConnection>
   </scm>
 
   <modules>
     <module>parent</module>
-    <module>api</module>
-    <module>core</module>
+    <module>servicesapi</module>
+    <module>store</module>
     <module>search</module>
-    <module>helper/cnn-importer</module>
+    <module>crawler/cnn</module>
     <module>web</module>
     <module>bundlelist</module>
-    <module>store</module>
+    <module>ldpath</module>
   </modules>
 </project>

Propchange: incubator/stanbol/trunk/contenthub/search/featured/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Jan 26 15:37:02 2012
@@ -0,0 +1,4 @@
+.settings
+target
+.classpath
+.project

Added: incubator/stanbol/trunk/contenthub/search/featured/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/featured/pom.xml?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/featured/pom.xml (added)
+++ incubator/stanbol/trunk/contenthub/search/featured/pom.xml Thu Jan 26 15:37:02 2012
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to 
+  You under the Apache License, Version 2.0 (the "License"); you may not use 
+  this file except in compliance with the License. You may obtain a copy of 
+  the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+  by applicable law or agreed to in writing, software distributed under the 
+  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific 
+  language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.stanbol</groupId>
+    <artifactId>org.apache.stanbol.contenthub.parent</artifactId>
+    <version>0.9.0-incubating-SNAPSHOT</version>
+    <relativePath>../../parent</relativePath>
+  </parent>
+
+  <artifactId>org.apache.stanbol.contenthub.search.featured</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Apache Stanbol Featured Search</name>
+
+  <description>Aggregates the results of SolrSearch and RelatedKeywordSearch</description>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.contenthub.servicesapi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.contenthub.store.solr</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.contenthub.search.solr</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+</project>

Added: incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchImpl.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchImpl.java (added)
+++ incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchImpl.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,318 @@
+package org.apache.stanbol.contenthub.search.featured;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.clerezza.rdf.core.Literal;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.response.FacetField;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.stanbol.commons.solr.managed.ManagedSolrServer;
+import org.apache.stanbol.contenthub.search.featured.util.SolrContentItemConverter;
+import org.apache.stanbol.contenthub.search.solr.util.SolrQueryUtil;
+import org.apache.stanbol.contenthub.servicesapi.Constants;
+import org.apache.stanbol.contenthub.servicesapi.search.SearchException;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.FeaturedSearch;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.ResultantDocument;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.SearchResult;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeyword;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeywordSearchManager;
+import org.apache.stanbol.contenthub.servicesapi.search.solr.SolrSearch;
+import org.apache.stanbol.contenthub.servicesapi.store.StoreException;
+import org.apache.stanbol.contenthub.servicesapi.store.vocabulary.SolrVocabulary;
+import org.apache.stanbol.contenthub.store.solr.manager.SolrCoreManager;
+import org.apache.stanbol.enhancer.servicesapi.ContentItem;
+import org.apache.stanbol.enhancer.servicesapi.EnhancementException;
+import org.apache.stanbol.enhancer.servicesapi.EnhancementJobManager;
+import org.apache.stanbol.enhancer.servicesapi.helper.InMemoryContentItem;
+import org.apache.stanbol.enhancer.servicesapi.rdf.Properties;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+@Service
+public class FeaturedSearchImpl implements FeaturedSearch {
+
+    private final static Logger log = LoggerFactory.getLogger(FeaturedSearchImpl.class);
+
+    private static Map<String,List<String>> stopWords;
+
+    static {
+        stopWords = new HashMap<String,List<String>>();
+        // TODO read stopwords from the files located in default solr core zip
+        List<String> englishStopWords = Arrays.asList("i", "me", "my", "myself", "we", "our", "ours",
+            "ourselves", "you", "your", "yours", "yourself", "yourselves", "he", "him", "his", "himself",
+            "she", "her", "hers", "herself", "it", "its", "itself", "they", "them", "their", "theirs",
+            "themselves", "what", "which", "who", "whom", "this", "that", "these", "those", "am", "is",
+            "are", "was", "were", "be  ", "been", "being", "have", "has ", "had ", "having", "do", "does",
+            "did ", "doing", "would", "should", "could", "ought", "a", "an", "the", "and", "but", "if", "or",
+            "because", "as", "until", "while", "", "of", "at", "by", "for", "with", "about", "against",
+            "between", "into", "through", "during", "before", "after", "above", "below", "to", "from", "up",
+            "down", "in", "out", "on", "off", "over", "under", "again", "further", "then", "once", "here",
+            "there", "when", "where", "why", "how", "all", "any", "both", "each", "few", "more", "most",
+            "other", "some", "such", "no", "nor", "not", "only", "own", "same", "so", "than", "too", "very",
+            "i'm", "you're", "he's", "she's", "it's", "we're", "they're", "i've", "you've", "we've",
+            "they've", "i'd", "you'd", "he'd", "she'd", "we'd", "they'd", "i'll", "you'll", "he'll",
+            "she'll", "we'll", "they'll", "isn't", "aren't", "wasn't", "weren't", "hasn't", "haven't",
+            "hadn't", "doesn't", "don't", "didn't", "won't", "wouldn't", "shan't", "shouldn't", "can't",
+            "cannot", "couldn't", "mustn't", "let's", "that's", "who's", "what's", "here's", "there's",
+            "when's", "where's", "why's", "how's", "of");
+        stopWords.put("en", englishStopWords);
+    }
+
+    @Reference
+    private SolrSearch solrSearch;
+
+    @Reference
+    private RelatedKeywordSearchManager relatedKeywordSearchManager;
+
+    @Reference
+    private ManagedSolrServer managedSolrServer;
+
+    @Reference
+    private EnhancementJobManager enhancementJobManager;
+
+    private BundleContext bundleContext;
+
+    @Activate
+    public void activate(ComponentContext context) {
+        this.bundleContext = context.getBundleContext();
+    }
+
+    @Override
+    public SearchResult search(String queryTerm) throws SearchException {
+        return search(queryTerm, null, null);
+    }
+
+    private List<FacetField> bringAnnotatedFacetsForward(List<FacetField> facets) {
+        List<FacetField> annotatedEntityFacets = new ArrayList<FacetField>();
+        List<FacetField> facetsHavingNullValues = new ArrayList<FacetField>();
+        for (FacetField ff : facets) {
+            String facetName = ff.getName();
+            if (ff.getValues() == null) {
+                facetsHavingNullValues.add(ff);
+            } else if (SolrVocabulary.SolrFieldName.isAnnotatedEntityFacet(facetName)) {
+                annotatedEntityFacets.add(ff);
+            }
+        }
+        for (FacetField ff : annotatedEntityFacets) {
+            facets.remove(ff);
+        }
+        for (FacetField ff : annotatedEntityFacets) {
+            facets.add(0, ff);
+        }
+        for (FacetField ff : facetsHavingNullValues) {
+            facets.remove(ff);
+        }
+        return facets;
+    }
+
+    @Override
+    public SearchResult search(String queryTerm, String ontologyURI, String ldProgramName) throws SearchException {
+        QueryResponse queryResponse = solrSearch.search(queryTerm, ldProgramName);
+        return search(queryTerm, queryResponse, ontologyURI, ldProgramName);
+    }
+
+    private SearchResult search(String queryTerm,
+                                QueryResponse queryResponse,
+                                String ontologyURI,
+                                String ldProgramName) throws SearchException {
+        List<ResultantDocument> resultantDocuments = new ArrayList<ResultantDocument>();
+        for (SolrDocument solrDocument : queryResponse.getResults()) {
+            resultantDocuments.add(SolrContentItemConverter.solrDocument2solrContentItem(solrDocument));
+        }
+        Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords = new HashMap<String,Map<String,List<RelatedKeyword>>>();
+        List<String> queryTerms = tokenizeEntities(queryTerm);
+
+        for (String queryToken : queryTerms) {
+            relatedKeywords.putAll(relatedKeywordSearchManager.getRelatedKeywordsFromAllSources(queryToken,
+                ontologyURI).getRelatedKeywords());
+        }
+        return new FeaturedSearchResult(resultantDocuments,
+                bringAnnotatedFacetsForward(queryResponse.getFacetFields()), relatedKeywords);
+    }
+
+    @Override
+    public SearchResult search(SolrParams solrQuery) throws SearchException {
+        return search(solrQuery, null, null);
+    }
+
+    @Override
+    public SearchResult search(SolrParams solrQuery, String ontologyURI, String ldProgramName) throws SearchException {
+        QueryResponse queryResponse = solrSearch.search(solrQuery, ldProgramName);
+        String queryTerm = SolrQueryUtil.extractQueryTermFromSolrQuery(solrQuery);
+        return search(queryTerm, queryResponse, ontologyURI, ldProgramName);
+    }
+
+    @Override
+    public List<String> getFacetNames() throws SearchException {
+        return getFacetNames(null);
+    }
+
+    @Override
+    public List<String> getFacetNames(String ldProgramName) throws SearchException {
+        SolrServer solrServer = null;
+        try {
+            solrServer = SolrCoreManager.getInstance(bundleContext, managedSolrServer).getServer(
+                ldProgramName);
+        } catch (StoreException e) {
+            String msg = String
+                    .format("SolrSearchImpl.getFacetNames: Failed to obtain solr server for ldprogram: %s",
+                        ldProgramName);
+            log.error(msg, e);
+            throw new SearchException(msg, e);
+        }
+        List<String> facetNames = null;
+        try {
+            facetNames = SolrQueryUtil.getFacetNames(solrServer);
+        } catch (SolrServerException e) {
+            String msg = "SolrSearchImpl.getFacetNames: Failed to execute solr query";
+            log.error(msg, e);
+            throw new SearchException(msg, e);
+        } catch (IOException e) {
+            throw new SearchException(e.getMessage(), e);
+        }
+        return facetNames;
+    }
+
+    @Override
+    public List<String> tokenizeEntities(String queryTerm) {
+        // obtain entities about query term through Enhancer
+        ContentItem ci = null;
+        boolean error = false;
+        try {
+            ci = new InMemoryContentItem(queryTerm.getBytes(Constants.DEFAULT_ENCODING), "text/plain");
+            enhancementJobManager.enhanceContent(ci);
+        } catch (UnsupportedEncodingException e) {
+            log.error("Failed to get bytes of query term: {}", queryTerm, e);
+            error = true;
+        } catch (EnhancementException e) {
+            log.error("Failed to get enmancements for the query term: {}", queryTerm, e);
+            error = true;
+        }
+
+        List<String> tokenizedTerms = new ArrayList<String>();
+        if (error || ci == null || ci.getMetadata() == null) {
+            tokenizedTerms.add(queryTerm);
+        } else {
+            // traverse selected text assertions
+            MGraph queryTermMetadata = ci.getMetadata();
+            Iterator<Triple> textAnnotations = queryTermMetadata.filter(null,
+                Properties.ENHANCER_SELECTED_TEXT, null);
+            while (textAnnotations.hasNext()) {
+                Resource r = textAnnotations.next().getObject();
+                String selectedText = "";
+                if (r instanceof Literal) {
+                    selectedText = ((Literal) r).getLexicalForm();
+                } else {
+                    selectedText = r.toString();
+                }
+
+                tokenizedTerms.add(selectedText);
+            }
+
+            // get language of the query term
+            String language = "en";
+            Iterator<Triple> lanIt = queryTermMetadata.filter(null, Properties.DC_LANGUAGE, null);
+            if (lanIt.hasNext()) {
+                Resource r = lanIt.next().getObject();
+                if (r instanceof Literal) {
+                    language = ((Literal) r).getLexicalForm();
+                } else {
+                    language = r.toString();
+                }
+            }
+            /*
+             * If there is no stopword list for the language detected, it is highly possible that the default
+             * language is detected is false. As English is the most common language, it is set as default.
+             */
+            if (!stopWords.containsKey(language)) {
+                language = "en";
+            }
+
+            // eliminate entity query tokens from the original query term
+            for (String queryToken : tokenizedTerms) {
+                queryTerm = removeQueryToken(queryTerm, queryToken);
+            }
+
+            // find non-entity query tokens
+            tokenizedTerms.addAll(getNonEntityQueryTerms(queryTerm, language));
+        }
+        return tokenizedTerms;
+    }
+
+    private Set<String> getNonEntityQueryTerms(String queryTerm, String language) {
+        String currentWord = "";
+        Set<String> queryTokens = new HashSet<String>();
+        List<String> languageSpecificStopWords = stopWords.get(language);
+        for (int i = 0; i < queryTerm.length(); i++) {
+            if (SolrQueryUtil.queryDelimiters.contains(queryTerm.charAt(i))) {
+                if (!currentWord.equals("")) {
+                    if (languageSpecificStopWords != null) {
+                        if (!languageSpecificStopWords.contains(currentWord.trim().toLowerCase())) {
+                            queryTokens.add(currentWord);
+                        }
+                    } else {
+                        queryTokens.add(currentWord);
+                    }
+                }
+                currentWord = "";
+                continue;
+            }
+            currentWord += queryTerm.charAt(i);
+        }
+        // check for the last word
+        if (!currentWord.equals("")) {
+            if (languageSpecificStopWords != null) {
+                if (!languageSpecificStopWords.contains(currentWord.trim().toLowerCase())) {
+                    queryTokens.add(currentWord);
+                }
+            } else {
+                queryTokens.add(currentWord);
+            }
+        }
+        return queryTokens;
+    }
+
+    private String removeQueryToken(String queryTerm, String queryToken) {
+        String newTerm;
+        int tokenStartIndex = queryTerm.indexOf(queryToken);
+        if (tokenStartIndex != -1) {
+            // find right delimeter
+            int rightDelimeterIndex = tokenStartIndex + queryToken.length();
+            for (; rightDelimeterIndex < queryTerm.length(); rightDelimeterIndex++) {
+                if (SolrQueryUtil.queryDelimiters.contains(queryTerm.charAt(rightDelimeterIndex))) {
+                    rightDelimeterIndex++;
+                    break;
+                }
+            }
+            newTerm = queryTerm.substring(0, tokenStartIndex);
+            if (rightDelimeterIndex < queryTerm.length()) {
+                newTerm += queryTerm.substring(rightDelimeterIndex);
+            }
+        } else {
+            newTerm = queryTerm;
+        }
+        return newTerm;
+    }
+}

Added: incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchResult.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchResult.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchResult.java (added)
+++ incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/FeaturedSearchResult.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,55 @@
+package org.apache.stanbol.contenthub.search.featured;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.solr.client.solrj.response.FacetField;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.ResultantDocument;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.SearchResult;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeyword;
+
+public class FeaturedSearchResult implements SearchResult {
+
+    private List<ResultantDocument> resultantDocuments;
+    private List<FacetField> facets;
+    private Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords;
+    
+    public FeaturedSearchResult(List<ResultantDocument> resultantDocuments,
+                                List<FacetField> facets,
+                                Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords) {
+        this.resultantDocuments = resultantDocuments;
+        this.facets = facets;
+        this.relatedKeywords = relatedKeywords;
+    }
+
+    @Override
+    public List<ResultantDocument> getResultantDocuments() {
+        return this.resultantDocuments;
+    }
+
+    @Override
+    public List<FacetField> getFacets() {
+        return this.facets;
+    }
+    
+    @Override
+    public Map<String,Map<String,List<RelatedKeyword>>> getRelatedKeywords() {
+        return this.relatedKeywords;
+    }
+
+    @Override
+    public void setDocuments(List<ResultantDocument> resultantDocuments) {
+        this.resultantDocuments = resultantDocuments;
+    }
+
+    @Override
+    public void setFacets(List<FacetField> facets) {
+        this.facets = facets;
+    }
+
+    @Override
+    public void setRelatedKeywords(Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords) {
+        this.relatedKeywords = relatedKeywords;
+    }
+
+}

Added: incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/ResultantDocumentImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/ResultantDocumentImpl.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/ResultantDocumentImpl.java (added)
+++ incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/ResultantDocumentImpl.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,81 @@
+package org.apache.stanbol.contenthub.search.featured;
+
+import org.apache.stanbol.contenthub.servicesapi.search.featured.ResultantDocument;
+import org.apache.stanbol.contenthub.store.solr.util.ContentItemIDOrganizer;
+
+public class ResultantDocumentImpl implements ResultantDocument {
+
+    private String id;
+    private String dereferencableURI;
+    private String mimetype;
+    private long enhancementCount;
+    private String title;
+
+    public ResultantDocumentImpl(String uri,
+                                 String mimeType,
+                                 long enhancementCount,
+                                 String title) {
+        this.id = ContentItemIDOrganizer.detachBaseURI(uri);
+        this.mimetype = mimeType;
+        this.title = (title == null || title.trim().equals("") ? id : title);
+        this.enhancementCount = enhancementCount;
+    }
+
+    public ResultantDocumentImpl(String uri,
+                                 String dereferencableURI,
+                                 String mimeType,
+                                 long enhancementCount,
+                                 String title) {
+        this.id = ContentItemIDOrganizer.detachBaseURI(uri);
+        this.dereferencableURI = dereferencableURI;
+        this.mimetype = mimeType;
+        this.title = (title == null || title.trim().equals("") ? id : title);
+        this.enhancementCount = enhancementCount;
+    }
+    
+    @Override
+    public String getLocalId() {
+        return this.id;
+    }
+    
+    @Override
+    public String getDereferencableURI() {
+        return this.dereferencableURI;
+    }
+
+    @Override
+    public String getMimetype() {
+        return this.mimetype;
+    }
+
+    @Override
+    public long getEnhancementCount() {
+        return this.enhancementCount;
+    }
+
+    @Override
+    public String getTitle() {
+        return this.title;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setDereferencableURI(String dereferencableURI) {
+        this.dereferencableURI = dereferencableURI;
+    }
+
+    public void setMimetype(String mimetype) {
+        this.mimetype = mimetype;
+    }
+
+    public void setEnhancements(long enhancementCount) {
+        this.enhancementCount = enhancementCount;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+    
+}

Added: incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/util/SolrContentItemConverter.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/util/SolrContentItemConverter.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/util/SolrContentItemConverter.java (added)
+++ incubator/stanbol/trunk/contenthub/search/featured/src/main/java/org/apache/stanbol/contenthub/search/featured/util/SolrContentItemConverter.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,37 @@
+package org.apache.stanbol.contenthub.search.featured.util;
+
+import org.apache.solr.common.SolrDocument;
+import org.apache.stanbol.contenthub.search.featured.ResultantDocumentImpl;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.ResultantDocument;
+import org.apache.stanbol.contenthub.servicesapi.store.vocabulary.SolrVocabulary.SolrFieldName;
+
+public class SolrContentItemConverter {
+    /**
+     * This method converts a {@link SolrDocument} into a {@link HTMLContentItem}. Note currently, it ignores
+     * its metadata produced after enhancement process and stored. Its constraints indexed in Solr are also
+     * ignored as these items are only shown as a list in HTML interface.
+     */
+    public static ResultantDocument solrDocument2solrContentItem(SolrDocument solrDocument) {
+        return solrDocument2solrContentItem(solrDocument, null);
+    }
+    
+    public static ResultantDocument solrDocument2solrContentItem(SolrDocument solrDocument, String baseURI) {
+        String id = getStringValueFromSolrField(solrDocument, SolrFieldName.ID.toString());
+        String mimeType = getStringValueFromSolrField(solrDocument, SolrFieldName.MIMETYPE.toString());
+        String title = getStringValueFromSolrField(solrDocument, SolrFieldName.TITLE.toString());
+        long enhancementCount = (Long) solrDocument.getFieldValue(SolrFieldName.ENHANCEMENTCOUNT.toString());
+        String dereferencableURI = baseURI != null ? (baseURI + "contenthub/store/content/" + id) : null;
+        title = (title == null || title.trim().equals("") ? id : title);
+        ResultantDocumentImpl resultantDocument = new ResultantDocumentImpl(id, dereferencableURI, mimeType,
+                enhancementCount, title);
+        return resultantDocument;
+    }
+
+    private static String getStringValueFromSolrField(SolrDocument solrDocument, String field) {
+        Object result = solrDocument.getFieldValue(field);
+        if (result != null) {
+            return result.toString();
+        }
+        return "";
+    }
+}

Modified: incubator/stanbol/trunk/contenthub/search/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/pom.xml?rev=1236246&r1=1236245&r2=1236246&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/pom.xml (original)
+++ incubator/stanbol/trunk/contenthub/search/pom.xml Thu Jan 26 15:37:02 2012
@@ -1,36 +1,29 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to 
+  You under the Apache License, Version 2.0 (the "License"); you may not use 
+  this file except in compliance with the License. You may obtain a copy of 
+  the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+  by applicable law or agreed to in writing, software distributed under the 
+  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific 
+  language governing permissions and limitations under the License. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
 
-  <!-- parent>
+  <parent>
     <groupId>org.apache.stanbol</groupId>
     <artifactId>org.apache.stanbol.contenthub.parent</artifactId>
     <version>0.9.0-incubating-SNAPSHOT</version>
     <relativePath>../parent</relativePath>
-  </parent -->
+  </parent>
 
-  <groupId>org.apache.stanbol</groupId>
   <artifactId>org.apache.stanbol.contenthub.search.reactor</artifactId>
-  <version>0.9.0-incubating-SNAPSHOT</version>
   <packaging>pom</packaging>
+  <version>${search-version}</version>
 
   <name>Apache Stanbol Search Reactor</name>
   <description>
@@ -41,21 +34,16 @@
 
   <scm>
     <connection>
-      scm:svn:http://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/search
+				  scm:svn:http://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/search
     </connection>
     <developerConnection>
-      scm:svn:https://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/search
+				  scm:svn:https://svn.apache.org/repos/asf/incubator/stanbol/trunk/contenthub/search
     </developerConnection>
   </scm>
 
   <modules>
-    <module>engines/solr</module>
-    <module>ext/edu.smu.tspell.jaws</module>
-    <module>engines/wordnet</module>
-    <module>engines/ontologyresource</module>
-    <!--
-    <module>engines/enhancement</module>
-    <module>engines/location</module>-->
-    
+    <module>solr</module>
+    <module>related</module>
+    <module>featured</module>
   </modules>
 </project>

Propchange: incubator/stanbol/trunk/contenthub/search/related/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Jan 26 15:37:02 2012
@@ -0,0 +1,4 @@
+.settings
+target
+.classpath
+.project

Added: incubator/stanbol/trunk/contenthub/search/related/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/related/pom.xml?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/related/pom.xml (added)
+++ incubator/stanbol/trunk/contenthub/search/related/pom.xml Thu Jan 26 15:37:02 2012
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to 
+  You under the Apache License, Version 2.0 (the "License"); you may not use 
+  this file except in compliance with the License. You may obtain a copy of 
+  the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+  by applicable law or agreed to in writing, software distributed under the 
+  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific 
+  language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.stanbol</groupId>
+    <artifactId>org.apache.stanbol.contenthub.parent</artifactId>
+    <version>0.9.0-incubating-SNAPSHOT</version>
+    <relativePath>../../parent</relativePath>
+  </parent>
+
+  <artifactId>org.apache.stanbol.contenthub.search.related</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Apache Stanbol Search Related Keyword Searcher</name>
+
+  <description>Finds ontlogy classes and individuals based on query keywords
+Finds related keywords from various types of source e.g Wordnet, an external ontology, semantic information obtained through referenced sites
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Embed-Dependency>jaws</Embed-Dependency>
+            <Export-Package>edu.smu.tspell.*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.entityhub.model.clerezza</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.contenthub.servicesapi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.stanbol</groupId>
+      <artifactId>org.apache.stanbol.cmsadapter.servicesapi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
+
+    <!-- Clerezza -->
+    <dependency>
+      <groupId>org.apache.clerezza</groupId>
+      <artifactId>rdf.jena.facade</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+    <!-- Jena dependencies -->
+    <dependency>
+      <groupId>com.hp.hpl.jena</groupId>
+      <artifactId>jena</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.hp.hpl.jena</groupId>
+      <artifactId>arq</artifactId>
+    </dependency>
+
+    <!-- Jaws Wordnet client -->
+    <dependency>
+      <groupId>edu.smu.tspell</groupId>
+      <artifactId>jaws</artifactId>
+    </dependency>
+  </dependencies>
+
+  <repositories>
+    <repository>
+      <releases>
+        <updatePolicy>always</updatePolicy>
+      </releases>
+      <snapshots>
+        <updatePolicy>always</updatePolicy>
+      </snapshots>
+      <id>local-wordnet-repo</id>
+      <url>file://localhost/${project.basedir}/src/main/resources/local-maven-repository</url>
+    </repository>
+  </repositories>
+</project>

Added: incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordImpl.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordImpl.java (added)
+++ incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordImpl.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,43 @@
+package org.apache.stanbol.contenthub.search.related;
+
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeyword;
+
+public class RelatedKeywordImpl implements RelatedKeyword {
+    
+    private String keyword;
+    private double score;
+    private String source;
+
+    public RelatedKeywordImpl(String keyword, double score) {
+        this.keyword = keyword;
+        this.score = score;
+        this.source = RelatedKeyword.Source.UNKNOWN.toString();
+    }
+    
+    public RelatedKeywordImpl(String keyword, double score, String source) {
+        this.keyword = keyword;
+        this.score = score;
+        this.source = source;
+    }
+    
+    public RelatedKeywordImpl(String keyword, double score, RelatedKeyword.Source source) {
+        this.keyword = keyword;
+        this.score = score;
+        this.source = source.toString();
+    }
+
+    @Override
+    public String getKeyword() {
+        return this.keyword;
+    }
+
+    @Override
+    public double getScore() {
+        return this.score;
+    }
+
+    @Override
+    public String getSource() {
+        return this.source;
+    }
+}

Added: incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchManagerImpl.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchManagerImpl.java (added)
+++ incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchManagerImpl.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,85 @@
+package org.apache.stanbol.contenthub.search.related;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.ReferenceStrategy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.stanbol.contenthub.search.related.ontologyresource.OntologyResourceSearch;
+import org.apache.stanbol.contenthub.search.related.referencedsite.ReferencedSiteSearch;
+import org.apache.stanbol.contenthub.search.related.wordnet.WordnetSearch;
+import org.apache.stanbol.contenthub.servicesapi.search.SearchException;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.SearchResult;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeyword;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeywordSearch;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeywordSearchManager;
+
+@Component
+@Service
+public class RelatedKeywordSearchManagerImpl implements RelatedKeywordSearchManager {
+
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, referenceInterface = RelatedKeywordSearch.class, policy = ReferencePolicy.DYNAMIC, strategy = ReferenceStrategy.EVENT, bind = "bindRelatedKeywordSearch", unbind = "unbindRelatedKeywordSearch")
+    private List<RelatedKeywordSearch> rkwSearchers = new CopyOnWriteArrayList<RelatedKeywordSearch>();
+
+    protected void bindRelatedKeywordSearch(RelatedKeywordSearch relatedKeywordSearch) {
+        rkwSearchers.add(relatedKeywordSearch);
+    }
+
+    protected void unbindRelatedKeywordSearch(RelatedKeywordSearch relatedKeywordSearch) {
+        rkwSearchers.remove(relatedKeywordSearch);
+    }
+    
+    @Override
+    public SearchResult getRelatedKeywordsFromAllSources(String keyword) throws SearchException {
+        return getRelatedKeywordsFromAllSources(keyword, null);
+    }
+
+    @Override
+    public SearchResult getRelatedKeywordsFromAllSources(String keyword, String ontologyURI) throws SearchException {
+        Map<String,List<RelatedKeyword>> relatedKeywords = new HashMap<String,List<RelatedKeyword>>();
+        for (RelatedKeywordSearch searcher : rkwSearchers) {
+            relatedKeywords.putAll(searcher.search(keyword, ontologyURI));
+        }
+        Map<String,Map<String,List<RelatedKeyword>>> relatedKeywordsMap = new HashMap<String,Map<String,List<RelatedKeyword>>>();
+        relatedKeywordsMap.put(keyword, relatedKeywords);
+        return new RelatedKeywordSearchResult(relatedKeywordsMap);
+    }
+
+    private SearchResult getRelatedKeywordsFrom(String keyword, Class<? extends RelatedKeywordSearch> cls, String... ontologyURI) throws SearchException {
+        Map<String,List<RelatedKeyword>> relatedKeywords = new HashMap<String,List<RelatedKeyword>>();
+        for (RelatedKeywordSearch searcher : rkwSearchers) {
+            if(cls.isAssignableFrom(searcher.getClass())) {
+                if(ontologyURI != null && ontologyURI.length > 0) {
+                    relatedKeywords.putAll(searcher.search(keyword, ontologyURI[0]));    
+                } else {
+                    relatedKeywords.putAll(searcher.search(keyword));
+                }
+                break;
+            }
+        }
+        Map<String,Map<String,List<RelatedKeyword>>> relatedKeywordsMap = new HashMap<String,Map<String,List<RelatedKeyword>>>();
+        relatedKeywordsMap.put(keyword, relatedKeywords);
+        return new RelatedKeywordSearchResult(relatedKeywordsMap);
+    }
+    
+    @Override
+    public SearchResult getRelatedKeywordsFromWordnet(String keyword) throws SearchException {
+        return getRelatedKeywordsFrom(keyword, WordnetSearch.class);
+    }
+
+    @Override
+    public SearchResult getRelatedKeywordsFromOntology(String keyword, String ontologyURI) throws SearchException {
+        return getRelatedKeywordsFrom(keyword, OntologyResourceSearch.class, ontologyURI);
+    }
+
+    @Override
+    public SearchResult getRelatedKeywordsFromReferencedCites(String keyword) throws SearchException {
+        return getRelatedKeywordsFrom(keyword, ReferencedSiteSearch.class);
+    }
+}

Added: incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchResult.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchResult.java?rev=1236246&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchResult.java (added)
+++ incubator/stanbol/trunk/contenthub/search/related/src/main/java/org/apache/stanbol/contenthub/search/related/RelatedKeywordSearchResult.java Thu Jan 26 15:37:02 2012
@@ -0,0 +1,67 @@
+/**
+ * 
+ */
+package org.apache.stanbol.contenthub.search.related;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.solr.client.solrj.response.FacetField;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.ResultantDocument;
+import org.apache.stanbol.contenthub.servicesapi.search.featured.SearchResult;
+import org.apache.stanbol.contenthub.servicesapi.search.related.RelatedKeyword;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author anil.sinaci
+ *
+ */
+public class RelatedKeywordSearchResult implements SearchResult {
+
+    private static final Logger log = LoggerFactory.getLogger(RelatedKeywordSearchResult.class); 
+    
+    private Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords;
+    
+    public RelatedKeywordSearchResult(Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords) {
+        this.relatedKeywords = relatedKeywords;
+    }
+    
+    @Override
+    public List<ResultantDocument> getResultantDocuments() {
+        log.warn("RelatedKeywordSearchResult does not contain any ResultantDocument");
+        return null;
+    }
+
+    @Override
+    public List<FacetField> getFacets() {
+        log.warn("RelatedKeywordSearchResult does not contain any FacetField");
+        return null;
+    }
+
+    @Override
+    public Map<String,Map<String,List<RelatedKeyword>>> getRelatedKeywords() {
+        return this.relatedKeywords;
+    }
+
+    @Override
+    public void setDocuments(List<ResultantDocument> resultantDocuments) {
+        String msg = "RelatedKeywordSearchResult cannot contain any ResultantDocument";
+        log.error(msg);
+        throw new NotImplementedException(msg);
+    }
+
+    @Override
+    public void setFacets(List<FacetField> facets) {
+        String msg = "RelatedKeywordSearchResult cannot contain any FacetField";
+        log.error(msg);
+        throw new NotImplementedException(msg);
+    }
+
+    @Override
+    public void setRelatedKeywords(Map<String,Map<String,List<RelatedKeyword>>> relatedKeywords) {
+        this.relatedKeywords = relatedKeywords;
+    }
+
+}