/**
* YearNavigator.java
* (C) 2016 by reger24; https://github.com/reger24
*
* This is a part of YaCy, a peer-to-peer based web search engine
*
* LICENSE
*
* 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, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.search.navigator;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import net.yacy.cora.federate.solr.SolrType;
import net.yacy.cora.sorting.ReversibleScoreMap;
import net.yacy.kelondro.data.meta.URIMetadataNode;
import net.yacy.search.query.QueryModifier;
import net.yacy.search.schema.CollectionSchema;
/**
* Navigator for date fields, showing the year of the date, ordered by the key =
* year string
*
* following fields are declared as SorlType.date (and can be used by YearNavigator)
* last_modified
* dates_in_content_dts
* startDates_dts
* endDates_dts
* load_date_dt
* fresh_date_dt
*
* as of now the config (in yacy.init/yacy.conf can be used to define the field
* to use by adding : (colon) fieldname, optional :Titlestring
* example: search.navigation=year:last_modified:Year
*
*/
public class YearNavigator extends StringNavigator implements Navigator {
public YearNavigator(String title, CollectionSchema field) {
super(title, field);
if (field.getType() != SolrType.date) throw new IllegalArgumentException("field is not of type Date");
}
/**
* For dates_in_content_dts a special modifier is returned to limit date for
* the full year using from:YEAR-01-01 to:YEAR-12-31
* @param key
* @return from:key-01-01 to:key-12-31
*/
@Override
public String getQueryModifier(final String key) {
if (this.field == CollectionSchema.dates_in_content_dts)
return "from:" + key +"-01-01 to:" + key + "-12-31 ";
else
return key;
}
/**
* Shortens the facet date field to a year and increases count
* @param facets
*/
@Override
public void incFacet(Map<String, ReversibleScoreMap<String>> facets) {
if (field != null && facets != null && !facets.isEmpty()) {
ReversibleScoreMap<String> fcts = facets.get(field.getSolrFieldName());
if (fcts != null) {
Iterator<String> it = fcts.iterator();
// loop through the facet to extract the year
while (it.hasNext()) {
String datestring = it.next();
this.inc(datestring.substring(0, 4), fcts.get(datestring));
}
}
}
}
@Override
public void incDoc(URIMetadataNode doc) {
if (field != null) {
if (field.getType() == SolrType.date) {
Object val = doc.getFieldValue(field.getSolrFieldName());
if (val != null) {
Calendar cal = Calendar.getInstance();
if (val instanceof Collection) {
Collection<?> ll = (Collection<?>) val;
for (Object o : ll) {
if (o instanceof String) {
this.inc((String) o);
} else if (o instanceof Date) {
cal.setTime((Date) o);
String year = Integer.toString(cal.get(Calendar.YEAR));
this.inc(year);
}
}
} else {
cal.setTime((Date) val);
String year = Integer.toString(cal.get(Calendar.YEAR));
this.inc(year);
}
}
}
}
}
/**
* YearNavigator returns keys in asc or desc order instead of ordered by
* score
*
* @param up true = asc
* @return key alphabetically ordered
*/
@Override
public Iterator<String> keys(boolean up) {
TreeSet<String> years;
if (up) {
years = new TreeSet<String>();
} else {
years = new TreeSet<String>(Collections.reverseOrder());
}
// make sure keys with high score are included (display may be limited in size)
// Iterator<String> it = this.iterator();
Iterator<String> it = super.keys(false);
while (it.hasNext()) {
years.add(it.next());
}
return years.iterator();
}
/**
* For date_in_content_dts it return true if form:YEAR and to:YEAR is part
* of the modifier, otherwise false.
* @param modifier the search query modifier
* @param name 4 digit year string
* @return true when when the modifier is active
*/
@Override
public boolean modifieractive(QueryModifier modifier, String name) {
if (this.field == CollectionSchema.dates_in_content_dts) {
if (modifier.toString().contains("from:" + name) && modifier.toString().contains("to:" + name)) {
return true;
}
}
return false;
}
}