Author: ssmiweve
Date: 2009-02-25 00:48:13 +0100 (Wed, 25 Feb 2009)
New Revision: 7208

Added:
   
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/FacetedSearchConfigurationDeserializer.java
   
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/FacetedCommandConfig.java
Modified:
   
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/SolrCommandConfig.java
   
branches/2.18/generic.sesam/search-command-control/default/src/main/java/no/sesat/search/mode/command/SolrSearchCommand.java
   branches/2.18/mojo/src/main/java/no/sesat/mojo/modes/Builder.java
   
branches/2.18/query-transform-control-spi/src/main/java/no/sesat/search/query/transform/QueryTransformer.java
   branches/2.18/result-spi/src/main/java/no/sesat/search/result/Navigator.java
   
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/CommandConfig.java
Log:
Support for Command Facets. Particularly Solr's SimpleFacetToolkit


Added: 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/FacetedSearchConfigurationDeserializer.java
===================================================================
--- 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/FacetedSearchConfigurationDeserializer.java
                             (rev 0)
+++ 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/FacetedSearchConfigurationDeserializer.java
     2009-02-24 23:48:13 UTC (rev 7208)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (2009) Schibsted Søk AS
+ * This file is part of SESAT.
+ *
+ *   SESAT is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU Affero General Public License as published 
by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   SESAT is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Affero General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Affero General Public License
+ *   along with SESAT.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package no.sesat.search.mode.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import no.sesat.search.result.Navigator;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**  UTility class to deserialise facets.
+ *
+ * @version $Id$
+ */
+final class FacetedSearchConfigurationDeserializer {
+
+    private static final Logger LOG = 
Logger.getLogger(FacetedSearchConfigurationDeserializer.class);
+
+    private static final String ERR_ONLY_ONE_CHILD_FACET_ALLOWED
+            = "Each Facet is only allowed to have one child. Parent was ";
+
+    private static final String INFO_PARSING_FACET = "  Parsing facet ";
+
+    /** Currently only used by the subclasses but hopefully open to all one 
day.
+     * @param navsE w3c dom elements to deserialise
+     * @return collection of Navigators
+     */
+    static final Collection<Navigator> parseNavigators(final Element navsE) {
+
+        final Collection<Navigator> navigators = new ArrayList<Navigator>();
+        final NodeList children = navsE.getChildNodes();
+        for (int i = 0; i < children.getLength(); ++i) {
+            final Node child = children.item(i);
+            if (child instanceof Element && "facet".equals(((Element) 
child).getTagName())) {
+                final Element navE = (Element) child;
+                final String id = navE.getAttribute("id");
+                final String name = navE.getAttribute("name");
+                final String sortAttr = navE.getAttribute("sort") != null && 
navE.getAttribute("sort").length() > 0
+                        ? navE.getAttribute("sort").toUpperCase() : "COUNT";
+                LOG.info(INFO_PARSING_FACET + id + " [" + name + "]" + ", 
sort=" + sortAttr);
+                final Navigator.Sort sort = Navigator.Sort.valueOf(sortAttr);
+
+                final boolean boundaryMatch = 
navE.getAttribute("boundary-match").equals("true");
+
+                final Navigator nav = new Navigator(
+                        name,
+                        navE.getAttribute("field"),
+                        navE.getAttribute("display-name"),
+                        sort,
+                        boundaryMatch);
+                nav.setId(id);
+                final Collection<Navigator> childNavigators = 
parseNavigators(navE);
+                if (childNavigators.size() > 1) {
+                    throw new 
IllegalStateException(ERR_ONLY_ONE_CHILD_FACET_ALLOWED + id);
+                } else if (childNavigators.size() == 1) {
+                    nav.setChildNavigator(childNavigators.iterator().next());
+                }
+                navigators.add(nav);
+            }
+        }
+
+        return navigators;
+    }
+
+    static final void readNavigators(
+            final Element element,
+            final FacetedCommandConfig config,
+            final SearchConfiguration inherit,
+            final Map<String, Navigator> facets){
+
+        final FacetedCommandConfig navCmdInherit = inherit instanceof 
FacetedCommandConfig
+                ? (FacetedCommandConfig) inherit
+                : null;
+
+        if (null != navCmdInherit && null != navCmdInherit.getFacets()) {
+
+            facets.putAll(navCmdInherit.getFacets());
+        }
+
+        final NodeList nList = element.getElementsByTagName("facets");
+
+        for (int i = 0; i < nList.getLength(); ++i) {
+            final Collection<Navigator> navs = parseNavigators((Element) 
nList.item(i));
+            for (Navigator navigator : navs) {
+                facets.put(navigator.getId(), navigator);
+            }
+        }
+    }
+
+    private FacetedSearchConfigurationDeserializer(){}
+
+}


Property changes on: 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/FacetedSearchConfigurationDeserializer.java
___________________________________________________________________
Added: svn:keywords
   + Id

Modified: 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/SolrCommandConfig.java
===================================================================
--- 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/SolrCommandConfig.java
  2009-02-24 23:42:05 UTC (rev 7207)
+++ 
branches/2.18/generic.sesam/search-command-config/src/main/java/no/sesat/search/mode/config/SolrCommandConfig.java
  2009-02-24 23:48:13 UTC (rev 7208)
@@ -1,4 +1,4 @@
-/* Copyright (2008) Schibsted Søk AS
+/* Copyright (2008-2009) Schibsted Søk AS
  * This file is part of SESAT.
  *
  *   SESAT is free software: you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 import java.util.Map;
 import no.sesat.search.mode.SearchModeFactory.Context;
 import no.sesat.search.mode.config.CommandConfig.Controller;
+import no.sesat.search.result.Navigator;
 import org.w3c.dom.Element;
 
 /** Searching against a Solr index using the Solrj client.
@@ -33,9 +34,8 @@
  * @version $Id$
  */
 @Controller("SolrSearchCommand")
-public class SolrCommandConfig extends CommandConfig {
+public class SolrCommandConfig extends CommandConfig implements 
FacetedCommandConfig {
 
-
     // Constants -----------------------------------------------------
 
     // Attributes ----------------------------------------------------
@@ -48,6 +48,10 @@
 
     private Integer timeout = Integer.MAX_VALUE;
 
+    private final Map<String, Navigator> facets = new 
HashMap<String,Navigator>();
+
+    private String facetToolkit;
+
     // Static --------------------------------------------------------
 
     // Constructors --------------------------------------------------
@@ -138,7 +142,34 @@
         return timeout;
     }
 
+    /**
+     *
+     * @return
+     */
     @Override
+    public Map<String, Navigator> getFacets() {
+        return facets;
+    }
+
+    /**
+     *
+     * @param navigatorKey
+     * @return
+     */
+    @Override
+    public Navigator getFacet(final String navigatorKey) {
+        return facets.get(navigatorKey);
+    }
+
+    public String getFacetToolkit() {
+        return facetToolkit;
+    }
+
+    public void setFacetToolkit(final String toolkit){
+        this.facetToolkit = toolkit;
+    }
+
+    @Override
     public SearchConfiguration readSearchConfiguration(
             final Element element,
             final SearchConfiguration inherit,
@@ -156,6 +187,8 @@
             }
         }
 
+        FacetedSearchConfigurationDeserializer.readNavigators(element, this, 
inherit, facets);
+
         return this;
     }
 

