2011-06-13 23:44:03 +02:00
// QueryParams.java
2005-10-10 02:33:25 +02:00
// -----------------------
// part of YACY
2008-07-20 19:14:51 +02:00
// (C) by Michael Peter Christen; mc@yacy.net
2005-10-10 02:33:25 +02:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2005
// Created: 10.10.2005
//
2009-09-05 22:41:21 +02:00
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
//
2005-10-10 02:33:25 +02:00
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2011-09-25 18:59:06 +02:00
package net.yacy.search.query ;
2005-10-10 02:33:25 +02:00
2012-01-17 01:53:08 +01:00
import java.util.Collection ;
2010-06-23 13:19:32 +02:00
import java.util.HashMap ;
2006-09-30 00:27:20 +02:00
import java.util.Iterator ;
2013-06-28 12:39:36 +02:00
import java.util.LinkedHashSet ;
2010-06-23 13:19:32 +02:00
import java.util.Map ;
2011-12-13 00:16:05 +01:00
import java.util.Set ;
2013-11-25 15:20:54 +01:00
import java.util.SortedSet ;
2010-03-23 11:17:28 +01:00
import java.util.regex.Pattern ;
2011-03-23 01:48:19 +01:00
import java.util.regex.PatternSyntaxException ;
2014-07-18 12:43:01 +02:00
2012-11-21 18:46:49 +01:00
import net.yacy.cora.document.analysis.Classification ;
import net.yacy.cora.document.analysis.Classification.ContentDomain ;
2013-09-15 00:30:23 +02:00
import net.yacy.cora.document.encoding.ASCII ;
2014-07-18 12:43:01 +02:00
import net.yacy.cora.document.id.AnchorURL ;
2013-03-13 14:47:00 +01:00
import net.yacy.cora.federate.solr.Ranking ;
2012-09-25 21:20:03 +02:00
import net.yacy.cora.federate.yacy.CacheStrategy ;
2012-09-20 19:38:22 +02:00
import net.yacy.cora.geo.GeoLocation ;
2012-06-11 23:49:30 +02:00
import net.yacy.cora.lod.vocabulary.Tagging ;
2012-09-21 16:46:57 +02:00
import net.yacy.cora.order.Base64Order ;
2014-03-27 13:29:14 +01:00
import net.yacy.cora.protocol.RequestHeader ;
2012-07-27 12:13:53 +02:00
import net.yacy.cora.storage.HandleSet ;
2013-07-09 14:28:25 +02:00
import net.yacy.cora.util.ConcurrentLog ;
2012-07-27 12:13:53 +02:00
import net.yacy.cora.util.SpaceExceededException ;
2009-10-18 02:53:43 +02:00
import net.yacy.document.Condenser ;
2012-12-18 02:29:03 +01:00
import net.yacy.document.LibraryProvider ;
2009-10-11 02:12:19 +02:00
import net.yacy.kelondro.data.word.Word ;
2010-04-15 15:22:59 +02:00
import net.yacy.kelondro.data.word.WordReferenceRow ;
2012-07-27 12:13:53 +02:00
import net.yacy.kelondro.index.RowHandleSet ;
2012-09-21 16:46:57 +02:00
import net.yacy.kelondro.util.Bitfield ;
2009-10-10 03:14:19 +02:00
import net.yacy.kelondro.util.SetTools ;
2011-10-04 11:06:24 +02:00
import net.yacy.peers.Seed ;
2011-09-25 18:59:06 +02:00
import net.yacy.search.index.Segment ;
import net.yacy.search.ranking.RankingProfile ;
2013-02-21 13:23:55 +01:00
import net.yacy.search.schema.CollectionConfiguration ;
import net.yacy.search.schema.CollectionSchema ;
2014-07-18 12:43:01 +02:00
2014-06-27 23:05:06 +02:00
import org.apache.solr.client.solrj.SolrQuery ;
import org.apache.solr.client.solrj.SolrQuery.SortClause ;
import org.apache.solr.common.params.CommonParams ;
import org.apache.solr.common.params.FacetParams ;
2005-10-10 02:33:25 +02:00
2009-07-09 00:14:57 +02:00
public final class QueryParams {
2011-06-13 23:44:03 +02:00
2011-11-17 02:05:45 +01:00
public enum Searchdom {
LOCAL , CLUSTER , GLOBAL ;
2011-11-24 15:57:09 +01:00
@Override
public String toString ( ) {
if ( this = = LOCAL ) return " local " ;
else if ( this = = CLUSTER ) return " global " ; // yes thats right: global, not cluster because a cluster search is a global search
else if ( this = = GLOBAL ) return " global " ;
return " local " ;
}
2011-11-17 02:05:45 +01:00
}
2010-10-09 10:55:57 +02:00
2013-09-24 11:26:51 +02:00
private static final Map < String , CollectionSchema > defaultfacetfields = new HashMap < String , CollectionSchema > ( ) ;
static {
// the key shall match with configuration property search.navigation
defaultfacetfields . put ( " location " , CollectionSchema . coordinate_p ) ;
defaultfacetfields . put ( " hosts " , CollectionSchema . host_s ) ;
defaultfacetfields . put ( " protocol " , CollectionSchema . url_protocol_s ) ;
defaultfacetfields . put ( " filetype " , CollectionSchema . url_file_ext_s ) ;
defaultfacetfields . put ( " authors " , CollectionSchema . author_sxt ) ;
2014-06-15 12:11:23 +02:00
defaultfacetfields . put ( " collections " , CollectionSchema . collection_sxt ) ;
2014-01-24 03:11:25 +01:00
defaultfacetfields . put ( " language " , CollectionSchema . language_s ) ;
2013-09-24 11:26:51 +02:00
//missing: namespace
}
2012-11-06 14:32:08 +01:00
private static final int defaultmaxfacets = 30 ;
2009-01-30 16:33:00 +01:00
public static final Bitfield empty_constraint = new Bitfield ( 4 , " AAAAAA " ) ;
2010-03-23 14:41:41 +01:00
public static final Pattern catchall_pattern = Pattern . compile ( " .* " ) ;
2012-11-01 10:22:22 +01:00
private static final Pattern matchnothing_pattern = Pattern . compile ( " " ) ;
2011-06-13 23:44:03 +02:00
2012-12-18 02:29:03 +01:00
private final QueryGoal queryGoal ;
2012-11-05 03:19:28 +01:00
public int itemsPerPage ;
2010-03-23 14:41:41 +01:00
public int offset ;
2012-12-26 21:25:27 +01:00
public Pattern urlMask ;
public final Pattern prefer ;
2013-02-12 03:42:46 +01:00
public final String tld , inlink ;
2012-12-26 21:25:27 +01:00
boolean urlMask_isCatchall ;
2012-04-22 00:04:36 +02:00
public final Classification . ContentDomain contentdom ;
2010-03-23 14:41:41 +01:00
public final String targetlang ;
2012-11-01 10:22:22 +01:00
protected final Collection < Tagging . Metatag > metatags ;
2011-11-17 02:05:45 +01:00
public final Searchdom domType ;
2012-11-01 10:22:22 +01:00
private final int zonecode ;
2010-03-23 14:41:41 +01:00
public final int maxDistance ;
public final Bitfield constraint ;
2013-02-26 17:16:31 +01:00
public final boolean allofconstraint ;
2012-11-01 10:22:22 +01:00
protected CacheStrategy snippetCacheStrategy ;
2010-03-23 14:41:41 +01:00
public final RankingProfile ranking ;
2010-01-11 00:09:48 +01:00
private final Segment indexSegment ;
2012-11-06 14:32:08 +01:00
public final String clienthost ; // this is the client host that starts the query, not a site operator
2012-11-01 10:22:22 +01:00
protected final Set < String > siteexcludes ; // set of domain hashes that are excluded if not included by sitehash
2013-02-12 03:42:46 +01:00
public final QueryModifier modifier ;
2011-10-04 11:06:24 +02:00
public Seed remotepeer ;
2012-11-01 10:22:22 +01:00
public final long starttime ; // the time when the query started, how long it should take and the time when the timeout is reached (milliseconds)
protected final long maxtime ;
2012-12-18 02:29:03 +01:00
private final long timeout ;
2008-02-18 00:35:48 +01:00
// values that are set after a search:
2011-01-11 23:58:14 +01:00
public int transmitcount ; // number of results that had been shown to the user
2008-02-18 00:35:48 +01:00
public long searchtime , urlretrievaltime , snippetcomputationtime ; // time to perform the search, to get all the urls, and to compute the snippets
2010-10-18 10:09:59 +02:00
public final String userAgent ;
2012-12-29 17:47:34 +01:00
protected boolean filterfailurls , filterscannerfail ;
2012-11-01 10:22:22 +01:00
protected double lat , lon , radius ;
2013-06-28 12:39:36 +02:00
public LinkedHashSet < String > facetfields ;
2012-11-06 14:32:08 +01:00
public int maxfacets ;
2013-02-02 07:21:18 +01:00
private SolrQuery cachedQuery ;
2013-02-21 13:23:55 +01:00
private CollectionConfiguration solrSchema ;
2011-06-13 23:44:03 +02:00
2009-07-09 00:14:57 +02:00
public QueryParams (
2012-11-18 01:22:41 +01:00
final QueryGoal queryGoal ,
2013-02-12 03:42:46 +01:00
final QueryModifier modifier ,
final int maxDistance ,
final String prefer ,
final ContentDomain contentdom ,
2008-09-21 02:04:42 +02:00
final String language ,
2012-06-11 23:49:30 +02:00
final Collection < Tagging . Metatag > metatags ,
2011-06-13 23:44:03 +02:00
final CacheStrategy snippetCacheStrategy ,
2013-02-12 03:42:46 +01:00
final int itemsPerPage ,
final int offset ,
final String urlMask ,
final String tld ,
final String inlink ,
final Searchdom domType ,
final Bitfield constraint ,
final boolean allofconstraint ,
2011-12-13 00:16:05 +01:00
final Set < String > siteexcludes ,
2008-08-02 14:12:04 +02:00
final int domainzone ,
final String host ,
2009-11-24 12:13:11 +01:00
final boolean specialRights ,
final Segment indexSegment ,
2010-10-18 10:09:59 +02:00
final RankingProfile ranking ,
2011-01-22 10:46:00 +01:00
final String userAgent ,
2012-05-31 22:39:53 +02:00
final boolean filterfailurls ,
2012-12-29 17:47:34 +01:00
final boolean filterscannerfail ,
2013-02-12 03:42:46 +01:00
final double lat ,
final double lon ,
2013-09-24 11:26:51 +02:00
final double radius ,
final String [ ] search_navigation
2013-02-12 03:42:46 +01:00
) {
2012-11-18 01:22:41 +01:00
this . queryGoal = queryGoal ;
2013-02-12 03:42:46 +01:00
this . modifier = modifier ;
2010-07-18 11:10:46 +02:00
this . ranking = ranking ;
this . maxDistance = maxDistance ;
this . contentdom = contentdom ;
2011-08-11 23:37:35 +02:00
this . itemsPerPage = Math . min ( ( specialRights ) ? 10000 : 1000 , itemsPerPage ) ;
this . offset = Math . max ( 0 , Math . min ( ( specialRights ) ? 10000 - this . itemsPerPage : 1000 - this . itemsPerPage , offset ) ) ;
2011-03-23 01:48:19 +01:00
try {
this . urlMask = Pattern . compile ( urlMask . toLowerCase ( ) ) ;
} catch ( final PatternSyntaxException ex ) {
throw new IllegalArgumentException ( " Not a valid regular expression: " + urlMask , ex ) ;
}
2010-03-23 14:41:41 +01:00
this . urlMask_isCatchall = this . urlMask . toString ( ) . equals ( catchall_pattern . toString ( ) ) ;
2012-12-26 21:25:27 +01:00
if ( this . urlMask_isCatchall ) {
2013-12-04 13:48:01 +01:00
String protocolfilter = modifier . protocol = = null ? " .* " : modifier . protocol ;
String defaulthostprefix = modifier . protocol = = null ? " www " : modifier . protocol ;
String hostfilter = modifier . sitehost = = null & & tld = = null ? " .* " : modifier . sitehost = = null ? " .* \\ . " + tld : modifier . sitehost . startsWith ( defaulthostprefix + " . " ) ? " ( " + defaulthostprefix + " \\ .)? " + modifier . sitehost . substring ( 4 ) : " ( " + defaulthostprefix + " \\ .)? " + modifier . sitehost ;
String filefilter = modifier . filetype = = null ? " .* " : " .* " + modifier . filetype + " .* " ;
String filter = protocolfilter + " :// " + hostfilter + " / " + filefilter ;
if ( ! filter . equals ( " .*://.*/.* " ) ) {
this . urlMask = Pattern . compile ( filter ) ;
2012-12-26 21:25:27 +01:00
this . urlMask_isCatchall = false ;
}
}
2012-12-19 12:45:40 +01:00
this . tld = tld ;
2013-01-14 12:50:21 +01:00
this . inlink = inlink ;
2011-03-23 01:48:19 +01:00
try {
this . prefer = Pattern . compile ( prefer ) ;
} catch ( final PatternSyntaxException ex ) {
throw new IllegalArgumentException ( " Not a valid regular expression: " + prefer , ex ) ;
}
2012-11-05 03:19:28 +01:00
this . prefer . toString ( ) . equals ( matchnothing_pattern . toString ( ) ) ;
2010-07-18 11:10:46 +02:00
assert language ! = null ;
2008-09-21 02:04:42 +02:00
this . targetlang = language ;
2012-01-17 01:53:08 +01:00
this . metatags = metatags ;
2008-09-21 02:04:42 +02:00
this . domType = domType ;
2008-03-11 12:09:38 +01:00
this . zonecode = domainzone ;
2010-07-18 11:10:46 +02:00
this . constraint = constraint ;
this . allofconstraint = allofconstraint ;
2012-07-10 22:59:03 +02:00
this . siteexcludes = siteexcludes ! = null & & siteexcludes . isEmpty ( ) ? null : siteexcludes ;
2013-09-02 18:55:38 +02:00
this . snippetCacheStrategy = contentdom = = ContentDomain . TEXT ? snippetCacheStrategy : contentdom = = null ? null : CacheStrategy . CACHEONLY ;
2012-11-06 14:32:08 +01:00
this . clienthost = host ;
2008-02-18 00:35:48 +01:00
this . remotepeer = null ;
2012-06-04 15:37:39 +02:00
this . starttime = Long . valueOf ( System . currentTimeMillis ( ) ) ;
this . maxtime = 10000 ;
this . timeout = this . starttime + this . timeout ;
2009-11-24 12:13:11 +01:00
this . indexSegment = indexSegment ;
2010-10-18 10:09:59 +02:00
this . userAgent = userAgent ;
2011-01-11 23:58:14 +01:00
this . transmitcount = 0 ;
2011-01-22 10:46:00 +01:00
this . filterfailurls = filterfailurls ;
2012-12-29 17:47:34 +01:00
this . filterscannerfail = filterscannerfail ;
2012-05-31 22:39:53 +02:00
// we normalize here the location and radius because that should cause a better caching
// and as surplus it will increase privacy
this . lat = Math . floor ( lat * this . kmNormal ) / this . kmNormal ;
this . lon = Math . floor ( lon * this . kmNormal ) / this . kmNormal ;
this . radius = Math . floor ( radius * this . kmNormal + 1 ) / this . kmNormal ;
2013-06-28 12:39:36 +02:00
this . facetfields = new LinkedHashSet < String > ( ) ;
2013-02-04 16:42:10 +01:00
2013-02-21 13:23:55 +01:00
this . solrSchema = indexSegment . fulltext ( ) . getDefaultConfiguration ( ) ;
2013-09-24 11:26:51 +02:00
for ( String navkey : search_navigation ) {
CollectionSchema f = defaultfacetfields . get ( navkey ) ;
2014-06-27 23:05:06 +02:00
// handle special field, authors_sxt (add to facet w/o contains check, as authors_sxt is not enabled (is copyfield))
if ( f ! = null & & ( solrSchema . contains ( f ) | | f . name ( ) . equals ( " author_sxt " ) ) ) this . facetfields . add ( f . getSolrFieldName ( ) ) ;
2013-02-04 16:42:10 +01:00
}
2013-02-21 13:23:55 +01:00
for ( Tagging v : LibraryProvider . autotagging . getVocabularies ( ) ) this . facetfields . add ( CollectionSchema . VOCABULARY_PREFIX + v . getName ( ) + CollectionSchema . VOCABULARY_SUFFIX ) ;
2012-11-06 14:32:08 +01:00
this . maxfacets = defaultmaxfacets ;
2013-02-02 07:21:18 +01:00
this . cachedQuery = null ;
2009-11-24 12:13:11 +01:00
}
2011-06-13 23:44:03 +02:00
2012-11-01 10:22:22 +01:00
private double kmNormal = 100 . d ; // 100 =ca 40000.d / 360.d == 111.11 - if lat/lon is multiplied with this, rounded and diveded by this, the location is normalized to a 1km grid
2012-05-31 22:39:53 +02:00
2009-11-24 12:13:11 +01:00
public Segment getSegment ( ) {
return this . indexSegment ;
2005-10-10 02:33:25 +02:00
}
2011-06-13 23:44:03 +02:00
2007-09-04 01:43:55 +02:00
public int neededResults ( ) {
// the number of result lines that must be computed
2009-08-30 12:28:23 +02:00
return this . offset + this . itemsPerPage ;
2007-09-04 01:43:55 +02:00
}
2011-06-13 23:44:03 +02:00
2012-05-21 01:58:29 +02:00
public int itemsPerPage ( ) {
2007-09-08 13:50:19 +02:00
// the number of result lines that are displayed at once (size of result page)
2009-08-30 12:28:23 +02:00
return this . itemsPerPage ;
2007-09-04 01:43:55 +02:00
}
2012-11-05 03:19:28 +01:00
2008-08-02 14:12:04 +02:00
public void setOffset ( final int newOffset ) {
2007-09-04 01:43:55 +02:00
this . offset = newOffset ;
2005-10-10 02:33:25 +02:00
}
2011-06-13 23:44:03 +02:00
2008-04-24 10:42:08 +02:00
public boolean isLocal ( ) {
2011-11-17 02:05:45 +01:00
return this . domType = = Searchdom . LOCAL ;
2007-09-04 01:43:55 +02:00
}
2011-06-13 23:44:03 +02:00
2010-04-15 15:22:59 +02:00
public static HandleSet hashes2Set ( final String query ) {
2012-07-27 12:13:53 +02:00
final HandleSet keyhashes = new RowHandleSet ( WordReferenceRow . urlEntryRow . primaryKeyLength , WordReferenceRow . urlEntryRow . objectOrder , 0 ) ;
2010-07-18 11:10:46 +02:00
if ( query ! = null ) {
for ( int i = 0 ; i < ( query . length ( ) / Word . commonHashLength ) ; i + + ) try {
2011-05-27 10:24:54 +02:00
keyhashes . put ( ASCII . getBytes ( query . substring ( i * Word . commonHashLength , ( i + 1 ) * Word . commonHashLength ) ) ) ;
2012-07-27 12:13:53 +02:00
} catch ( final SpaceExceededException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . logException ( e ) ;
2010-07-18 11:10:46 +02:00
}
2009-04-16 17:29:00 +02:00
}
return keyhashes ;
2010-04-15 15:22:59 +02:00
}
2011-06-13 23:44:03 +02:00
2010-04-15 15:22:59 +02:00
public static String hashSet2hashString ( final HandleSet hashes ) {
final byte [ ] bb = new byte [ hashes . size ( ) * Word . commonHashLength ] ;
int p = 0 ;
2010-07-18 11:10:46 +02:00
for ( final byte [ ] b : hashes ) {
2011-05-27 10:24:54 +02:00
assert b . length = = Word . commonHashLength : " hash = " + ASCII . String ( b ) ;
2010-04-15 15:22:59 +02:00
System . arraycopy ( b , 0 , bb , p , Word . commonHashLength ) ;
p + = Word . commonHashLength ;
2009-06-02 00:45:28 +02:00
}
2011-05-27 10:24:54 +02:00
return ASCII . String ( bb ) ;
2006-09-13 19:13:28 +02:00
}
2007-12-12 19:57:43 +01:00
2012-08-19 13:17:03 +02:00
public static String hashSet2hashString ( final Set < String > hashes ) {
final byte [ ] bb = new byte [ hashes . size ( ) * Word . commonHashLength ] ;
int p = 0 ;
for ( final String s : hashes ) {
assert s . length ( ) = = Word . commonHashLength : " hash = " + s ;
System . arraycopy ( ASCII . getBytes ( s ) , 0 , bb , p , Word . commonHashLength ) ;
p + = Word . commonHashLength ;
}
return ASCII . String ( bb ) ;
}
2010-04-15 15:22:59 +02:00
public static String anonymizedQueryHashes ( final HandleSet hashes ) {
2008-08-28 23:15:59 +02:00
// create a more anonymized representation of a query hashes for logging
2009-04-16 17:29:00 +02:00
final Iterator < byte [ ] > i = hashes . iterator ( ) ;
2009-10-11 02:12:19 +02:00
final StringBuilder sb = new StringBuilder ( hashes . size ( ) * ( Word . commonHashLength + 2 ) + 2 ) ;
2007-12-12 19:57:43 +01:00
sb . append ( " [ " ) ;
2009-04-16 17:29:00 +02:00
byte [ ] hash ;
2007-12-12 19:57:43 +01:00
if ( i . hasNext ( ) ) {
2008-01-08 21:12:31 +01:00
hash = i . next ( ) ;
2011-05-27 10:24:54 +02:00
sb . append ( ASCII . String ( hash ) . substring ( 0 , 3 ) ) . append ( " ......... " ) ;
2007-12-12 19:57:43 +01:00
}
while ( i . hasNext ( ) ) {
2008-01-08 21:12:31 +01:00
hash = i . next ( ) ;
2011-05-27 10:24:54 +02:00
sb . append ( " , " ) . append ( ASCII . String ( hash ) . substring ( 0 , 3 ) ) . append ( " ......... " ) ;
2007-12-12 19:57:43 +01:00
}
sb . append ( " ] " ) ;
2011-03-07 21:36:40 +01:00
return sb . toString ( ) ;
2007-12-12 19:57:43 +01:00
}
2011-06-13 23:44:03 +02:00
2010-06-22 14:28:53 +02:00
/ * *
* check if the given text matches with the query
* this checks inclusion and exclusion words
* @param text
* @return true if the query matches with the given text
* /
2012-11-01 10:22:22 +01:00
private final boolean matchesText ( final String text ) {
2010-07-18 11:10:46 +02:00
boolean ret = false ;
2013-11-25 15:20:54 +01:00
QueryGoal . NormalizedWords words = new QueryGoal . NormalizedWords ( Condenser . getWords ( text , null ) . keySet ( ) ) ;
2013-11-26 02:24:47 +01:00
if ( ! SetTools . anymatchByTest ( this . queryGoal . getExcludeWords ( ) , words ) ) {
2013-11-25 15:20:54 +01:00
ret = SetTools . totalInclusion ( this . queryGoal . getIncludeWords ( ) , words ) ;
2010-07-18 11:10:46 +02:00
}
return ret ;
2010-06-22 14:28:53 +02:00
}
2013-11-25 15:20:54 +01:00
2013-11-26 02:24:47 +01:00
protected static final boolean anymatch ( final String text , final Iterator < String > keywords ) {
if ( keywords = = null | | ! keywords . hasNext ( ) ) return false ;
2013-11-25 15:20:54 +01:00
final SortedSet < String > textwords = ( SortedSet < String > ) Condenser . getWords ( text , null ) . keySet ( ) ;
2013-11-26 02:24:47 +01:00
return SetTools . anymatchByTest ( keywords , textwords ) ;
2007-04-05 12:14:48 +02:00
}
2011-06-13 23:44:03 +02:00
2013-09-03 11:14:23 +02:00
public SolrQuery solrQuery ( final ContentDomain cd , final boolean getFacets , final boolean excludeintext_image ) {
2013-09-02 18:55:38 +02:00
if ( cd = = ContentDomain . IMAGE ) return solrImageQuery ( getFacets ) ;
2013-09-03 11:14:23 +02:00
return solrTextQuery ( getFacets , excludeintext_image ) ;
2013-09-02 18:55:38 +02:00
}
2013-09-03 11:14:23 +02:00
private SolrQuery solrTextQuery ( final boolean getFacets , final boolean excludeintext_image ) {
2013-02-02 07:21:18 +01:00
if ( this . cachedQuery ! = null ) {
this . cachedQuery . setStart ( this . offset ) ;
2013-09-03 12:22:29 +02:00
if ( ! getFacets ) this . cachedQuery . setFacet ( false ) ;
2013-02-02 07:21:18 +01:00
return this . cachedQuery ;
}
2013-09-02 18:55:38 +02:00
2012-12-19 01:00:57 +01:00
// construct query
2013-09-02 18:55:38 +02:00
final SolrQuery params = getBasicParams ( getFacets ) ;
2013-04-16 14:45:14 +02:00
int rankingProfile = this . ranking . coeff_date = = RankingProfile . COEFF_MAX ? 1 : ( this . modifier . sitehash ! = null | | this . modifier . sitehost ! = null ) ? 2 : 0 ;
2013-09-03 11:14:23 +02:00
params . setQuery ( this . queryGoal . collectionTextQueryString ( this . indexSegment . fulltext ( ) . getDefaultConfiguration ( ) , rankingProfile , excludeintext_image ) . toString ( ) ) ;
2013-04-16 14:45:14 +02:00
Ranking ranking = indexSegment . fulltext ( ) . getDefaultConfiguration ( ) . getRanking ( rankingProfile ) ; // for a by-date ranking select different ranking profile
2014-06-15 12:38:30 +02:00
String fq = ranking . getFilterQuery ( ) ;
2013-03-13 14:47:00 +01:00
String bq = ranking . getBoostQuery ( ) ;
String bf = ranking . getBoostFunction ( ) ;
2014-01-30 10:51:08 +01:00
if ( this . queryGoal . getIncludeSize ( ) > 1 ) {
// add boost on combined words
if ( bq . length ( ) > 0 ) bq + = " " ;
bq + = CollectionSchema . text_t . getSolrFieldName ( ) + " : \" " + this . queryGoal . getIncludeString ( ) + " \" ^10 " ;
}
2014-06-15 12:38:30 +02:00
if ( fq . length ( ) > 0 ) {
2014-06-27 23:05:06 +02:00
String oldfq = params . get ( CommonParams . FQ ) ;
params . setParam ( CommonParams . FQ , oldfq = = null | | oldfq . length ( ) = = 0 ? fq : " ( " + oldfq + " ) AND ( " + fq + " ) " ) ;
2014-06-15 12:38:30 +02:00
}
2013-04-16 14:45:14 +02:00
if ( bq . length ( ) > 0 ) params . setParam ( " bq " , bq ) ;
if ( bf . length ( ) > 0 ) params . setParam ( " boost " , bf ) ; // a boost function extension, see http://wiki.apache.org/solr/ExtendedDisMax#bf_.28Boost_Function.2C_additive.29
2013-09-02 18:55:38 +02:00
// prepare result
ConcurrentLog . info ( " Protocol " , " SOLR QUERY: " + params . toString ( ) ) ;
this . cachedQuery = params ;
return params ;
}
private SolrQuery solrImageQuery ( boolean getFacets ) {
if ( this . cachedQuery ! = null ) {
this . cachedQuery . setStart ( this . offset ) ;
2013-09-03 12:22:29 +02:00
if ( ! getFacets ) this . cachedQuery . setFacet ( false ) ;
2013-09-02 18:55:38 +02:00
return this . cachedQuery ;
}
// construct query
final SolrQuery params = getBasicParams ( getFacets ) ;
params . setQuery ( this . queryGoal . collectionImageQueryString ( ) . toString ( ) ) ;
// set boosts
StringBuilder bq = new StringBuilder ( ) ;
bq . append ( CollectionSchema . url_file_ext_s . getSolrFieldName ( ) ) . append ( " : \" jpg \" " ) ;
bq . append ( " OR " ) . append ( CollectionSchema . url_file_ext_s . getSolrFieldName ( ) ) . append ( " : \" tif \" " ) ;
bq . append ( " OR " ) . append ( CollectionSchema . url_file_ext_s . getSolrFieldName ( ) ) . append ( " : \" tiff \" " ) ;
bq . append ( " OR " ) . append ( CollectionSchema . url_file_ext_s . getSolrFieldName ( ) ) . append ( " : \" png \" " ) ;
params . setParam ( " bq " , bq . toString ( ) ) ;
// prepare result
ConcurrentLog . info ( " Protocol " , " SOLR QUERY: " + params . toString ( ) ) ;
this . cachedQuery = params ;
return params ;
}
private SolrQuery getBasicParams ( boolean getFacets ) {
final SolrQuery params = new SolrQuery ( ) ;
params . setParam ( " defType " , " edismax " ) ;
2014-07-25 18:53:13 +02:00
params . setParam ( " qf " , CollectionSchema . text_t . getSolrFieldName ( ) + " ^1.0 " ) ;
2012-12-19 01:56:33 +01:00
params . setStart ( this . offset ) ;
params . setRows ( this . itemsPerPage ) ;
params . setFacet ( false ) ;
2013-09-02 18:55:38 +02:00
if ( this . ranking . coeff_date = = RankingProfile . COEFF_MAX ) {
// set a most-recent ordering
params . setSort ( new SortClause ( CollectionSchema . last_modified . getSolrFieldName ( ) , SolrQuery . ORDER . desc ) ) ;
//params.setSortField(CollectionSchema.last_modified.getSolrFieldName(), ORDER.desc); // deprecated in Solr 4.2
}
// add site facets
final String fq = getFacets ( ) ;
if ( fq . length ( ) > 0 ) {
params . setFilterQueries ( fq ) ;
}
// set facet query attributes
if ( getFacets & & this . facetfields . size ( ) > 0 ) {
params . setFacet ( true ) ;
2013-11-15 15:41:41 +01:00
params . setFacetMinCount ( 1 ) ;
2013-09-02 18:55:38 +02:00
params . setFacetLimit ( this . maxfacets ) ;
params . setFacetSort ( FacetParams . FACET_SORT_COUNT ) ;
params . setParam ( FacetParams . FACET_METHOD , FacetParams . FACET_METHOD_fcs ) ;
2014-03-27 13:29:14 +01:00
for ( String field : this . facetfields ) params . addFacetField ( " {!ex= " + field + " } " + field ) ;
2013-09-02 18:55:38 +02:00
} else {
params . setFacet ( false ) ;
}
params . setFields ( " * " , " score " ) ; // we need the score for post-ranking
return params ;
}
private String getFacets ( ) {
2012-12-19 01:00:57 +01:00
2012-12-19 01:56:33 +01:00
// add site facets
2012-12-19 01:00:57 +01:00
final StringBuilder fq = new StringBuilder ( ) ;
2013-02-12 03:42:46 +01:00
if ( this . modifier . sitehash = = null & & this . modifier . sitehost = = null ) {
2012-08-27 14:41:33 +02:00
if ( this . siteexcludes ! = null ) {
for ( String ex : this . siteexcludes ) {
2013-02-21 13:23:55 +01:00
fq . append ( " AND - " ) . append ( CollectionSchema . host_id_s . getSolrFieldName ( ) ) . append ( ':' ) . append ( ex ) ;
2012-08-27 14:41:33 +02:00
}
}
} else {
2013-02-12 03:42:46 +01:00
if ( this . modifier . sitehost ! = null ) {
2013-01-16 14:54:35 +01:00
// consider to search for hosts with 'www'-prefix, if not already part of the host name
2013-02-12 03:42:46 +01:00
if ( this . modifier . sitehost . startsWith ( " www. " ) ) {
2013-02-21 13:23:55 +01:00
fq . append ( " AND ( " ) . append ( CollectionSchema . host_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . sitehost . substring ( 4 ) ) . append ( '\"' ) ;
fq . append ( " OR " ) . append ( CollectionSchema . host_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . sitehost ) . append ( " \" ) " ) ;
2013-01-16 14:54:35 +01:00
} else {
2013-02-21 13:23:55 +01:00
fq . append ( " AND ( " ) . append ( CollectionSchema . host_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . sitehost ) . append ( '\"' ) ;
fq . append ( " OR " ) . append ( CollectionSchema . host_s . getSolrFieldName ( ) ) . append ( " : \" www. " ) . append ( this . modifier . sitehost ) . append ( " \" ) " ) ;
2013-01-16 14:54:35 +01:00
}
} else
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( CollectionSchema . host_id_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . sitehash ) . append ( '\"' ) ;
2012-08-27 14:41:33 +02:00
}
2012-11-07 13:53:29 +01:00
2012-12-18 02:29:03 +01:00
// add vocabulary facets
2013-12-29 08:05:37 +01:00
if ( this . metatags ! = null ) {
for ( Tagging . Metatag tag : this . metatags ) {
fq . append ( " AND " ) . append ( CollectionSchema . VOCABULARY_PREFIX ) . append ( tag . getVocabularyName ( ) ) . append ( CollectionSchema . VOCABULARY_SUFFIX ) . append ( " : \" " ) . append ( tag . getObject ( ) ) . append ( '\"' ) ;
}
2012-12-18 02:29:03 +01:00
}
2014-01-24 03:11:25 +01:00
// add language facet
if ( this . modifier . language ! = null & & this . modifier . language . length ( ) > 0 & & this . solrSchema . contains ( ( CollectionSchema . language_s ) ) ) {
fq . append ( " AND " ) . append ( CollectionSchema . language_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . language ) . append ( '\"' ) ;
}
2014-06-27 23:05:06 +02:00
// add author facets (check for contains(author) as author_sxt is omitted copyfield)
if ( this . modifier . author ! = null & & this . modifier . author . length ( ) > 0 & & this . solrSchema . contains ( CollectionSchema . author ) ) {
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( CollectionSchema . author_sxt . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . author ) . append ( '\"' ) ;
2012-12-19 01:56:33 +01:00
}
2014-06-15 12:11:23 +02:00
// add collection facets
if ( this . modifier . collection ! = null & & this . modifier . collection . length ( ) > 0 & & this . solrSchema . contains ( CollectionSchema . collection_sxt ) ) {
fq . append ( " AND " ) . append ( QueryModifier . parseCollectionExpression ( this . modifier . collection ) ) ;
}
2012-10-07 07:46:55 +02:00
2013-02-12 03:42:46 +01:00
if ( this . modifier . protocol ! = null ) {
2014-03-27 13:29:14 +01:00
fq . append ( " AND {!tag= " ) . append ( CollectionSchema . url_protocol_s . getSolrFieldName ( ) ) . append ( " } " ) . append ( CollectionSchema . url_protocol_s . getSolrFieldName ( ) ) . append ( ':' ) . append ( this . modifier . protocol ) ;
2012-12-19 12:45:40 +01:00
}
if ( this . tld ! = null ) {
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( CollectionSchema . host_dnc_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . tld ) . append ( '\"' ) ;
2012-12-19 12:45:40 +01:00
}
2013-02-12 03:42:46 +01:00
if ( this . modifier . filetype ! = null ) {
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( CollectionSchema . url_file_ext_s . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . modifier . filetype ) . append ( '\"' ) ;
2012-12-19 12:45:40 +01:00
}
2013-01-14 12:50:21 +01:00
if ( this . inlink ! = null ) {
2013-09-01 14:35:36 +02:00
fq . append ( " AND " ) . append ( CollectionSchema . outboundlinks_urlstub_sxt . getSolrFieldName ( ) ) . append ( " : \" " ) . append ( this . inlink ) . append ( '\"' ) ;
2013-01-14 12:50:21 +01:00
}
2012-11-13 11:45:56 +01:00
if ( ! this . urlMask_isCatchall ) {
2012-12-19 12:45:40 +01:00
// add a filter query on urls
2012-11-13 11:45:56 +01:00
String urlMaskPattern = this . urlMask . pattern ( ) ;
2012-12-19 01:00:57 +01:00
// solr doesn't like slashes, backslashes or doublepoints; remove them // urlmask = ".*\\." + ft + "(\\?.*)?";
2012-11-13 11:45:56 +01:00
int p ;
while ( ( p = urlMaskPattern . indexOf ( ':' ) ) > = 0 ) urlMaskPattern = urlMaskPattern . substring ( 0 , p ) + " . " + urlMaskPattern . substring ( p + 1 ) ;
while ( ( p = urlMaskPattern . indexOf ( '/' ) ) > = 0 ) urlMaskPattern = urlMaskPattern . substring ( 0 , p ) + " . " + urlMaskPattern . substring ( p + 1 ) ;
2012-12-19 01:00:57 +01:00
while ( ( p = urlMaskPattern . indexOf ( '\\' ) ) > = 0 ) urlMaskPattern = urlMaskPattern . substring ( 0 , p ) + " . " + urlMaskPattern . substring ( p + 2 ) ;
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( CollectionSchema . sku . getSolrFieldName ( ) + " :/ " + urlMaskPattern + " / " ) ;
2012-11-13 11:45:56 +01:00
}
2012-08-27 14:41:33 +02:00
if ( this . radius > 0 . 0d & & this . lat ! = 0 . 0d & & this . lon ! = 0 . 0d ) {
2012-08-27 15:25:25 +02:00
// localtion search, no special ranking
2012-10-07 07:46:55 +02:00
// try http://localhost:8090/solr/select?q=*:*&fq={!bbox sfield=coordinate_p pt=50.17,8.65 d=1}
//params.setQuery("!bbox " + q.toString());
//params.set("sfield", YaCySchema.coordinate_p.name());
//params.set("pt", Double.toString(this.lat) + "," + Double.toString(this.lon));
//params.set("d", GeoLocation.degreeToKm(this.radius));
2013-02-21 13:23:55 +01:00
fq . append ( " AND " ) . append ( " {!bbox sfield= " + CollectionSchema . coordinate_p . getSolrFieldName ( ) + " pt= " + Double . toString ( this . lat ) + " , " + Double . toString ( this . lon ) + " d= " + GeoLocation . degreeToKm ( this . radius ) + " } " ) ;
2012-10-07 07:46:55 +02:00
//params.setRows(Integer.MAX_VALUE);
2012-08-27 14:41:33 +02:00
}
2013-04-23 20:42:54 +02:00
2013-09-02 18:55:38 +02:00
return fq . length ( ) > 0 ? fq . substring ( 5 ) : fq . toString ( ) ;
2005-12-06 17:15:21 +01:00
}
2013-09-02 18:55:38 +02:00
2012-11-18 01:22:41 +01:00
public QueryGoal getQueryGoal ( ) {
return this . queryGoal ;
2012-10-02 14:29:45 +02:00
}
2014-07-18 12:43:01 +02:00
public final Map < AnchorURL , String > separateMatches ( final Map < AnchorURL , String > links ) {
final Map < AnchorURL , String > matcher = new HashMap < > ( ) ;
final Iterator < Map . Entry < AnchorURL , String > > i = links . entrySet ( ) . iterator ( ) ;
Map . Entry < AnchorURL , String > entry ;
AnchorURL url ;
2010-06-23 13:19:32 +02:00
String anchorText ;
while ( i . hasNext ( ) ) {
entry = i . next ( ) ;
url = entry . getKey ( ) ;
anchorText = entry . getValue ( ) ;
2011-06-13 23:44:03 +02:00
if ( matchesText ( anchorText ) ) {
2010-06-23 13:19:32 +02:00
matcher . put ( url , anchorText ) ;
i . remove ( ) ;
}
}
return matcher ;
}
2011-06-13 23:44:03 +02:00
2012-06-05 12:06:26 +02:00
private volatile String idCacheAnon = null , idCache = null ;
2010-09-06 12:00:07 +02:00
final static private char asterisk = '*' ;
2008-08-02 14:12:04 +02:00
public String id ( final boolean anonymized ) {
2010-09-06 12:00:07 +02:00
if ( anonymized ) {
2011-06-13 23:44:03 +02:00
if ( this . idCacheAnon ! = null ) return this . idCacheAnon ;
2010-09-06 12:00:07 +02:00
} else {
2011-06-13 23:44:03 +02:00
if ( this . idCache ! = null ) return this . idCache ;
2010-09-06 12:00:07 +02:00
}
2012-06-05 12:06:26 +02:00
synchronized ( this ) {
// do a Double-Checked Locking
if ( anonymized ) {
if ( this . idCacheAnon ! = null ) return this . idCacheAnon ;
} else {
if ( this . idCache ! = null ) return this . idCache ;
}
// generate a string that identifies a search so results can be re-used in a cache
final StringBuilder context = new StringBuilder ( 180 ) ;
if ( anonymized ) {
2012-11-18 01:22:41 +01:00
context . append ( anonymizedQueryHashes ( this . queryGoal . getIncludeHashes ( ) ) ) ;
2012-06-05 12:06:26 +02:00
context . append ( '-' ) ;
2012-11-18 01:22:41 +01:00
context . append ( anonymizedQueryHashes ( this . queryGoal . getExcludeHashes ( ) ) ) ;
2012-06-05 12:06:26 +02:00
} else {
2012-11-18 01:22:41 +01:00
context . append ( hashSet2hashString ( this . queryGoal . getIncludeHashes ( ) ) ) ;
2012-06-05 12:06:26 +02:00
context . append ( '-' ) ;
2012-11-18 01:22:41 +01:00
context . append ( hashSet2hashString ( this . queryGoal . getExcludeHashes ( ) ) ) ;
2012-06-05 12:06:26 +02:00
}
//context.append(asterisk);
//context.append(this.domType);
context . append ( asterisk ) ;
context . append ( this . contentdom ) . append ( asterisk ) ;
context . append ( this . zonecode ) . append ( asterisk ) ;
context . append ( ASCII . String ( Word . word2hash ( this . ranking . toExternalString ( ) ) ) ) . append ( asterisk ) ;
context . append ( Base64Order . enhancedCoder . encodeString ( this . prefer . toString ( ) ) ) . append ( asterisk ) ;
context . append ( Base64Order . enhancedCoder . encodeString ( this . urlMask . toString ( ) ) ) . append ( asterisk ) ;
2013-02-12 03:42:46 +01:00
context . append ( this . modifier . sitehash ) . append ( asterisk ) ;
context . append ( this . modifier . author ) . append ( asterisk ) ;
2013-04-23 20:42:54 +02:00
context . append ( this . modifier . protocol ) . append ( asterisk ) ;
context . append ( this . modifier . filetype ) . append ( asterisk ) ;
context . append ( this . modifier . collection ) . append ( asterisk ) ;
context . append ( this . modifier . toString ( ) ) . append ( asterisk ) ;
context . append ( this . siteexcludes ) . append ( asterisk ) ;
2012-06-05 12:06:26 +02:00
context . append ( this . targetlang ) . append ( asterisk ) ;
context . append ( this . constraint ) . append ( asterisk ) ;
context . append ( this . maxDistance ) . append ( asterisk ) ;
2013-01-14 12:50:21 +01:00
context . append ( this . tld ) . append ( asterisk ) ;
context . append ( this . inlink ) . append ( asterisk ) ;
2012-06-05 12:06:26 +02:00
context . append ( this . lat ) . append ( asterisk ) . append ( this . lon ) . append ( asterisk ) . append ( this . radius ) . append ( asterisk ) ;
context . append ( this . snippetCacheStrategy = = null ? " null " : this . snippetCacheStrategy . name ( ) ) ;
String result = context . toString ( ) ;
if ( anonymized ) {
this . idCacheAnon = result ;
} else {
this . idCache = result ;
}
return result ;
2010-07-18 11:10:46 +02:00
}
2007-08-25 01:12:59 +02:00
}
2011-06-13 23:44:03 +02:00
2009-06-02 00:45:28 +02:00
/ * *
* make a query anchor tag
* @param page
* @param theQuery
* @param originalUrlMask
* @param addToQuery
* @return
* /
2014-03-27 13:29:14 +01:00
public static StringBuilder navurl ( final RequestHeader . FileType ext , final int page , final QueryParams theQuery , final String newQueryString , boolean newModifierReplacesOld ) {
2011-06-13 23:44:03 +02:00
2014-03-21 18:01:26 +01:00
final StringBuilder sb = navurlBase ( ext , theQuery , newQueryString , newModifierReplacesOld ) ;
2011-06-13 23:44:03 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &startRecord= " ) ;
2012-05-21 01:58:29 +02:00
sb . append ( page * theQuery . itemsPerPage ( ) ) ;
2011-06-13 23:44:03 +02:00
return sb ;
}
2014-01-30 22:00:32 +01:00
/ * *
* construct navigator url
*
* @param ext extension of servlet ( e . g . html , rss )
* @param theQuery search query
* @param newModifier optional new modifier .
* - if null existing modifier of theQuery is appended
2014-01-30 22:57:27 +01:00
* - if not null this new modifier is appended in addition to existing modifier
* - if isEmpty overwrites ( clears ) existing modifier
2014-01-30 22:00:32 +01:00
* @return url to new search result page
* /
2014-03-27 13:29:14 +01:00
public static StringBuilder navurlBase ( final RequestHeader . FileType ext , final QueryParams theQuery , final String newModifier , boolean newModifierReplacesOld ) {
2010-07-18 11:10:46 +02:00
2011-03-09 10:29:05 +01:00
final StringBuilder sb = new StringBuilder ( 120 ) ;
2010-07-18 11:10:46 +02:00
sb . append ( " /yacysearch. " ) ;
2014-03-27 13:29:14 +01:00
sb . append ( ext . name ( ) . toLowerCase ( ) ) ;
2010-12-08 11:50:23 +01:00
sb . append ( " ?query= " ) ;
2014-01-30 22:00:32 +01:00
if ( newModifier = = null ) {
2014-03-21 18:01:26 +01:00
sb . append ( theQuery . getQueryGoal ( ) . getQueryString ( true ) ) ;
2014-01-30 22:00:32 +01:00
if ( ! theQuery . modifier . isEmpty ( ) ) sb . append ( " + " + theQuery . modifier . toString ( ) ) ;
} else {
2014-03-21 18:01:26 +01:00
if ( newModifier . isEmpty ( ) ) {
sb . append ( theQuery . getQueryGoal ( ) . getQueryString ( true ) ) ;
} else {
if ( newModifierReplacesOld ) {
sb . append ( newModifier ) ;
} else {
2014-03-27 13:29:14 +01:00
sb . append ( theQuery . queryGoal . getQueryString ( true ) ) ;
2014-03-21 18:01:26 +01:00
if ( ! theQuery . modifier . isEmpty ( ) ) sb . append ( " + " + theQuery . modifier . toString ( ) ) ;
sb . append ( " + " + newModifier ) ;
}
2014-01-30 22:57:27 +01:00
}
2014-01-30 22:00:32 +01:00
}
2010-07-18 11:10:46 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &maximumRecords= " ) ;
2012-05-21 01:58:29 +02:00
sb . append ( theQuery . itemsPerPage ( ) ) ;
2010-07-18 11:10:46 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &resource= " ) ;
2010-07-18 11:10:46 +02:00
sb . append ( ( theQuery . isLocal ( ) ) ? " local " : " global " ) ;
2014-01-05 03:40:10 +01:00
sb . append ( " &verify= " ) ;
2010-10-09 10:55:57 +02:00
sb . append ( theQuery . snippetCacheStrategy = = null ? " false " : theQuery . snippetCacheStrategy . toName ( ) ) ;
2010-07-18 11:10:46 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &prefermaskfilter= " ) ;
2010-07-18 11:10:46 +02:00
sb . append ( theQuery . prefer ) ;
2014-01-05 03:40:10 +01:00
sb . append ( " &cat=href " ) ;
2010-07-18 11:10:46 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &constraint= " ) ;
2010-07-18 11:10:46 +02:00
sb . append ( ( theQuery . constraint = = null ) ? " " : theQuery . constraint . exportB64 ( ) ) ;
2014-01-05 03:40:10 +01:00
sb . append ( " &contentdom= " ) ;
2012-04-22 00:04:36 +02:00
sb . append ( theQuery . contentdom . toString ( ) ) ;
2010-07-18 11:10:46 +02:00
2014-01-05 03:40:10 +01:00
sb . append ( " &former= " ) ;
2014-01-20 00:58:17 +01:00
sb . append ( theQuery . getQueryGoal ( ) . getQueryString ( true ) ) ;
2010-07-18 11:10:46 +02:00
2011-06-13 23:44:03 +02:00
return sb ;
2009-06-02 00:45:28 +02:00
}
2011-06-13 23:44:03 +02:00
2005-10-10 02:33:25 +02:00
}