Index: main/plugin-odf-web/i18n/messages_en.xml
===================================================================
--- main/plugin-odf-web/i18n/messages_en.xml (revision 29090)
+++ main/plugin-odf-web/i18n/messages_en.xml (working copy)
@@ -27,6 +27,8 @@
Allows to position ODF root page
Program search
Right to insert the program search service
+ Course Search
+ Right to insert the course search service
Program by criteria
Right to insert the program by criteria services (by domain, by degree, ...)
Schema of studies
@@ -78,15 +80,20 @@
Please, delete an odf root page before creating a new one.
Choose the catalog which will be link to the current ODF root page.
- Treaning offer
+ Training offer
Search a formation
Search engine on study programs
+ Search courses
+ Search engine on courses
Title
Optional. Set a title to be displayed above the search form.
Results per page
Maximum number of results displayed per page
Display the subprograms
Check this option to display the subprograms
+ Display the diplomas using the course
+ Check this box if you want the diplomas using the course to be displayed
+ Program(s) integrating the course:
Catalog
The search will be based on the selected catalog
Enable faceted search
@@ -99,6 +106,7 @@
Default
Choice lists only (as links)
Classification of results by domain
+ Default
Search fields
Select the search fields you want to display.
Diploma
@@ -108,7 +116,7 @@
Study level
Teaching department
Place
- Program title
+ Title
Keywords (full-text search)
Domain
Distance learning
@@ -134,7 +142,7 @@
Score
Title
- Program title
+ Title
keywords
Index: main/plugin-odf-web/i18n/messages_fr.xml
===================================================================
--- main/plugin-odf-web/i18n/messages_fr.xml (revision 29090)
+++ main/plugin-odf-web/i18n/messages_fr.xml (working copy)
@@ -27,6 +27,8 @@
Autorise à positionner la page racine de l'offre de formation
Recherche de formations
Droit de créer le service de moteur de recherche de formations
+ Recherche d'UE
+ Droit de créer le service de moteur de recherche d'
Formations par critère
Droit de créer les services d'affichage des formations par critère (par domaine, par diplôme, ...)
Schéma des formations
@@ -81,12 +83,17 @@
Offre de formation
Rechercher une formation
Moteur de recherche sur l'offre de formation
+ Rechercher une UE
+ Moteur de recherche sur les UE
Titre
Optionnel. Définissez un titre qui sera affiché au dessus du formulaire de recherche.
Résultats par page
Nombre de résultats maximum à afficher par page
Afficher les parcours
Cochez cette case pour afficher les parcours
+ Afficher les diplômes qui intègrent cette UE
+ Cochez cette case pour afficher les diplômes qui intègrent cette UE
+ Formation(s) intégrant cette UE :
Catalogue
Catalogue des formations recherchées
Recherche à facettes
@@ -99,6 +106,7 @@
Par défaut
Listes à choix uniquement (sous forme de liens)
Classification des résultats par domaine
+ Par défaut
Champs de la recherche
Sélectionnez les champs de recherche que vous souhaitez afficher.
Type de diplôme
@@ -108,7 +116,7 @@
Niveau d'étude
Composante
Lieu
- Intitulé de la formation
+ Intitulé
Mots-clés (recherche plein-texte)
Domaine
Formation à distance
@@ -134,7 +142,7 @@
Pertinence
Titre
- Intitulé de la formation
+ Intitulé
Mots clés
Index: main/plugin-odf-web/pages/services/search/course/search-course_2.3.xml
===================================================================
--- main/plugin-odf-web/pages/services/search/course/search-course_2.3.xml (revision 0)
+++ main/plugin-odf-web/pages/services/search/course/search-course_2.3.xml (revision 0)
@@ -0,0 +1,19 @@
+
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_XSLT_SEARCH23_LABEL
+
\ No newline at end of file
Index: main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl
===================================================================
--- main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl (revision 0)
+++ main/plugin-odf-web/pages/services/search/course/search-course_2.3.xsl (revision 0)
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hit page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/plugin.xml
===================================================================
--- main/plugin-odf-web/plugin.xml (revision 29090)
+++ main/plugin-odf-web/plugin.xml (working copy)
@@ -320,9 +320,12 @@
PLUGINS_ODFWEB_SERVICE_SEARCH_FIELDS
PLUGINS_ODFWEB_SERVICE_SEARCH_FIELDS_DESC
-
+
multiselect
+
+
+
PLUGINS_ODFWEB_SERVICE_SEARCH_FACET
@@ -397,6 +400,121 @@
+
+
+
+
+
+ PLUGINS_ODFWEB_RIGHT_SERVICE_COURSE_SEARCH_LABEL
+ PLUGINS_ODFWEB_RIGHT_SERVICE_COURSE_SEARCH_DESCRIPTION
+ plugin.web:PLUGINS_WEB_RIGHTS_SERVICE_CREATE_CATEGORY
+
+
+
+
+
+ service/search-course.html
+ Odf_Right_Service_OdfCourseSearch
+
+ PLUGINS_ODFWEB_SERVICE_COURSE_SEARCH_LABEL
+ PLUGINS_ODFWEB_SERVICE_COURSE_SEARCH_DESCRIPTION
+ PLUGINS_WEB_SERVICE_CATEGORY_31_ODF
+
+ img/services/search_16.png
+ img/services/search_32.png
+ img/services/search_48.png
+
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_HEADER
+ PLUGINS_ODFWEB_SERVICE_SEARCH_HEADER_DESC
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_FIELDS
+ PLUGINS_ODFWEB_SERVICE_SEARCH_FIELDS_DESC
+
+
+
+ multiselect
+
+
+
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_FACET
+ PLUGINS_ODFWEB_SERVICE_SEARCH_FACET_DESC
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_MODE
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_MODE_DESC
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_MODE_CRITERIA_AND_RESULTS
+ criteria-and-results
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_MODE_CRITERIA_OR_RESULTS
+ criteria-or-results
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_MODE_CRITERIA_ONLY
+ criteria-only
+
+
+
+
+
+ fo-search-mode
+
+
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_CRITERIA_PAGE
+ plugin.web:PLUGINS_WEB_SERVICE_FRONT_SEARCH_CRITERIA_PAGE_DESC
+ current-sitemap
+
+ true
+
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_COURSE_DISPLAY_RELATED_PROGRAMS
+ PLUGINS_ODFWEB_SERVICE_SEARCH_COURSE_DISPLAY_RELATED_PROGRAMS_DESC
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_OFFSET
+ PLUGINS_ODFWEB_SERVICE_SEARCH_OFFSET_DESC
+ 10
+
+
+
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_GROUP_ID
+ PLUGINS_ODFWEB_SERVICE_SEARCH_GROUP_ID_DESC
+
+
+ PLUGINS_ODFWEB_SERVICE_SEARCH_XSLT
+ PLUGINS_ODFWEB_SERVICE_SEARCH_XSLT_DESC
+ sorted-enumeration
+ pages/services/search/course/search-course_2.3.xsl
+
+
+ pages/services/search/course
+
+ pages/services/search/course/search-course_2.3.xsl
+
+
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/sitemap.xmap
===================================================================
--- main/plugin-odf-web/sitemap.xmap (revision 29090)
+++ main/plugin-odf-web/sitemap.xmap (working copy)
@@ -19,6 +19,7 @@
+
@@ -115,6 +116,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/WebODFContentIndexer.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/WebODFContentIndexer.java (revision 0)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/WebODFContentIndexer.java (revision 0)
@@ -0,0 +1,59 @@
+package org.ametys.plugins.odfweb;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Field.Index;
+import org.apache.lucene.document.Field.Store;
+
+import org.ametys.cms.repository.Content;
+import org.ametys.odf.course.Course;
+import org.ametys.odf.program.Program;
+import org.ametys.plugins.odfweb.repository.OdfPageResolver;
+import org.ametys.plugins.odfweb.repository.ProgramPage;
+import org.ametys.web.repository.page.Page;
+
+/**
+ * Content indexer for the web
+ */
+public class WebODFContentIndexer extends org.ametys.odf.contenttype.ODFContentIndexer
+{
+ /** The ODF page resolver */
+ private OdfPageResolver _odfPageResolver;
+
+ @Override
+ public void service(ServiceManager manager) throws ServiceException
+ {
+ super.service(manager);
+ _odfPageResolver = (OdfPageResolver) manager.lookup(OdfPageResolver.ROLE);
+ }
+
+ @Override
+ public void indexContent(Content content, Document document, Map parameters) throws Exception
+ {
+ super.indexContent(content, document, parameters);
+
+ if (content instanceof Course)
+ {
+ Course course = (Course) content;
+ Page coursePage = (Page) parameters.get("page");
+
+ List referencingPrograms = course.getReferencingPrograms();
+ // No duplicates
+ Set distinctRefPrograms = new HashSet(referencingPrograms);
+
+ for (Program program : distinctRefPrograms)
+ {
+ ProgramPage programPage = _odfPageResolver.getProgramPage(program, coursePage.getSiteName());
+ String pathInSitemap = programPage.getPathInSitemap();
+ document.add(new Field("referencingProgram", coursePage.getSitemapName() + "/" + pathInSitemap + ";" + program.getTitle(), Store.YES, Index.NOT_ANALYZED));
+ }
+ }
+ }
+}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java (revision 0)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/AbstractODFSearchGenerator.java (revision 0)
@@ -0,0 +1,712 @@
+package org.ametys.plugins.odfweb.generators;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceNotFoundException;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.MultiFieldQueryParser;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.tika.io.IOUtils;
+import org.xml.sax.SAXException;
+
+import org.ametys.cms.contenttype.ContentType;
+import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
+import org.ametys.cms.contenttype.MetadataDefinition;
+import org.ametys.cms.lucene.FieldNames;
+import org.ametys.odf.enumeration.OdfEnumerationHelper;
+import org.ametys.odf.orgunit.RootOrgUnitProvider;
+import org.ametys.runtime.util.I18nizableText;
+import org.ametys.runtime.util.parameter.Enumerator;
+import org.ametys.web.frontoffice.AbstractSearchGenerator;
+import org.ametys.web.lucene.IndexerHelper;
+import org.ametys.web.lucene.LuceneConstants;
+import org.ametys.web.repository.page.ZoneItem;
+
+/**
+ * Abstract class gathering mutual logic for a search on an ODF content
+ */
+public abstract class AbstractODFSearchGenerator extends AbstractSearchGenerator
+{
+ /** The "-for-sorting" suffix */
+ private static final String _FOR_SORTING = "-for-sorting";
+ /** The path to the configuration files directory */
+ private static final String __BOOST_CONF_DIR_PATH = "context://WEB-INF/param/odf/search";
+ /** The cache for the boosts by service id and by field name */
+ private static Map> _searchConfigurationCache = new HashMap> ();
+
+ /** The last time the file was modified by service id */
+ private static Map _lastConfUpdate = new HashMap ();
+
+ /** The source resolver */
+ protected SourceResolver _sourceResolver;
+
+ /** The ODF constants provider. */
+ protected OdfEnumerationHelper _enumerationHelper;
+
+ /** The root org unit provider. */
+ protected RootOrgUnitProvider _rootOrgUnitProvider;
+
+ /** The content type extension point. */
+ protected ContentTypeExtensionPoint _cTypeEP;
+
+ /** The inputs as a Map fieldName -> metadataPath. */
+ protected Map _searchFields;
+
+ @Override
+ public void service(ServiceManager smanager) throws ServiceException
+ {
+ super.service(smanager);
+ _enumerationHelper = (OdfEnumerationHelper) smanager.lookup(OdfEnumerationHelper.ROLE);
+ _rootOrgUnitProvider = (RootOrgUnitProvider) smanager.lookup(RootOrgUnitProvider.ROLE);
+ _cTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
+ _sourceResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE);
+ }
+
+ @Override
+ public void generate() throws IOException, SAXException, ProcessingException
+ {
+ String[] fields = parameters.getParameter("fields", "").split(",");
+
+ _searchFields = new LinkedHashMap();
+
+ for (String metadataPath : fields)
+ {
+ int slashPos = metadataPath.lastIndexOf('/');
+ String fieldName = slashPos < 0 ? metadataPath : metadataPath.substring(slashPos + 1);
+
+ _searchFields.put(fieldName, metadataPath);
+ }
+
+ super.generate();
+ }
+
+ @Override
+ protected Query getQuery (Request request) throws ParseException, IllegalArgumentException
+ {
+ return getQuery(getParameterValues(request));
+ }
+
+ /**
+ * Extract the parameter values from the request.
+ * @param request the request.
+ * @return the parameter values.
+ */
+ protected Map getParameterValues(Request request)
+ {
+ Map params = new HashMap();
+
+ for (String fieldName : _searchFields.keySet())
+ {
+ params.put(fieldName, request.getParameter(fieldName));
+ }
+
+ return params;
+ }
+
+ /**
+ * Get the query.
+ * @param params
+ * @return the lucene Query.
+ * @throws ParseException
+ * @throws IllegalArgumentException
+ */
+ protected Query getQuery(Map params) throws ParseException, IllegalArgumentException
+ {
+ BooleanQuery query = new BooleanQuery();
+
+ Request request = ObjectModelHelper.getRequest(objectModel);
+ ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName());
+
+ TermQuery termQuery = new TermQuery(new Term(FieldNames.CONTENT_TYPES, getContentType()));
+ termQuery.setBoost(0);
+ query.add(termQuery, BooleanClause.Occur.MUST);
+
+ // Initialize/update configuration cache if necessary
+ Map searchConfigurationCache = null;
+ Map boostsCache = null;
+
+ if (zoneItem != null)
+ {
+ searchConfigurationCache = _getSearchConfigurationCache(zoneItem.getServiceId());
+ boostsCache = (Map) searchConfigurationCache.get("boosts");
+ }
+
+ // Title
+ _addTitleQuery(query, params.get("title"), _getConfiguredBoost("title", boostsCache));
+
+ // Catalog
+ String catalog = StringUtils.defaultIfEmpty(params.get("catalog"), parameters.getParameter("catalog", ""));
+ if (StringUtils.isEmpty(catalog))
+ {
+ if (zoneItem != null)
+ {
+ catalog = zoneItem.getServiceParameters().getString("catalog", "");
+ }
+ }
+
+ if (StringUtils.isNotEmpty(catalog))
+ {
+ termQuery = new TermQuery(new Term("catalog", catalog));
+ termQuery.setBoost(0);
+ query.add(termQuery, BooleanClause.Occur.MUST);
+ }
+
+ // Keywords
+ _addTextFieldQuery(query, params.get("textfield"), _getConfiguredBoost("textfield", boostsCache));
+
+ for (String fieldName : _searchFields.keySet())
+ {
+ if (!fieldName.equals("title") && !fieldName.equals("textfield") && !fieldName.equals("catalog"))
+ {
+ String value = params.get(fieldName);
+ if (StringUtils.isNotEmpty(value))
+ {
+ termQuery = new TermQuery(new Term(fieldName, value));
+ termQuery.setBoost(_getConfiguredBoost(fieldName, boostsCache));
+ query.add(termQuery, BooleanClause.Occur.MUST);
+ }
+ }
+ }
+
+ return query;
+ }
+
+ @Override
+ protected String[] getFields ()
+ {
+ // TODO
+ return new String[] {"title", "keywords", "full"};
+ }
+
+ @Override
+ protected Map getCriteria(Request request, String siteName, String lang)
+ {
+ Map criteria = new HashMap();
+
+ for (String fieldName : _searchFields.keySet())
+ {
+ if (!fieldName.equals("title") && !fieldName.equals("textfield"))
+ {
+ String metadataPath = _searchFields.get(fieldName);
+
+ Criterion criterion = null;
+ if (StringUtils.isNotEmpty(metadataPath))
+ {
+ criterion = getCriterion(fieldName, metadataPath);
+ }
+
+ if (criterion != null)
+ {
+ criteria.put(fieldName, criterion);
+ }
+ }
+ }
+
+ return criteria;
+ }
+
+ /**
+ * Get the criterion corresponding to the field.
+ * @param fieldName the field name.
+ * @param metadataPath the corresponding metadata path.
+ * @return the corresponding Criterion.
+ */
+ protected Criterion getCriterion(String fieldName, String metadataPath)
+ {
+ try
+ {
+ ContentType programCType = _cTypeEP.getExtension(getContentType());
+
+ MetadataDefinition metadataDefinition = getMetadataDefinition(programCType, metadataPath);
+
+ Enumerator enumerator = metadataDefinition.getEnumerator();
+
+ if (enumerator != null)
+ {
+ Map values = new LinkedHashMap();
+ Map entries = enumerator.getEntries();
+ for (Entry entry : entries.entrySet())
+ {
+ values.put(entry.getKey().toString(), entry.getValue());
+ }
+
+ // Odf-specific criterion (with list label).
+ return new OdfCriterion(fieldName, metadataDefinition.getLabel(), "criterion-enumerated-" + fieldName, values);
+ }
+ }
+ catch (Exception e)
+ {
+ getLogger().error("Error retrieving the values of an enumerator.", e);
+ throw new IllegalStateException("Error retrieving the values of an enumerator.", e);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get a metadata definition from its path.
+ * @param contentType the content type.
+ * @param metadataPath the metadata path.
+ * @return the metadata definition or null if not found.
+ */
+ protected MetadataDefinition getMetadataDefinition(ContentType contentType, String metadataPath)
+ {
+ String[] pathSegments = StringUtils.split(metadataPath, '/');
+
+ if (pathSegments.length == 0)
+ {
+ return null;
+ }
+
+ MetadataDefinition metadataDef = contentType.getMetadataDefinition(pathSegments[0]);
+
+ for (int i = 1; i < pathSegments.length && metadataDef != null; i++)
+ {
+ metadataDef = metadataDef.getMetadataDefinition(pathSegments[i]);
+ }
+
+ return metadataDef;
+ }
+
+ @Override
+ protected void saxHits (Searcher searcher, TopDocs rs, int start, int offset) throws SAXException, IOException
+ {
+ ScoreDoc[] scoreDocs = rs.scoreDocs;
+
+ int limit = Math.min(start + offset, scoreDocs.length);
+
+ for (int i = start; i < limit; i++)
+ {
+ Document doc = searcher.doc(rs.scoreDocs[i].doc);
+ if (TYPE_PAGE.equals(doc.get(TYPE)))
+ {
+ try
+ {
+ saxPageHit(rs, doc, i);
+ }
+ catch (ProcessingException e)
+ {
+ getLogger().error("An exception occurred while saxing the page hits", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected SortField getSortField (Request request)
+ {
+ if (request.getParameter("sort-by-title-for-sorting") != null)
+ {
+ return new SortField("title-for-sorting", SortField.STRING);
+ }
+ else if (request.getParameter("sort-by-date") != null)
+ {
+ return new SortField("date", SortField.STRING);
+ }
+
+ return SortField.FIELD_SCORE;
+ }
+
+ @Override
+ protected void saxFormFields (Request request, String siteName, String lang) throws SAXException
+ {
+ if (_searchFields.containsKey("title"))
+ {
+ XMLUtils.createElement(contentHandler, "title");
+ }
+
+ if (_searchFields.containsKey("textfield"))
+ {
+ XMLUtils.createElement(contentHandler, "textfield");
+ }
+ }
+
+ @Override
+ protected void saxCriteria(Map criteria, Request request, BitSet queryBitSet, String siteName, String lang, boolean withHitCount) throws SAXException
+ {
+ super.saxCriteria(criteria, request, queryBitSet, siteName, lang, withHitCount);
+
+ XMLUtils.startElement(contentHandler, "criteria");
+ for (String criterionName : criteria.keySet())
+ {
+ Criterion criterion = criteria.get(criterionName);
+
+ if (criterion instanceof OdfCriterion)
+ {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addCDATAAttribute("name", criterionName);
+
+ XMLUtils.startElement(contentHandler, "criterion", attrs);
+ ((OdfCriterion) criterion).getLabel().toSAX(contentHandler);
+ XMLUtils.endElement(contentHandler, "criterion");
+ }
+ }
+ XMLUtils.endElement(contentHandler, "criteria");
+ }
+
+ @Override
+ protected void saxCriterion(Criterion criterion, String siteName, String lang, BitSet criteriaValuesBitSet) throws SAXException, IOException
+ {
+ super.saxCriterion(criterion, siteName, lang, criteriaValuesBitSet);
+ }
+
+ @Override
+ protected void saxFormValues (Request request, int start, int offset) throws SAXException
+ {
+ for (String fieldName : _searchFields.keySet())
+ {
+ String value = request.getParameter(fieldName);
+ XMLUtils.createElement(contentHandler, fieldName, StringUtils.defaultString(value));
+ }
+ }
+
+ /**
+ * Get the index searcher.
+ * @param siteName
+ * @param lang
+ * @return the index searcher.
+ * @throws IOException
+ */
+ protected IndexSearcher getSearcher(String siteName, String lang) throws IOException
+ {
+ File indexDir = IndexerHelper.getIndexDir(_context, siteName, lang);
+ if (indexDir.exists() && indexDir.listFiles().length > 0)
+ {
+ return new IndexSearcher(FSDirectory.open(indexDir));
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Searcher getSearchIndex(Request request, List siteNames, String lang) throws IOException
+ {
+ return getSearcher(siteNames.get(0), lang);
+ }
+
+ @Override
+ protected void saxAdditionalInfos() throws SAXException, IOException, ProcessingException
+ {
+ super.saxAdditionalInfos();
+
+ Request request = ObjectModelHelper.getRequest(objectModel);
+
+ String forceCriteriaDisplay = request.getParameter("force-criteria-display");
+
+ if (forceCriteriaDisplay != null)
+ {
+ XMLUtils.createElement(contentHandler, "force-criteria-display", forceCriteriaDisplay);
+ }
+
+ String catalog = parameters.getParameter("catalog", "");
+ XMLUtils.createElement(contentHandler, "catalog", catalog);
+ }
+
+ @Override
+ protected String getSearchMode()
+ {
+ String searchMode = super.getSearchMode();
+
+ Request request = ObjectModelHelper.getRequest(objectModel);
+
+ String forceCriteriaDisplay = request.getParameter("force-criteria-display");
+ if (forceCriteriaDisplay != null)
+ {
+ searchMode = "criteria-and-results";
+ }
+
+ return searchMode;
+ }
+
+ @Override
+ protected List getConfiguredSortFields()
+ {
+ Request request = ObjectModelHelper.getRequest(objectModel);
+ ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName());
+
+ Map searchConfigurationCache = null;
+ List> sortsCache = null;
+
+ if (zoneItem != null)
+ {
+ searchConfigurationCache = _getSearchConfigurationCache(zoneItem.getServiceId());
+ sortsCache = (List>) searchConfigurationCache.get("sorts");
+ }
+ else
+ {
+ return null;
+ }
+
+ List sortFields = new ArrayList ();
+ for (Map sortCache : sortsCache)
+ {
+ sortFields.add(new SortField(sortCache.get("field") + _FOR_SORTING, SortField.STRING, sortCache.get("order").equals("descending")));
+ }
+
+ return sortFields;
+ }
+
+ /**
+ * Get the researched content type
+ * @return the content type
+ */
+ protected abstract String getContentType();
+
+ private void _addTitleQuery(BooleanQuery query, String title, float boost) throws ParseException, IllegalArgumentException
+ {
+ if (!StringUtils.isEmpty(title))
+ {
+ Matcher m = _TEXTFIELD_PATTERN.matcher(title);
+ if (!m.matches())
+ {
+ throw new IllegalArgumentException(title + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
+ }
+
+ QueryParser parser = new QueryParser(LuceneConstants.LUCENE_VERSION, "title", _analyser);
+ Query titleQuery = parser.parse(title);
+ titleQuery.setBoost(boost);
+ query.add(titleQuery, BooleanClause.Occur.MUST);
+ }
+ }
+
+ private void _addTextFieldQuery(BooleanQuery query, String textfield, float boost) throws ParseException, IllegalArgumentException
+ {
+ if (!StringUtils.isEmpty(textfield))
+ {
+ Matcher m = _TEXTFIELD_PATTERN.matcher(textfield);
+ if (!m.matches())
+ {
+ throw new IllegalArgumentException(textfield + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
+ }
+
+ MultiFieldQueryParser parser = new MultiFieldQueryParser(LuceneConstants.LUCENE_VERSION, _fields, _analyser);
+ Query multiQuery = parser.parse(textfield);
+ multiQuery.setBoost(boost);
+ query.add(multiQuery, BooleanClause.Occur.MUST);
+ }
+ }
+
+ private synchronized Map _getSearchConfigurationCache(String serviceId)
+ {
+ Source searchConfigurationFileSource = null;
+ try
+ {
+ searchConfigurationFileSource = _sourceResolver.resolveURI(__BOOST_CONF_DIR_PATH + "/" + serviceId + ".xml");
+ if (!searchConfigurationFileSource.exists())
+ {
+ _searchConfigurationCache.remove(serviceId);
+ }
+ else
+ {
+ long lastModified = searchConfigurationFileSource.getLastModified();
+ if (!_lastConfUpdate.containsKey(serviceId) || _lastConfUpdate.get(serviceId) != lastModified)
+ {
+ // Initialization/Update required
+ _searchConfigurationCache.put(serviceId, _cacheConfigurationValues(searchConfigurationFileSource));
+ _lastConfUpdate.put(serviceId, lastModified);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ getLogger().error("An exception occurred while reading the search configuration file.", e);
+ _searchConfigurationCache.remove(serviceId);
+ }
+ finally
+ {
+ _sourceResolver.release(searchConfigurationFileSource);
+ }
+
+ return _searchConfigurationCache.get(serviceId);
+ }
+
+ @SuppressWarnings("resource")
+ private Map _cacheConfigurationValues(Source searchConfigurationSource) throws SourceNotFoundException, IOException, ConfigurationException, SAXException
+ {
+ Map searchConfigurationValues = new HashMap ();
+ InputStream is = null;
+
+ try
+ {
+ is = searchConfigurationSource.getInputStream();
+ Configuration configuration = new DefaultConfigurationBuilder().build(searchConfigurationSource.getInputStream());
+
+ // Boosts configuration
+ Configuration fieldsConfiguration = configuration.getChild("fields");
+ Map boosts = new HashMap ();
+
+ for (Configuration fieldConfiguration : fieldsConfiguration.getChildren("field"))
+ {
+ String fieldName = fieldConfiguration.getAttribute("name", null);
+ float fieldBoost = fieldConfiguration.getAttributeAsFloat("boost", -1);
+ if (fieldName == null || fieldBoost == -1)
+ {
+ // ignore the line
+ getLogger().warn("The configuration file has either wrong attribute names or values at '" + fieldConfiguration.getLocation() + "'. This corresponding line will be ignored.");
+ }
+ else
+ {
+ boosts.put(fieldName, fieldBoost);
+ }
+ }
+
+ searchConfigurationValues.put("boosts", boosts);
+
+ // Sorts configuration
+ Configuration sortsConfiguration = configuration.getChild("sorts");
+ List> sortList = new ArrayList> ();
+
+ for (Configuration sortConfiguration : sortsConfiguration.getChildren("sort"))
+ {
+ Map sort = new HashMap ();
+
+ String field = sortConfiguration.getAttribute("field", null);
+ String order = sortConfiguration.getAttribute("order", null);
+ if (field == null)
+ {
+ // ignore the line
+ getLogger().warn("The field attribute for a sort is mandatory. It is either mispelled or non-valued at '" + sortConfiguration.getLocation() + "'. The corresponding line will be ignored");
+ }
+ else
+ {
+ sort.put("field", field);
+ sort.put("order", order != null ? order : "ascending");
+ }
+
+ sortList.add(sort);
+ }
+
+ searchConfigurationValues.put("sorts", sortList);
+
+ return searchConfigurationValues;
+ }
+ finally
+ {
+ IOUtils.closeQuietly(is);
+ }
+ }
+
+ private float _getConfiguredBoost(String fieldName, Map boostCache)
+ {
+ if (boostCache != null && boostCache.containsKey(fieldName))
+ {
+ return boostCache.get(fieldName);
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ /**
+ * ODF-specific search criterion.
+ */
+ class OdfCriterion extends Criterion
+ {
+
+ private I18nizableText _label;
+
+ /**
+ * Build an OdfCriterion.
+ */
+ public OdfCriterion()
+ {
+ super();
+ }
+
+ /**
+ * Build an OdfCriterion.
+ * @param fieldName
+ * @param label
+ * @param xmlGroupName
+ * @param values
+ */
+ public OdfCriterion(String fieldName, I18nizableText label, String xmlGroupName, Map values)
+ {
+ super(fieldName, xmlGroupName, values);
+ this._label = label;
+ }
+
+ /**
+ * Build an OdfCriterion.
+ * @param fieldName
+ * @param label
+ * @param luceneTermName
+ * @param xmlGroupName
+ * @param values
+ */
+ public OdfCriterion(String fieldName, I18nizableText label, String luceneTermName, String xmlGroupName, Map values)
+ {
+ super(fieldName, luceneTermName, xmlGroupName, values);
+ this._label = label;
+ }
+
+ /**
+ * Build an OdfCriterion.
+ * @param fieldName
+ * @param label
+ * @param luceneTermName
+ * @param xmlElementName
+ * @param xmlGroupName
+ * @param values
+ */
+ public OdfCriterion(String fieldName, I18nizableText label, String luceneTermName, String xmlElementName, String xmlGroupName, Map values)
+ {
+ super(fieldName, luceneTermName, xmlElementName, xmlGroupName, values);
+ this._label = label;
+ }
+
+ /**
+ * Get the label.
+ * @return the label
+ */
+ public I18nizableText getLabel()
+ {
+ return _label;
+ }
+
+ /**
+ * Set the label.
+ * @param label the label to set
+ */
+ public void setLabel(I18nizableText label)
+ {
+ this._label = label;
+ }
+ }
+}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/CourseODFSearch.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/CourseODFSearch.java (revision 0)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/CourseODFSearch.java (revision 0)
@@ -0,0 +1,36 @@
+package org.ametys.plugins.odfweb.generators;
+
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.xml.sax.SAXException;
+
+import org.ametys.odf.course.CourseFactory;
+
+/**
+ * Generate the results of a search on courses
+ */
+public class CourseODFSearch extends AbstractODFSearchGenerator
+{
+ @Override
+ protected String getContentType()
+ {
+
+ return CourseFactory.COURSE_CONTENT_TYPE;
+ }
+
+ @Override
+ protected void saxAdditionalInfosOnPageHit(Document doc) throws SAXException
+ {
+ Field[] referencingPrograms = doc.getFields("referencingProgram");
+ for (Field referencingProgram : referencingPrograms)
+ {
+ String value = referencingProgram.stringValue();
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addCDATAAttribute("path", value.substring(0, value.indexOf(";")));
+ attrs.addCDATAAttribute("title", value.substring(value.indexOf(";") + 1));
+ XMLUtils.createElement(contentHandler, "referencingProgram", attrs);
+ }
+ }
+}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/ODFSearch.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/ODFSearch.java (revision 29090)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/generators/ODFSearch.java (working copy)
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Anyware Services
+ * Copyright 2015 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,548 +15,36 @@
*/
package org.ametys.plugins.odfweb.generators;
-import java.io.File;
-import java.io.IOException;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.cocoon.ProcessingException;
-import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.cocoon.environment.Request;
import org.apache.cocoon.xml.AttributesImpl;
import org.apache.cocoon.xml.XMLUtils;
-import org.apache.commons.lang.StringUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.queryParser.MultiFieldQueryParser;
-import org.apache.lucene.queryParser.ParseException;
-import org.apache.lucene.queryParser.QueryParser;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.ScoreDoc;
-import org.apache.lucene.search.Searcher;
-import org.apache.lucene.search.SortField;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.TopDocs;
-import org.apache.lucene.store.FSDirectory;
import org.xml.sax.SAXException;
-import org.ametys.cms.contenttype.ContentType;
-import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
-import org.ametys.cms.contenttype.MetadataDefinition;
-import org.ametys.cms.lucene.FieldNames;
-import org.ametys.odf.enumeration.OdfEnumerationConstant;
-import org.ametys.odf.enumeration.OdfEnumerationHelper;
-import org.ametys.odf.orgunit.RootOrgUnitProvider;
-import org.ametys.runtime.util.I18nizableText;
-import org.ametys.runtime.util.parameter.Enumerator;
-import org.ametys.web.frontoffice.AbstractSearchGenerator;
-import org.ametys.web.lucene.IndexerHelper;
-import org.ametys.web.lucene.LuceneConstants;
-import org.ametys.web.repository.page.ZoneItem;
+import org.ametys.odf.program.ProgramFactory;
/**
* Search generator for ODF pages
*/
-public class ODFSearch extends AbstractSearchGenerator
+public class ODFSearch extends AbstractODFSearchGenerator
{
-
- /** The ODF constants provider. */
- protected OdfEnumerationHelper _enumerationHelper;
-
- /** The root org unit provider. */
- protected RootOrgUnitProvider _rootOrgUnitProvider;
-
- /** The content type extension point. */
- protected ContentTypeExtensionPoint _cTypeEP;
-
- /** The inputs as a Map fieldName -> metadataPath. */
- protected Map _searchFields;
-
- @Override
- public void service(ServiceManager smanager) throws ServiceException
- {
- super.service(smanager);
- _enumerationHelper = (OdfEnumerationHelper) smanager.lookup(OdfEnumerationHelper.ROLE);
- _rootOrgUnitProvider = (RootOrgUnitProvider) smanager.lookup(RootOrgUnitProvider.ROLE);
- _cTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
- }
-
- @Override
- public void generate() throws IOException, SAXException, ProcessingException
- {
- String[] fields = parameters.getParameter("fields", "").split(",");
-
- _searchFields = new LinkedHashMap();
-
- for (String metadataPath : fields)
- {
- int slashPos = metadataPath.lastIndexOf('/');
- String fieldName = slashPos < 0 ? metadataPath : metadataPath.substring(slashPos + 1);
-
- _searchFields.put(fieldName, metadataPath);
- }
-
- super.generate();
- }
-
- @Override
- protected Query getQuery (Request request) throws ParseException, IllegalArgumentException
- {
- return getQuery(getParameterValues(request));
- }
-
- /**
- * Extract the parameter values from the request.
- * @param request the request.
- * @return the parameter values.
- */
- protected Map getParameterValues(Request request)
- {
- Map params = new HashMap();
-
- for (String fieldName : _searchFields.keySet())
- {
- params.put(fieldName, request.getParameter(fieldName));
- }
-
- return params;
- }
-
- /**
- * Get the query.
- * @param params
- * @return the lucene Query.
- * @throws ParseException
- * @throws IllegalArgumentException
- */
- protected Query getQuery(Map params) throws ParseException, IllegalArgumentException
- {
- BooleanQuery query = new BooleanQuery();
-
- TermQuery termQuery = new TermQuery(new Term(FieldNames.CONTENT_TYPES, "org.ametys.plugins.odf.Content.program"));
- termQuery.setBoost(0);
- query.add(termQuery, BooleanClause.Occur.MUST);
-
- // Titre
- _addTitleQuery(query, params.get("title"));
-
- // Catalog
- String catalog = StringUtils.defaultIfEmpty(params.get("catalog"), parameters.getParameter("catalog", ""));
- if (StringUtils.isEmpty(catalog))
- {
- Request request = ObjectModelHelper.getRequest(objectModel);
- ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName());
- if (zoneItem != null)
- {
- catalog = zoneItem.getServiceParameters().getString("catalog", "");
- }
- }
- if (StringUtils.isNotEmpty(catalog))
- {
- termQuery = new TermQuery(new Term("catalog", catalog));
- termQuery.setBoost(0);
- query.add(termQuery, BooleanClause.Occur.MUST);
- }
-
- // Keywords
- _addTextFieldQuery(query, params.get("textfield"));
-
- for (String fieldName : _searchFields.keySet())
- {
- if (!fieldName.equals("title") && !fieldName.equals("textfield") && !fieldName.equals("catalog"))
- {
- String value = params.get(fieldName);
- if (StringUtils.isNotEmpty(value))
- {
- termQuery = new TermQuery(new Term(fieldName, value));
- termQuery.setBoost(0);
- query.add(termQuery, BooleanClause.Occur.MUST);
- }
- }
- }
-
- return query;
- }
-
@Override
- protected String[] getFields ()
+ protected String getContentType()
{
- // TODO
- return new String[] {"title", "keywords", "full"};
- }
-
- @Override
- protected Map getCriteria(Request request, String siteName, String lang)
- {
- Map criteria = new HashMap();
-
- for (String fieldName : _searchFields.keySet())
- {
- if (!fieldName.equals("title") && !fieldName.equals("textfield"))
- {
- String metadataPath = _searchFields.get(fieldName);
-
- Criterion criterion = getCriterion(fieldName, metadataPath);
-
- if (criterion != null)
- {
- criteria.put(fieldName, criterion);
- }
- }
- }
-
- return criteria;
- }
-
- /**
- * Get the criterion corresponding to the field.
- * @param fieldName the field name.
- * @param metadataPath the corresponding metadata path.
- * @return the corresponding Criterion.
- */
- protected Criterion getCriterion(String fieldName, String metadataPath)
- {
- try
- {
- ContentType programCType = _cTypeEP.getExtension("org.ametys.plugins.odf.Content.program");
-
- MetadataDefinition metadataDefinition = getMetadataDefinition(programCType, metadataPath);
-
- Enumerator enumerator = metadataDefinition.getEnumerator();
-
- if (enumerator != null)
- {
- Map values = new LinkedHashMap();
- Map entries = enumerator.getEntries();
- for (Entry entry : entries.entrySet())
- {
- values.put(entry.getKey().toString(), entry.getValue());
- }
-
- // Odf-specific criterion (with list label).
- return new OdfCriterion(fieldName, metadataDefinition.getLabel(), "criterion-enumerated-" + fieldName, values);
- }
- }
- catch (Exception e)
- {
- getLogger().error("Error retrieving the values of an enumerator.", e);
- throw new IllegalStateException("Error retrieving the values of an enumerator.", e);
- }
-
- return null;
- }
-
- /**
- * Get a metadata definition from its path.
- * @param contentType the content type.
- * @param metadataPath the metadata path.
- * @return the metadata definition or null if not found.
- */
- protected MetadataDefinition getMetadataDefinition(ContentType contentType, String metadataPath)
- {
- String[] pathSegments = StringUtils.split(metadataPath, '/');
-
- if (pathSegments.length == 0)
- {
- return null;
- }
-
- MetadataDefinition metadataDef = contentType.getMetadataDefinition(pathSegments[0]);
-
- for (int i = 1; i < pathSegments.length && metadataDef != null; i++)
- {
- metadataDef = metadataDef.getMetadataDefinition(pathSegments[i]);
- }
-
- return metadataDef;
- }
-
- @Override
- protected void saxHits (Searcher searcher, TopDocs rs, int start, int offset) throws SAXException, IOException
- {
- ScoreDoc[] scoreDocs = rs.scoreDocs;
-
- int limit = Math.min(start + offset, scoreDocs.length);
-
- for (int i = start; i < limit; i++)
- {
- Document doc = searcher.doc(rs.scoreDocs[i].doc);
-
- if (TYPE_PAGE.equals(doc.get(TYPE)))
- {
- saxPageHit(rs, doc, i);
- }
- }
+ return ProgramFactory.PROGRAM_CONTENT_TYPE;
}
@Override
protected void saxAdditionalInfosOnPageHit(Document doc) throws SAXException
{
- String codeDomain = doc.get("domain");
- I18nizableText itemLabel = _enumerationHelper.getItemLabel(OdfEnumerationConstant.DOMAIN, codeDomain);
-
- AttributesImpl attr = new AttributesImpl();
- attr.addCDATAAttribute("code", codeDomain);
- XMLUtils.startElement(contentHandler, "domain", attr);
- itemLabel.toSAX(contentHandler);
- XMLUtils.endElement(contentHandler, "domain");
-
Field[] subprograms = doc.getFields("subprograms");
for (Field subprogram : subprograms)
{
String value = subprogram.stringValue();
- attr = new AttributesImpl();
- attr.addCDATAAttribute("path", value.substring(0, value.indexOf(";")));
- attr.addCDATAAttribute("title", value.substring(value.indexOf(";") + 1));
- XMLUtils.createElement(contentHandler, "subprogram", attr);
- }
- }
-
- @Override
- protected SortField getSortField (Request request)
- {
- if (request.getParameter("sort-by-title-for-sorting") != null)
- {
- return new SortField("title-for-sorting", SortField.STRING);
- }
- else if (request.getParameter("sort-by-date") != null)
- {
- return new SortField("date", SortField.STRING);
- }
-
- return SortField.FIELD_SCORE;
- }
-
- @Override
- protected void saxFormFields (Request request, String siteName, String lang) throws SAXException
- {
- if (_searchFields.containsKey("title"))
- {
- XMLUtils.createElement(contentHandler, "title");
- }
-
- if (_searchFields.containsKey("textfield"))
- {
- XMLUtils.createElement(contentHandler, "textfield");
- }
- }
-
- @Override
- protected void saxCriteria(Map criteria, Request request, BitSet queryBitSet, String siteName, String lang, boolean withHitCount) throws SAXException
- {
- super.saxCriteria(criteria, request, queryBitSet, siteName, lang, withHitCount);
-
- XMLUtils.startElement(contentHandler, "criteria");
- for (String criterionName : criteria.keySet())
- {
- Criterion criterion = criteria.get(criterionName);
-
- if (criterion instanceof OdfCriterion)
- {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addCDATAAttribute("name", criterionName);
-
- XMLUtils.startElement(contentHandler, "criterion", attrs);
- ((OdfCriterion) criterion).getLabel().toSAX(contentHandler);
- XMLUtils.endElement(contentHandler, "criterion");
- }
- }
- XMLUtils.endElement(contentHandler, "criteria");
- }
-
- @Override
- protected void saxCriterion(Criterion criterion, String siteName, String lang, BitSet criteriaValuesBitSet) throws SAXException, IOException
- {
- super.saxCriterion(criterion, siteName, lang, criteriaValuesBitSet);
- }
-
- @Override
- protected void saxFormValues (Request request, int start, int offset) throws SAXException
- {
- for (String fieldName : _searchFields.keySet())
- {
- String value = request.getParameter(fieldName);
- XMLUtils.createElement(contentHandler, fieldName, StringUtils.defaultString(value));
- }
- }
-
- /**
- * Get the index searcher.
- * @param siteName
- * @param lang
- * @return the index searcher.
- * @throws IOException
- */
- protected IndexSearcher getSearcher(String siteName, String lang) throws IOException
- {
- File indexDir = IndexerHelper.getIndexDir(_context, siteName, lang);
- if (indexDir.exists() && indexDir.listFiles().length > 0)
- {
- return new IndexSearcher(FSDirectory.open(indexDir));
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addCDATAAttribute("path", value.substring(0, value.indexOf(";")));
+ attrs.addCDATAAttribute("title", value.substring(value.indexOf(";") + 1));
+ XMLUtils.createElement(contentHandler, "subprogram", attrs);
}
-
- return null;
}
-
- @Override
- protected Searcher getSearchIndex(Request request, List siteNames, String lang) throws IOException
- {
- return getSearcher(siteNames.get(0), lang);
- }
-
- @Override
- protected void saxAdditionalInfos() throws SAXException, IOException, ProcessingException
- {
- super.saxAdditionalInfos();
-
- Request request = ObjectModelHelper.getRequest(objectModel);
-
- String forceCriteriaDisplay = request.getParameter("force-criteria-display");
-
- if (forceCriteriaDisplay != null)
- {
- XMLUtils.createElement(contentHandler, "force-criteria-display", forceCriteriaDisplay);
- }
-
- String catalog = parameters.getParameter("catalog", "");
- XMLUtils.createElement(contentHandler, "catalog", catalog);
- }
-
- @Override
- protected String getSearchMode()
- {
- String searchMode = super.getSearchMode();
-
- Request request = ObjectModelHelper.getRequest(objectModel);
-
- String forceCriteriaDisplay = request.getParameter("force-criteria-display");
- if (forceCriteriaDisplay != null)
- {
- searchMode = "criteria-and-results";
- }
-
- return searchMode;
- }
-
- private void _addTitleQuery(BooleanQuery query, String title) throws ParseException, IllegalArgumentException
- {
- if (!StringUtils.isEmpty(title))
- {
- Matcher m = _TEXTFIELD_PATTERN.matcher(title);
- if (!m.matches())
- {
- throw new IllegalArgumentException(title + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
- }
-
- QueryParser parser = new QueryParser(LuceneConstants.LUCENE_VERSION, "title", _analyser);
- Query titleQuery = parser.parse(title);
- query.add(titleQuery, BooleanClause.Occur.MUST);
- }
- }
-
- private void _addTextFieldQuery(BooleanQuery query, String textfield) throws ParseException, IllegalArgumentException
- {
- if (!StringUtils.isEmpty(textfield))
- {
- Matcher m = _TEXTFIELD_PATTERN.matcher(textfield);
- if (!m.matches())
- {
- throw new IllegalArgumentException(textfield + " does not match the expected regular expression : " + _TEXTFIELD_PATTERN.pattern());
- }
-
- MultiFieldQueryParser parser = new MultiFieldQueryParser(LuceneConstants.LUCENE_VERSION, _fields, _analyser);
- Query multiQuery = parser.parse(textfield);
- query.add(multiQuery, BooleanClause.Occur.MUST);
- }
- }
-
- /**
- * ODF-specific search criterion.
- */
- class OdfCriterion extends Criterion
- {
-
- private I18nizableText _label;
-
- /**
- * Build an OdfCriterion.
- */
- public OdfCriterion()
- {
- super();
- }
-
- /**
- * Build an OdfCriterion.
- * @param fieldName
- * @param label
- * @param xmlGroupName
- * @param values
- */
- public OdfCriterion(String fieldName, I18nizableText label, String xmlGroupName, Map values)
- {
- super(fieldName, xmlGroupName, values);
- this._label = label;
- }
-
- /**
- * Build an OdfCriterion.
- * @param fieldName
- * @param label
- * @param luceneTermName
- * @param xmlGroupName
- * @param values
- */
- public OdfCriterion(String fieldName, I18nizableText label, String luceneTermName, String xmlGroupName, Map values)
- {
- super(fieldName, luceneTermName, xmlGroupName, values);
- this._label = label;
- }
-
- /**
- * Build an OdfCriterion.
- * @param fieldName
- * @param label
- * @param luceneTermName
- * @param xmlElementName
- * @param xmlGroupName
- * @param values
- */
- public OdfCriterion(String fieldName, I18nizableText label, String luceneTermName, String xmlElementName, String xmlGroupName, Map values)
- {
- super(fieldName, luceneTermName, xmlElementName, xmlGroupName, values);
- this._label = label;
- }
-
- /**
- * Get the label.
- * @return the label
- */
- public I18nizableText getLabel()
- {
- return _label;
- }
-
- /**
- * Set the label.
- * @param label the label to set
- */
- public void setLabel(I18nizableText label)
- {
- this._label = label;
- }
-
- }
-
}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/AbstractSearchFieldEnumerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/AbstractSearchFieldEnumerator.java (working copy)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/AbstractSearchFieldEnumerator.java (working copy)
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Anyware Services
+ * Copyright 2015 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
import org.ametys.cms.contenttype.MetadataDefinition;
import org.ametys.odf.contenttype.ODFContentType;
-import org.ametys.odf.program.ProgramFactory;
import org.ametys.runtime.plugin.component.PluginAware;
import org.ametys.runtime.util.I18nizableText;
import org.ametys.runtime.util.parameter.Enumerator;
@@ -35,7 +34,7 @@
/**
* Enumerates search fields for the ODF search service.
*/
-public class SearchFieldEnumerator extends AbstractLogEnabled implements Enumerator, Serviceable, PluginAware
+public abstract class AbstractSearchFieldEnumerator extends AbstractLogEnabled implements Enumerator, Serviceable, PluginAware
{
/** The content type extension point. */
@@ -59,7 +58,7 @@
@Override
public Map getEntries() throws Exception
{
- ContentType programCType = _cTypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
+ ContentType cType = _cTypeEP.getExtension(getContentType());
String catalogue = "plugin." + _pluginName;
Map entries = new LinkedHashMap();
@@ -69,9 +68,9 @@
entries.put("textfield", new I18nizableText(catalogue, "PLUGINS_ODFWEB_SERVICE_SEARCH_FIELD_KEYWORDS"));
// Enumerated fields.
- if (programCType instanceof ODFContentType)
+ if (cType instanceof ODFContentType)
{
- Map enumeratedMetadatas = ((ODFContentType) programCType).getEnumeratedMetadatas();
+ Map enumeratedMetadatas = ((ODFContentType) cType).getEnumeratedMetadatas();
for (String path : enumeratedMetadatas.keySet())
{
@@ -90,4 +89,9 @@
return getEntries().get(value);
}
+ /**
+ * The content type to enumerate metadatas from
+ * @return string the id of the content type
+ */
+ protected abstract String getContentType();
}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/CourseODFSearchFieldEnumerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/CourseODFSearchFieldEnumerator.java (revision 0)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/CourseODFSearchFieldEnumerator.java (revision 0)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015 Anyware Services
+ *
+ * Licensed 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.
+ */
+package org.ametys.plugins.odfweb.services;
+
+import org.ametys.odf.course.CourseFactory;
+
+/**
+ * Enumerates the search fields for a course
+ */
+public class CourseODFSearchFieldEnumerator extends AbstractSearchFieldEnumerator
+{
+ @Override
+ protected String getContentType()
+ {
+ return CourseFactory.COURSE_CONTENT_TYPE;
+ }
+}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/ODFSearchFieldEnumerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/ODFSearchFieldEnumerator.java (revision 0)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/ODFSearchFieldEnumerator.java (revision 0)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015 Anyware Services
+ *
+ * Licensed 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.
+ */
+package org.ametys.plugins.odfweb.services;
+
+import org.ametys.odf.program.ProgramFactory;
+
+/**
+ * Enumerate the search fields for a program
+ */
+public class ODFSearchFieldEnumerator extends AbstractSearchFieldEnumerator
+{
+ @Override
+ protected String getContentType()
+ {
+ return ProgramFactory.PROGRAM_CONTENT_TYPE;
+ }
+}
Index: main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/SearchFieldEnumerator.java
===================================================================
--- main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/SearchFieldEnumerator.java (revision 29090)
+++ main/plugin-odf-web/src/org/ametys/plugins/odfweb/services/SearchFieldEnumerator.java (working copy)
@@ -1,93 +0,0 @@
-/*
- * Copyright 2014 Anyware Services
- *
- * Licensed 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.
- */
-package org.ametys.plugins.odfweb.services;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-
-import org.ametys.cms.contenttype.ContentType;
-import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
-import org.ametys.cms.contenttype.MetadataDefinition;
-import org.ametys.odf.contenttype.ODFContentType;
-import org.ametys.odf.program.ProgramFactory;
-import org.ametys.runtime.plugin.component.PluginAware;
-import org.ametys.runtime.util.I18nizableText;
-import org.ametys.runtime.util.parameter.Enumerator;
-
-/**
- * Enumerates search fields for the ODF search service.
- */
-public class SearchFieldEnumerator extends AbstractLogEnabled implements Enumerator, Serviceable, PluginAware
-{
-
- /** The content type extension point. */
- protected ContentTypeExtensionPoint _cTypeEP;
-
- /** The plugin name. */
- protected String _pluginName;
-
- @Override
- public void service(ServiceManager serviceManager) throws ServiceException
- {
- _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE);
- }
-
- @Override
- public void setPluginInfo(String pluginName, String featureName)
- {
- _pluginName = pluginName;
- }
-
- @Override
- public Map getEntries() throws Exception
- {
- ContentType programCType = _cTypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
- String catalogue = "plugin." + _pluginName;
-
- Map entries = new LinkedHashMap();
-
- // Static fields.
- entries.put("title", new I18nizableText(catalogue, "PLUGINS_ODFWEB_SERVICE_SEARCH_FIELD_LABEL"));
- entries.put("textfield", new I18nizableText(catalogue, "PLUGINS_ODFWEB_SERVICE_SEARCH_FIELD_KEYWORDS"));
-
- // Enumerated fields.
- if (programCType instanceof ODFContentType)
- {
- Map enumeratedMetadatas = ((ODFContentType) programCType).getEnumeratedMetadatas();
-
- for (String path : enumeratedMetadatas.keySet())
- {
- MetadataDefinition metadataDefinition = enumeratedMetadatas.get(path);
-
- entries.put(path, metadataDefinition.getLabel());
- }
- }
-
- return entries;
- }
-
- @Override
- public I18nizableText getEntry(String value) throws Exception
- {
- return getEntries().get(value);
- }
-
-}