Modified: 
branches/2.18/generic.sesam/search-command-control/default/src/main/java/no/sesat/search/mode/command/SolrSearchCommand.java
===================================================================
--- 
branches/2.18/generic.sesam/search-command-control/default/src/main/java/no/sesat/search/mode/command/SolrSearchCommand.java
        2009-02-24 23:42:05 UTC (rev 7207)
+++ 
branches/2.18/generic.sesam/search-command-control/default/src/main/java/no/sesat/search/mode/command/SolrSearchCommand.java
        2009-02-24 23:48:13 UTC (rev 7208)
@@ -1,5 +1,5 @@
 /*
- * Copyright (2008) Schibsted Søk AS
+ * Copyright (2008-2009) Schibsted Søk AS
  * This file is part of SESAT.
  *
  *   SESAT is free software: you can redistribute it and/or modify
@@ -24,9 +24,13 @@
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import no.sesat.commons.ref.ReferenceMap;
+import no.sesat.search.datamodel.generic.StringDataObject;
+import no.sesat.search.datamodel.request.ParametersDataObject;
+import no.sesat.search.mode.config.FacetedCommandConfig;
 import no.sesat.search.mode.config.SolrCommandConfig;
 import no.sesat.search.result.BasicResultItem;
 import no.sesat.search.result.BasicResultList;
+import no.sesat.search.result.Navigator;
 import no.sesat.search.result.ResultItem;
 import no.sesat.search.result.ResultList;
 import no.sesat.search.site.config.SiteConfiguration;
@@ -57,6 +61,7 @@
     // Attributes ----------------------------------------------------
 
     private SolrServer server;
+    private final FacetToolkit facetToolkit;
 
     // Static --------------------------------------------------------
 
@@ -85,6 +90,8 @@
         } catch (MalformedURLException ex) {
             LOG.error(ex.getMessage(), ex);
         }
+
+        facetToolkit = new SimpleFacetToolkitImpl();
     }
 
     // Public --------------------------------------------------------
@@ -103,6 +110,8 @@
                     .setRows(getSearchConfiguration().getResultsToReturn())
                     
.setFields(getSearchConfiguration().getResultFieldMap().keySet().toArray(new 
String[]{}));
 
+            createFacets(query);
+
             // when the root logger is set to DEBUG do not limit connection 
times
             if(Logger.getRootLogger().getLevel().isGreaterOrEqual(Level.INFO)){
                 query.setTimeAllowed(getSearchConfiguration().getTimeout());
@@ -143,7 +152,31 @@
 
     // Protected -----------------------------------------------------
 
+    protected FacetToolkit createFacetToolkit(){
 
+        FacetToolkit toolkit = null;
+        final String toolkitName = getSearchConfiguration().getFacetToolkit();
+        if(null != toolkit){
+            try{
+                final Class<FacetToolkit> cls = (Class<FacetToolkit>) 
Class.forName(toolkitName);
+                toolkit = cls.newInstance();
+            }catch(ClassNotFoundException cnfe){
+                LOG.error(cnfe.getMessage());
+            }catch(InstantiationException ie){
+                LOG.error(ie.getMessage());
+            }catch(IllegalAccessException iae){
+                LOG.error(iae.getMessage());
+            }
+        }
+        return toolkit;
+    }
+
+    protected final void createFacets(final SolrQuery query){
+        if(null != facetToolkit){
+            facetToolkit.createFacets(context, query);
+        }
+    }
+
     protected BasicResultItem createItem(final SolrDocument doc) {
 
         BasicResultItem item = new BasicResultItem();
@@ -160,4 +193,55 @@
     // Private -------------------------------------------------------
 
     // Inner classes -------------------------------------------------
+
+    /**
+     * Provider to add facets from request to SolrQuery.
+     */
+    public interface FacetToolkit{
+        void createFacets(SearchCommand.Context context, SolrQuery query);
+    }
+
+    /**
+     * Solr's Simple Faceting toolkit.
+     *
+     * {...@link http://wiki.apache.org/solr/SolrFacetingOverview}
+     * {...@link http://wiki.apache.org/solr/SimpleFacetParameters}
+     */
+    public static class SimpleFacetToolkitImpl implements FacetToolkit{
+
+        public void createFacets(final SearchCommand.Context context, final 
SolrQuery query) {
+
+            final Map<String,Navigator> facets = 
getSearchConfiguration(context).getFacets();
+
+            query.setFacet(0 < facets.size());
+
+            // facet counters
+            for(Navigator facet : facets.values()){
+                query.addFacetField(facet.getField());
+            }
+
+            // facet selection
+            for (final Navigator facet : facets.values()) {
+
+                final StringDataObject facetValue = 
context.getDataModel().getParameters().getValue(facet.getId());
+
+                if (null != facetValue) {
+
+                    // splitting here allows for multiple navigation 
selections within the one navigation level.
+                    for(String navSingleValue : 
facetValue.getString().split(",")){
+
+                        final String value =  facet.isBoundaryMatch()
+                                ? "^\"" + navSingleValue + "\"$"
+                                : "\"" + navSingleValue + "\"";
+
+                        query.addFacetQuery(facet.getField() + ':' + value);
+                    }
+                }
+            }
+        }
+
+        private FacetedCommandConfig getSearchConfiguration(final 
SearchCommand.Context context){
+            return (FacetedCommandConfig) context.getSearchConfiguration();
+        }
+    }
 }

