001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/search/CmsSearchParameters.java,v $
003: * Date : $Date: 2008-02-27 12:05:38 $
004: * Version: $Revision: 1.12 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.search;
033:
034: import org.opencms.i18n.CmsEncoder;
035: import org.opencms.main.CmsException;
036: import org.opencms.main.CmsIllegalArgumentException;
037: import org.opencms.main.CmsLog;
038: import org.opencms.main.OpenCms;
039: import org.opencms.search.fields.CmsSearchField;
040: import org.opencms.util.CmsStringUtil;
041:
042: import java.util.ArrayList;
043: import java.util.Iterator;
044: import java.util.LinkedList;
045: import java.util.List;
046:
047: import org.apache.commons.collections.ListUtils;
048: import org.apache.commons.logging.Log;
049: import org.apache.lucene.search.Sort;
050: import org.apache.lucene.search.SortField;
051:
052: /**
053: * Contains the search parameters for a call to <code>{@link org.opencms.search.CmsSearchIndex#search(org.opencms.file.CmsObject, CmsSearchParameters)}</code>.<p>
054: *
055: * Primary purpose is translation of search arguments to response parameters and from request parameters as
056: * well as support for creation of restrictions of several search query parameter sets. <p>
057: *
058: * @author Alexander Kandzior
059: *
060: * @version $Revision: 1.12 $
061: *
062: * @since 6.0.0
063: */
064: public class CmsSearchParameters {
065:
066: /** Sort result documents by date of creation, then score. */
067: public static final Sort SORT_DATE_CREATED = new Sort(
068: new SortField[] {
069: new SortField(CmsSearchField.FIELD_DATE_CREATED,
070: SortField.STRING, true),
071: SortField.FIELD_SCORE });
072:
073: /** Sort result documents by date of last modification, then score. */
074: public static final Sort SORT_DATE_LASTMODIFIED = new Sort(
075: new SortField[] {
076: new SortField(
077: CmsSearchField.FIELD_DATE_LASTMODIFIED,
078: SortField.STRING, true),
079: SortField.FIELD_SCORE });
080:
081: /** Default sort order (by document score - for this <code>null</code> gave best performance). */
082: public static final Sort SORT_DEFAULT = null;
083:
084: /** Names of the default sort options. */
085: public static final String[] SORT_NAMES = { "SORT_DEFAULT",
086: "SORT_DATE_CREATED", "SORT_DATE_LASTMODIFIED", "SORT_TITLE" };
087:
088: /** Sort result documents by title, then score. */
089: public static final Sort SORT_TITLE = new Sort(new SortField[] {
090: new SortField(CmsSearchField.FIELD_TITLE),
091: SortField.FIELD_SCORE });
092:
093: /** The log object for this class. */
094: private static final Log LOG = CmsLog
095: .getLog(CmsSearchParameters.class);
096:
097: /** The number of displayed pages returned by getPageLinks(). */
098: protected int m_displayPages;
099:
100: /** The number of matches per page. */
101: protected int m_matchesPerPage;
102:
103: /** If <code>true</code>, the category count is calculated for all search results. */
104: private boolean m_calculateCategories;
105:
106: /** The list of categories to limit the search to. */
107: private List m_categories;
108:
109: /** Indicates if all fields should be used for generating the excerpt, regardless if they have been searched or not. */
110: private boolean m_excerptOnlySearchedFields;
111:
112: /** The list of search index fields to search in. */
113: private List m_fields;
114:
115: /** The index to search. */
116: private CmsSearchIndex m_index;
117:
118: /** The creation date the resources have to have as maximum. */
119: private long m_maxDateCreated;
120:
121: /** The last modification date the resources have to have as maximum. */
122: private long m_maxDateLastModified;
123:
124: /** The creation date the resources have to have as minimum. */
125: private long m_minDateCreated;
126:
127: /** The last modification date the resources have to have as minimum. */
128: private long m_minDateLastModified;
129:
130: /** The current result page. */
131: private int m_page;
132:
133: /** The search query to use. */
134: private String m_query;
135:
136: /** The minimum length of the search query. */
137: private int m_queryLength;
138:
139: /** Only resource that are sub-resource of one of the search roots are included in the search result. */
140: private List m_roots;
141:
142: /** The sort order for the search. */
143: private Sort m_sort;
144:
145: /**
146: * Creates a new search parameter instance with no search query and
147: * default values for the remaining parameters. <p>
148: *
149: * Before using this search parameters for a search method
150: * <code>{@link #setQuery(String)}</code> has to be invoked. <p>
151: *
152: */
153: public CmsSearchParameters() {
154:
155: this ("");
156: }
157:
158: /**
159: * Creates a new search parameter instance with the provided search query and
160: * default values for the remaining parameters. <p>
161: *
162: * Only the "meta" field (combination of content and title) will be used for search.
163: * No search root restriction is chosen.
164: * No category restriction is used.
165: * No categorie counts are calculated for the result.
166: * Sorting is turned off. This is a simple but fast setup. <p>
167: *
168: * @param query the query to search for
169: */
170: public CmsSearchParameters(String query) {
171:
172: this (query, null, null, null, false, null);
173:
174: }
175:
176: /**
177: * Creates a new search parameter instance with the provided parameter values.<p>
178: *
179: * @param query the search term to search the index
180: * @param fields the list of fields to search
181: * @param roots only resource that are sub-resource of one of the search roots are included in the search result
182: * @param categories the list of categories to limit the search to
183: * @param calculateCategories if <code>true</code>, the category count is calculated for all search results
184: * (use with caution, this option uses much performance)
185: * @param sort the sort order for the search
186: */
187: public CmsSearchParameters(String query, List fields, List roots,
188: List categories, boolean calculateCategories, Sort sort) {
189:
190: super ();
191: m_query = (query == null) ? "" : query;
192: if (fields == null) {
193: fields = new ArrayList(2);
194: fields.add(CmsSearchIndex.DOC_META_FIELDS[0]);
195: fields.add(CmsSearchIndex.DOC_META_FIELDS[1]);
196: }
197: m_fields = fields;
198: if (roots == null) {
199: roots = new ArrayList();
200: }
201: m_roots = roots;
202: m_categories = (categories == null) ? new LinkedList()
203: : categories;
204: m_calculateCategories = calculateCategories;
205: // null sort is allowed default
206: m_sort = sort;
207: m_page = 1;
208: m_queryLength = -1;
209: m_matchesPerPage = 10;
210: m_displayPages = 10;
211:
212: m_minDateCreated = Long.MIN_VALUE;
213: m_maxDateCreated = Long.MAX_VALUE;
214: m_minDateLastModified = Long.MIN_VALUE;
215: m_maxDateLastModified = Long.MAX_VALUE;
216: }
217:
218: /**
219: * Returns wether category counts are calculated for search results or not. <p>
220: *
221: * @return a boolean that tells wether category counts are calculated for search results or not
222: */
223: public boolean getCalculateCategories() {
224:
225: return m_calculateCategories;
226: }
227:
228: /**
229: * Returns the list of categories to limit the search to.<p>
230: *
231: * @return the list of categories to limit the search to
232: */
233: public List getCategories() {
234:
235: return m_categories;
236: }
237:
238: /**
239: * Returns the maximum number of pages which should be shown.<p>
240: *
241: * @return the maximum number of pages which should be shown
242: */
243: public int getDisplayPages() {
244:
245: return m_displayPages;
246: }
247:
248: /**
249: * Returns the list of search index field names (Strings) to search in.<p>
250: *
251: * @return the list of search index field names (Strings) to search in
252: */
253: public List getFields() {
254:
255: return m_fields;
256: }
257:
258: /**
259: * Get the name of the index for the search.<p>
260: *
261: * @return the name of the index for the search
262: */
263: public String getIndex() {
264:
265: return m_index.getName();
266: }
267:
268: /**
269: * Gets the number of matches displayed on each page.<p>
270: *
271: * @return matches per result page
272: */
273: public int getMatchesPerPage() {
274:
275: return m_matchesPerPage;
276: }
277:
278: /**
279: * Returns the creation date the resources have to have as maximum.<p>
280: *
281: * @return the creation date the resources have to have as maximum
282: */
283: public long getMaxDateCreated() {
284:
285: return m_maxDateCreated;
286: }
287:
288: /**
289: * Returns the last modification date the resources have to have as maximum.<p>
290: *
291: * @return the last modification date the resources have to have as maximum
292: */
293: public long getMaxDateLastModified() {
294:
295: return m_maxDateLastModified;
296: }
297:
298: /**
299: * Returns the creation date the resources have to have as minimum.<p>
300: *
301: * @return the creation date the resources have to have as minimum
302: */
303: public long getMinDateCreated() {
304:
305: return m_minDateCreated;
306: }
307:
308: /**
309: * Returns the last modification date the resources have to have as minimum.<p>
310: *
311: * @return the last modification date the resources have to have as minimum
312: */
313: public long getMinDateLastModified() {
314:
315: return m_minDateLastModified;
316: }
317:
318: /**
319: * Returns the search query to use.<p>
320: *
321: * @return the search query to use
322: */
323: public String getQuery() {
324:
325: return m_query;
326: }
327:
328: /**
329: * Gets the minimum search query length.<p>
330: *
331: * @return the minimum search query length
332: */
333: public int getQueryLength() {
334:
335: return m_queryLength;
336: }
337:
338: /**
339: * Returns the list of strings of search roots to use.<p>
340: *
341: * Only resource that are sub-resource of one of the search roots are included in the search result.<p>
342: *
343: * @return the list of strings of search roots to use
344: */
345: public List getRoots() {
346:
347: return m_roots;
348: }
349:
350: /**
351: * Returns the list of categories to limit the search to.<p>
352: *
353: * @return the list of categories to limit the search to
354: */
355: public String getSearchCategories() {
356:
357: return toSeparatedString(getCategories(), ',');
358: }
359:
360: /**
361: * Returns the search index to search in or null if not set before
362: * (<code>{@link #setSearchIndex(CmsSearchIndex)}</code>). <p>
363: *
364: * @return the search index to search in or null if not set before (<code>{@link #setSearchIndex(CmsSearchIndex)}</code>)
365: */
366: public CmsSearchIndex getSearchIndex() {
367:
368: return m_index;
369: }
370:
371: /**
372: * Returns the search page to display.<p>
373: *
374: * @return the search page to display
375: */
376: public int getSearchPage() {
377:
378: return m_page;
379: }
380:
381: /**
382: * Returns the comma separated lists of root folder names to restrict search to.<p>
383: *
384: * This method is a "sibling" to method <code>{@link #getRoots()}</code> but with
385: * the support of being useable with widget technology. <p>
386: *
387: * @return the comma separated lists of field names to search in
388: *
389: * @see #setSortName(String)
390: */
391:
392: public String getSearchRoots() {
393:
394: return toSeparatedString(m_roots, ',');
395: }
396:
397: /**
398: * Returns the instance that defines the sort order for the results.
399: *
400: * @return the instance that defines the sort order for the results
401: */
402: public Sort getSort() {
403:
404: return m_sort;
405: }
406:
407: /**
408: * Returns the name of the sort option being used.<p>
409: * @return the name of the sort option being used
410: *
411: * @see #SORT_NAMES
412: * @see #setSortName(String)
413: */
414: public String getSortName() {
415:
416: if (m_sort == SORT_DATE_CREATED) {
417: return SORT_NAMES[1];
418: }
419: if (m_sort == SORT_DATE_LASTMODIFIED) {
420: return SORT_NAMES[2];
421: }
422: if (m_sort == SORT_TITLE) {
423: return SORT_NAMES[3];
424: }
425: return SORT_NAMES[0];
426: }
427:
428: /**
429: * Returns <code>true</code> if the category count is calculated for all search results.<p>
430: *
431: * @return <code>true</code> if the category count is calculated for all search results
432: */
433: public boolean isCalculateCategories() {
434:
435: return m_calculateCategories;
436: }
437:
438: /**
439: * Returns <code>true</code> if fields configured for the excerpt should be used for generating the excerpt only
440: * if they have been actually searched in.<p>
441: *
442: * The default setting is <code>false</code>, which means all text fields configured for the excerpt will
443: * be used to gernerate the excerpt, regardless if they have been searched in or not.<p>
444: *
445: * Please note: A field will only be included in the excerpt if it has been configured as <code>excerpt="true"</code>
446: * in <code>opencms-search.xml</code>. This method controls if so configured fields are used depending on the
447: * fields searched, see {@link #setFields(List)}.<p>
448: *
449: * @return <code>true</code> if fields configured for the excerpt should be used for generating the excerpt only
450: * if they have been actually searched in
451: */
452: public boolean isExcerptOnlySearchedFields() {
453:
454: return m_excerptOnlySearchedFields;
455: }
456:
457: /**
458: * Creates a merged parameter set from this parameters, restricted by the given other parameters.<p>
459: *
460: * This is mainly intended for "search in search result" functions.<p>
461: *
462: * The restricted query is build of the queries of both parameters, appended with AND.<p>
463: *
464: * The lists in the restriction for <code>{@link #getFields()}</code>, <code>{@link #getRoots()}</code> and
465: * <code>{@link #getCategories()}</code> are <b>intersected</b> with the lists of this search parameters. Only
466: * elements containd in both lists are included for the created search parameters.
467: * If a list in either the restriction or in this search parameters is <code>null</code>,
468: * the list from the other search parameters is used direclty.<p>
469: *
470: * The values for
471: * <code>{@link #isCalculateCategories()}</code>
472: * and <code>{@link #getSort()}</code> of this parameters are used for the restricted parameters.<p>
473: *
474: * @param restriction the parameters to restrict this parameters with
475: * @return the restricted parameters
476: */
477: public CmsSearchParameters restrict(CmsSearchParameters restriction) {
478:
479: // append queries
480: StringBuffer query = new StringBuffer(256);
481: if (getQuery() != null) {
482: // don't blow up unneccessary closures (if CmsSearch is reused and restricted several times)
483: boolean closure = !getQuery().startsWith("+(");
484: if (closure) {
485: query.append("+(");
486: }
487: query.append(getQuery());
488: if (closure) {
489: query.append(")");
490: }
491: }
492: if (restriction.getQuery() != null) {
493: // don't let lucene max terms be exceeded in case someone reuses a CmsSearch and continuously restricts
494: // query with the same restrictions...
495: if (query.indexOf(restriction.getQuery()) < 0) {
496: query.append(" +(");
497: query.append(restriction.getQuery());
498: query.append(")");
499: }
500: }
501:
502: // restrict fields
503: List fields = null;
504: if ((m_fields != null) && (m_fields.size() > 0)) {
505: if ((restriction.getFields() != null)
506: && (restriction.getFields().size() > 0)) {
507: fields = ListUtils.intersection(m_fields, restriction
508: .getFields());
509: } else {
510: fields = m_fields;
511: }
512: } else {
513: fields = restriction.getFields();
514: }
515:
516: // restrict roots
517: List roots = null;
518: if ((m_roots != null) && (m_roots.size() > 0)) {
519: if ((restriction.getRoots() != null)
520: && (restriction.getRoots().size() > 0)) {
521: roots = ListUtils.intersection(m_roots, restriction
522: .getRoots());
523: // TODO: This only works if there are equal paths in both parameter sets - for two distinct sets
524: // all root restrictions are dropped with an empty list.
525: } else {
526: roots = m_roots;
527: }
528: } else {
529: roots = restriction.getRoots();
530: }
531:
532: // restrict categories
533: List categories = null;
534: if ((m_categories != null) && (m_categories.size() > 0)) {
535: if ((restriction.getCategories() != null)
536: && (restriction.getCategories().size() > 0)) {
537: categories = ListUtils.intersection(m_categories,
538: restriction.getCategories());
539: } else {
540: categories = m_categories;
541: }
542: } else {
543: categories = restriction.getCategories();
544: }
545:
546: // create the new search parameters
547: CmsSearchParameters result = new CmsSearchParameters(query
548: .toString(), fields, roots, categories,
549: m_calculateCategories, m_sort);
550: result.setIndex(getIndex());
551: return result;
552: }
553:
554: /**
555: * Set wether category counts shall be calculated for the corresponding search results or not.<p>
556: *
557: * @param flag true if category counts shall be calculated for the corresponding search results or false if not
558: */
559: public void setCalculateCategories(boolean flag) {
560:
561: m_calculateCategories = flag;
562: }
563:
564: /**
565: * Set the list of categories (strings) to this parameters. <p>
566: *
567: * @param categories the list of categories (strings) of this parameters
568: */
569: public void setCategories(List categories) {
570:
571: m_categories = categories;
572: }
573:
574: /**
575: * Sets the maximum number of pages which should be shown.<p>
576: *
577: * Enter an odd value to achieve a nice, "symmetric" output.<p>
578: *
579: * @param value the maximum number of pages which should be shown
580: */
581: public void setDisplayPages(int value) {
582:
583: m_displayPages = value;
584: }
585:
586: /**
587: * Controls if the excerpt from a field is generated only for searched fields, or for all fields (the default).<p>
588: *
589: * @param excerptAllFields if <code>true</code>, the excerpt is generated only from the fields actually searched in
590: *
591: * @see #isExcerptOnlySearchedFields()
592: */
593: public void setExcerptOnlySearchedFields(boolean excerptAllFields) {
594:
595: m_excerptOnlySearchedFields = excerptAllFields;
596: }
597:
598: /**
599: * Sets the list of strings of names of fields to search in. <p>
600: *
601: * @param fields the list of strings of names of fields to search in to set
602: */
603: public void setFields(List fields) {
604:
605: m_fields = fields;
606: }
607:
608: /**
609: * Set the name of the index to search.<p>
610: *
611: *
612: * @param indexName the name of the index
613: */
614: public void setIndex(String indexName) {
615:
616: CmsSearchIndex index;
617: if (CmsStringUtil.isNotEmpty(indexName)) {
618: try {
619: index = OpenCms.getSearchManager().getIndex(indexName);
620: if (index == null) {
621: throw new CmsException(Messages.get().container(
622: Messages.ERR_INDEX_NOT_FOUND_1, indexName));
623: }
624: setSearchIndex(index);
625: } catch (Exception exc) {
626: if (LOG.isErrorEnabled()) {
627: LOG.error(Messages.get().getBundle().key(
628: Messages.LOG_INDEX_ACCESS_FAILED_1,
629: indexName), exc);
630: }
631: }
632: }
633: }
634:
635: /**
636: * Sets the number of matches per page.<p>
637: *
638: * @param matches the number of matches per page
639: */
640: public void setMatchesPerPage(int matches) {
641:
642: m_matchesPerPage = matches;
643: }
644:
645: /**
646: * Sets the creation date the resources have to have as maximum.<p>
647: *
648: * @param dateCreatedTo the creation date the resources have to have as maximum to set
649: */
650: public void setMaxDateCreated(long dateCreatedTo) {
651:
652: m_maxDateCreated = dateCreatedTo;
653: }
654:
655: /**
656: * Sets the last modification date the resources have to have as maximum.<p>
657: *
658: * @param dateLastModifiedTo the last modification date the resources have to have as maximum to set
659: */
660: public void setMaxDateLastModified(long dateLastModifiedTo) {
661:
662: m_maxDateLastModified = dateLastModifiedTo;
663: }
664:
665: /**
666: * Sets the creation date the resources have to have as minimum.<p>
667: *
668: * @param dateCreatedFrom the creation date the resources have to have as minimum to set
669: */
670: public void setMinDateCreated(long dateCreatedFrom) {
671:
672: m_minDateCreated = dateCreatedFrom;
673: }
674:
675: /**
676: * Sets the last modification date the resources have to have as minimum.<p>
677: *
678: * @param dateLastModifiedFrom the the last modification date the resources have to have as minimum to set
679: */
680: public void setMinDateLastModified(long dateLastModifiedFrom) {
681:
682: m_minDateLastModified = dateLastModifiedFrom;
683: }
684:
685: /**
686: * Sets the query to search for. <p>
687: *
688: * The decoding here is tailored for query strings that are
689: * additionally manually utf-8 encoded at client side (javascript) to get around an
690: * issue with special chars in applications that use non- utf-8 encoding
691: * (e.g. ISO-8859-1) OpenCms applications. It is not recommended to use this with
692: * frontends that don't encode manually as characters like sole "%" (without number suffix)
693: * will cause an Exception.<p>
694: *
695: * @param query the querye to search for to set
696: *
697: */
698: public void setQuery(String query) {
699:
700: // query = CmsEncoder.decode(query);
701:
702: // for widget use the exception is thrown here to enforce the errmsg next to widget
703: if (query.trim().length() < getQueryLength()) {
704: throw new CmsIllegalArgumentException(Messages.get()
705: .container(Messages.ERR_QUERY_TOO_SHORT_1,
706: new Integer(getQueryLength())));
707: }
708: m_query = query;
709: }
710:
711: /**
712: * Sets the minimum length of the search query.<p>
713: *
714: * @param length the minimum search query length
715: */
716: public void setQueryLength(int length) {
717:
718: m_queryLength = length;
719: }
720:
721: /**
722: * Sets the list of strings of roots to search under for the search.<p>
723: *
724: * @param roots the list of strings of roots to search under for the search to set
725: */
726: public void setRoots(List roots) {
727:
728: m_roots = roots;
729: }
730:
731: /**
732: * Set the comma separated search root names to restrict search to.<p>
733: *
734: * @param categories the comma separated category names to restrict search to
735: */
736: public void setSearchCategories(String categories) {
737:
738: setCategories(CmsStringUtil.splitAsList(categories, ','));
739: }
740:
741: /**
742: * Sets the search index to use for the search. <p>
743: *
744: * @param index the search index to use for the search to set.
745: *
746: * @throws CmsIllegalArgumentException if null is given as argument
747: */
748: public void setSearchIndex(CmsSearchIndex index)
749: throws CmsIllegalArgumentException {
750:
751: if (index == null) {
752: throw new CmsIllegalArgumentException(Messages.get()
753: .container(Messages.ERR_INDEX_NULL_0));
754: }
755: m_index = index;
756: }
757:
758: /**
759: * Set the search page to display. <p>
760: *
761: * @param page the search page to display
762: */
763: public void setSearchPage(int page) {
764:
765: m_page = page;
766: }
767:
768: /**
769: * Set the comma separated search root names to restrict search to.<p>
770: *
771: * @param rootNameList the comma separated search root names to restrict search to
772: */
773: public void setSearchRoots(String rootNameList) {
774:
775: m_roots = CmsStringUtil.splitAsList(rootNameList, ',');
776: }
777:
778: /**
779: * Set the instance that defines the sort order for search results.
780: *
781: * @param sortOrder the instance that defines the sort order for search results to set
782: */
783: public void setSort(Sort sortOrder) {
784:
785: m_sort = sortOrder;
786: }
787:
788: /**
789: * Sets the internal member of type <code>{@link Sort}</code> according to
790: * the given sort name. <p>
791: *
792: * For a list of valid sort names, please see <code>{@link #SORT_NAMES}</code>.<p>
793: *
794: * @param sortName the name of the sort to use
795: *
796: * @see #SORT_NAMES
797: */
798: public void setSortName(String sortName) {
799:
800: if (sortName.equals(SORT_NAMES[1])) {
801: m_sort = SORT_DATE_CREATED;
802: } else if (sortName.equals(SORT_NAMES[2])) {
803: m_sort = SORT_DATE_LASTMODIFIED;
804: } else if (sortName.equals(SORT_NAMES[3])) {
805: m_sort = SORT_TITLE;
806: } else {
807: m_sort = SORT_DEFAULT;
808: }
809: }
810:
811: /**
812: * Creates a query String build from this search parameters for HTML links.<p>
813: *
814: * @return a query String build from this search parameters for HTML links
815: */
816: public String toQueryString() {
817:
818: StringBuffer result = new StringBuffer(128);
819: result.append("?action=search&query=");
820: result.append(CmsEncoder.encodeParameter(getQuery()));
821:
822: result.append("&matchesPerPage=");
823: result.append(getMatchesPerPage());
824: result.append("&displayPages=");
825: result.append(getDisplayPages());
826: result.append("&index=");
827: result.append(CmsEncoder.encodeParameter(getIndex()));
828:
829: Sort sort = getSort();
830: if (sort != CmsSearchParameters.SORT_DEFAULT) {
831: result.append("&sort=");
832: if (sort == CmsSearchParameters.SORT_TITLE) {
833: result.append("title");
834: } else if (sort == CmsSearchParameters.SORT_DATE_CREATED) {
835: result.append("date-created");
836: } else if (sort == CmsSearchParameters.SORT_DATE_LASTMODIFIED) {
837: result.append("date-lastmodified");
838: }
839: }
840:
841: if ((getCategories() != null) && (getCategories().size() > 0)) {
842: result.append("&category=");
843: Iterator it = getCategories().iterator();
844: while (it.hasNext()) {
845: result.append(it.next());
846: if (it.hasNext()) {
847: result.append(',');
848: }
849: }
850: }
851:
852: if ((getRoots() != null) && (getRoots().size() > 0)) {
853: result.append("&searchRoots=");
854: Iterator it = getRoots().iterator();
855: while (it.hasNext()) {
856: result.append(CmsEncoder.encode((String) it.next()));
857: if (it.hasNext()) {
858: result.append(',');
859: }
860: }
861: }
862:
863: if (isExcerptOnlySearchedFields()) {
864: result.append("&excerptOnlySearchedFields=true");
865: }
866:
867: return result.toString();
868: }
869:
870: /**
871: * @see java.lang.Object#toString()
872: */
873: public String toString() {
874:
875: StringBuffer result = new StringBuffer();
876: result.append("query:[");
877: result.append(m_query);
878: result.append("] ");
879: if ((m_fields != null) && (m_fields.size() > 0)) {
880: result.append("fields:[");
881: for (int i = 0; i < m_fields.size(); i++) {
882: result.append(m_fields.get(i));
883: if (i + 1 < m_fields.size()) {
884: result.append(", ");
885: }
886: }
887: result.append("] ");
888: }
889: if ((m_roots != null) && (m_roots.size() > 0)) {
890: result.append("roots:[");
891: for (int i = 0; i < m_roots.size(); i++) {
892: result.append(m_roots.get(i));
893: if (i + 1 < m_roots.size()) {
894: result.append(", ");
895: }
896: }
897: result.append("] ");
898: }
899: if ((m_categories != null) && (m_categories.size() > 0)) {
900: result.append("categories:[");
901: for (int i = 0; i < m_categories.size(); i++) {
902: result.append(m_categories.get(i));
903: if (i + 1 < m_categories.size()) {
904: result.append(", ");
905: }
906: }
907: result.append("] ");
908: }
909: if (m_calculateCategories) {
910: result.append("calculate-categories ");
911: }
912: if (m_excerptOnlySearchedFields) {
913: result.append("excerpt-searched-fields-only ");
914: }
915: result.append("sort:[");
916: if (m_sort == CmsSearchParameters.SORT_DEFAULT) {
917: result.append("default");
918: } else if (m_sort == CmsSearchParameters.SORT_TITLE) {
919: result.append("title");
920: } else if (m_sort == CmsSearchParameters.SORT_DATE_CREATED) {
921: result.append("date-created");
922: } else if (m_sort == CmsSearchParameters.SORT_DATE_LASTMODIFIED) {
923: result.append("date-lastmodified");
924: } else {
925: result.append("unknown");
926: }
927: result.append("]");
928:
929: return result.toString();
930: }
931:
932: private String toSeparatedString(List stringList, char c) {
933:
934: StringBuffer result = new StringBuffer();
935: Iterator it = stringList.iterator();
936: while (it.hasNext()) {
937: result.append(it.next());
938: if (it.hasNext()) {
939: result.append(c);
940: }
941: }
942: return result.toString();
943: }
944: }
|