/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.solr.response.transform; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.lucene.index.BinaryDocValues; import org.apache.lucene.util.BytesRef; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.search.CitationLRUCache; import org.apache.solr.search.SolrIndexSearcher; /** * * @since solr 4.0 */ public class CitationsTransformerFactory extends TransformerFactory { private String cacheName; private String resolutionField; @Override public void init(NamedList args) { defaultUserArgs = (String)args.get( "args" ); cacheName = (String)args.get( "cache-name" ); resolutionField = (String)args.get( "resolution-field" ); assert cacheName != null; assert resolutionField != null; } @Override public DocTransformer create(String field, SolrParams params, SolrQueryRequest req) { SolrIndexSearcher searcher = req.getSearcher(); CitationLRUCache<Object,Integer> cache = (CitationLRUCache<Object,Integer>) searcher.getCache(cacheName); if (cache == null) { throw new SolrException(ErrorCode.SERVER_ERROR, "Cannot find cache: " + cacheName); } Map<Integer, List<Integer>> references = null; int[][] citations = null; BinaryDocValues idMapping = null; if (params.getBool("resolve", false)) { try { idMapping = req.getSearcher().getSlowAtomicReader().getSortedDocValues(resolutionField); } catch (IOException e) { throw new SolrException(ErrorCode.SERVER_ERROR, "Cannot get data for resolving field: " + resolutionField, e); } } return new CitationsTransform( field, cache, params.get("counts", "citations,references"), params.get("values", ""), idMapping ); } } class CitationsTransform extends DocTransformer { final String name; private String[] counts; private String[] values; private BinaryDocValues idMapping; private CitationLRUCache<Object,Integer> cache; public CitationsTransform( String display, CitationLRUCache<Object,Integer> cache, String counts, String values, BinaryDocValues idMapping ) { this.name = display; this.cache = cache; this.counts = counts.split("\\s*,\\s*"); this.values = values.split("\\s*,\\s*"); this.idMapping = idMapping; } @Override public String getName() { return name; } @Override public void transform(SolrDocument doc, int docid, float score) { if( docid >= 0) { doc.setField( name, generate(doc, docid) ); } } private Map generate(SolrDocument doc, int docid) { HashMap<String, Object> data = new HashMap<String, Object>(); if (counts.length > 0) { for (String f: counts) { if (f.equals("citations")) { data.put("num_citations", getCitationCount(doc, docid)); } else if (f.equals("references")) { data.put("num_references", getReferenceCount(doc, docid)); } } for (String f: values) { if (f.equals("citations")) { data.put("citations", getCitationValues(doc, docid)); } else if (f.equals("references")) { data.put("references", getReferenceValues(doc, docid)); } } } return data; } private List<String> getCitationValues(SolrDocument doc, int docid) { ArrayList<String> data = new ArrayList<String>(); BytesRef ret = new BytesRef(); int[] citations = cache.getCitations(docid); if (citations != null) { for (int i=0;i<citations.length;i++) { if (citations[i] < 0) // unresolved refs = -1 continue; if (idMapping != null) { ret = idMapping.get(citations[i]); data.add(ret.utf8ToString()); } else { data.add(Integer.toString(citations[i])); } } } return data; } private List<String> getReferenceValues(SolrDocument doc, int docid) { ArrayList<String> data = new ArrayList<String>(); BytesRef ret = new BytesRef(); int[] references = cache.getReferences(docid); if (references != null) { for (int i=0;i<references.length;i++) { if (references[i] < 0) // unresolved refs = -1 continue; if (idMapping != null) { ret = idMapping.get(references[i]); data.add(ret.utf8ToString()); } else { data.add(Integer.toString(references[i])); } } } return data; } private int getCitationCount(SolrDocument doc, int docid) { int[] v = cache.getCitations(docid); if (v != null) { return _count(v); } else { return 0; } } private int _count(int[] v) { int res = 0; for (int x: v) { if (x >= 0) res++; } return res; } private int getReferenceCount(SolrDocument doc, int docid) { int[] v = cache.getReferences(docid); if (v != null) { return _count(v); } else { return 0; } } }