Modified: branches/2.18/mojo/src/main/java/no/sesat/mojo/modes/Builder.java
===================================================================
--- branches/2.18/mojo/src/main/java/no/sesat/mojo/modes/Builder.java   
2009-02-24 23:42:05 UTC (rev 7207)
+++ branches/2.18/mojo/src/main/java/no/sesat/mojo/modes/Builder.java   
2009-02-24 23:48:13 UTC (rev 7208)
@@ -1,5 +1,5 @@
 /*
- * Copyright (2008) Schibsted Søk AS
+ * Copyright (2008-2009) Schibsted Søk AS
  * This file is part of SESAT.
  *
  *   SESAT is free software: you can redistribute it and/or modify
@@ -200,6 +200,8 @@
 
         final ConfigElement navigators = new ConfigElement("navigators");
         final ConfigElement navigator = new ConfigElement("navigator");
+        final ConfigElement facets = new ConfigElement("facets");
+        final ConfigElement facet = new ConfigElement("facet");
         // TODO replace with introspection
         navigator.getAttributes().add(new ConfigAttribute("id", null, true));
         navigator.getAttributes().add(new ConfigAttribute("name", null, true));
@@ -207,18 +209,22 @@
         navigator.getAttributes().add(new ConfigAttribute("display-name", 
null, true));
         navigator.getAttributes().add(new ConfigAttribute("sort", null, 
false));
         navigator.getAttributes().add(new ConfigAttribute("boundary-match"));
+        facet.getAttributes().addAll(navigator.getAttributes());
 
         // allow recursive nesting of navigator.
         navigator.addChild(navigator);
-
         // only for fast commands
         navigators.addChild(navigator);
 
+        facet.addChild(facet);
+        facets.addChild(facet);
+
         for (ConfigElement command : commands) {
             command.addChild(queryBuilder);
             command.addChild(resultHandler);
             command.addChild(queryTransform);
             command.addChild(navigators);
+            command.addChild(facets);
         }
 
         final Runnable[] jobs = {new GenerateRelaxNG(modes, outputDir + 
"modes.rnc", id),

Modified: 
branches/2.18/query-transform-control-spi/src/main/java/no/sesat/search/query/transform/QueryTransformer.java
===================================================================
--- 
branches/2.18/query-transform-control-spi/src/main/java/no/sesat/search/query/transform/QueryTransformer.java
       2009-02-24 23:42:05 UTC (rev 7207)
+++ 
branches/2.18/query-transform-control-spi/src/main/java/no/sesat/search/query/transform/QueryTransformer.java
       2009-02-24 23:48:13 UTC (rev 7208)
@@ -1,4 +1,4 @@
-/* Copyright (2006-2008) Schibsted Søk AS
+/* Copyright (2006-2009) Schibsted Søk AS
  * This file is part of SESAT.
  *
  *   SESAT is free software: you can redistribute it and/or modify
@@ -30,6 +30,7 @@
 import org.w3c.dom.Element;
 
 import java.util.Map;
+import no.sesat.search.mode.config.SearchConfiguration;
 
 
 /**
@@ -109,7 +110,9 @@
      * <p/>
      * +docdatetime:>2005-10-28
      *
-     * @param parameters
+     * @deprecated all functionality should be provided by getFilter() with 
any access to parameters via the datamodel
+     *
+     * @param parameters the datamodel's parameters
      * @return filterstring
      */
     String getFilter(Map parameters);

Modified: 
branches/2.18/result-spi/src/main/java/no/sesat/search/result/Navigator.java
===================================================================
--- 
branches/2.18/result-spi/src/main/java/no/sesat/search/result/Navigator.java    
    2009-02-24 23:42:05 UTC (rev 7207)
+++ 
branches/2.18/result-spi/src/main/java/no/sesat/search/result/Navigator.java    
    2009-02-24 23:48:13 UTC (rev 7208)
@@ -23,6 +23,8 @@
  *
  * Each facet contains an id, name, displayName, sort definition, 
boundaryMatch enabled, and children navigators.
  *
+ * @todo rename to Facet
+ *
  * @version <tt>$Id$</tt>
  */
 public final class Navigator implements Serializable {
@@ -37,8 +39,8 @@
 
 
     public enum Sort {
-        COUNT(),
-        YEAR(),
+        COUNT,
+        YEAR,
         MONTH_YEAR(),
         DAY_MONTH_YEAR(),
         DAY_MONTH_YEAR_DESCENDING,

Modified: 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/CommandConfig.java
===================================================================
--- 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/CommandConfig.java
        2009-02-24 23:42:05 UTC (rev 7207)
+++ 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/CommandConfig.java
        2009-02-24 23:48:13 UTC (rev 7208)
@@ -1,4 +1,4 @@
-/* Copyright (2006-2008) Schibsted Søk AS
+/* Copyright (2006-2009) Schibsted Søk AS
  * This file is part of SESAT.
  *
  *   SESAT is free software: you can redistribute it and/or modify
@@ -362,6 +362,8 @@
     /** Currently only used by the fast subclasses but hopefully open to all 
one day. *
      * @param navsE w3c dom elements to deserialise
      * @return collection of Navigators
+     *
+     * @deprecated Use FacetedCommandConfigUtility.parseNavigators(Element) 
instead.
      */
     protected final Collection<Navigator> parseNavigators(final Element navsE) 
{
 

Added: 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/FacetedCommandConfig.java
===================================================================
--- 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/FacetedCommandConfig.java
                         (rev 0)
+++ 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/FacetedCommandConfig.java
 2009-02-24 23:48:13 UTC (rev 7208)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (2009) Schibsted Søk AS
+ * This file is part of SESAT.
+ *
+ *   SESAT is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU Affero General Public License as published 
by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   SESAT is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Affero General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Affero General Public License
+ *   along with SESAT.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package no.sesat.search.mode.config;
+
+import java.util.Map;
+import no.sesat.search.result.Navigator;
+
+/**
+ *
+ * @version $Id$
+ */
+public interface FacetedCommandConfig extends SearchConfiguration{
+
+    /**
+     *
+     * @param navigatorKey
+     * @return
+     */
+    Navigator getFacet(final String navigatorKey);
+
+    /**
+     *
+     * @return
+     */
+    Map<String, Navigator> getFacets();
+}


Property changes on: 
branches/2.18/search-command-config-spi/src/main/java/no/sesat/search/mode/config/FacetedCommandConfig.java
___________________________________________________________________
Added: svn:keywords
   + Id

_______________________________________________
Kernel-commits mailing list
[email protected]
http://sesat.no/mailman/listinfo/kernel-commits

Reply via email to