All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.response.transform.GeoTransformerFactory Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * 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.Iterator;

import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.spatial.ShapeValues;
import org.apache.lucene.spatial.ShapeValuesSource;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.composite.CompositeSpatialStrategy;
import org.apache.lucene.spatial.serialized.SerializedDVStrategy;
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.request.SolrQueryRequest;
import org.apache.solr.response.JSONResponseWriter;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.schema.AbstractSpatialFieldType;
import org.apache.solr.schema.SchemaField;
import org.locationtech.spatial4j.io.GeoJSONWriter;
import org.locationtech.spatial4j.io.ShapeWriter;
import org.locationtech.spatial4j.io.SupportedFormats;
import org.locationtech.spatial4j.shape.Shape;


/**
 * This DocumentTransformer will write a {@link Shape} to the SolrDocument using
 * the requested format.  Supported formats include:
 * 
    *
  • GeoJSON
  • *
  • WKT
  • *
  • Polyshape
  • *
* For more information see: spatial4j/FORMATS.md * * The shape is either read from a stored field, or a ValueSource. * * This transformer is useful when: *
    *
  • You want to return a format different than the stored encoding (WKT vs GeoJSON)
  • *
  • The {@link Shape} is stored in a {@link ValueSource}, not a stored field
  • *
  • the value is not stored in a format the output understands (ie, raw GeoJSON)
  • *
* */ public class GeoTransformerFactory extends TransformerFactory { @Override public DocTransformer create(String display, SolrParams params, SolrQueryRequest req) { String fname = params.get("f", display); if(fname.startsWith("[") && fname.endsWith("]")) { fname = display.substring(1,display.length()-1); } SchemaField sf = req.getSchema().getFieldOrNull(fname); if(sf==null) { throw new SolrException(ErrorCode.BAD_REQUEST, this.getClass().getSimpleName() +" using unknown field: "+fname); } if(!(sf.getType() instanceof AbstractSpatialFieldType)) { throw new SolrException(ErrorCode.BAD_REQUEST, "GeoTransformer requested non-spatial field: "+fname + " ("+sf.getType().getClass().getSimpleName()+")"); } final GeoFieldUpdater updater = new GeoFieldUpdater(); updater.field = fname; updater.display = display; updater.display_error = display+"_error"; final ShapeValuesSource shapes; AbstractSpatialFieldType sdv = (AbstractSpatialFieldType)sf.getType(); SpatialStrategy strategy = sdv.getStrategy(fname); if(strategy instanceof CompositeSpatialStrategy) { shapes = ((CompositeSpatialStrategy)strategy) .getGeometryStrategy().makeShapeValueSource(); } else if(strategy instanceof SerializedDVStrategy) { shapes = ((SerializedDVStrategy)strategy) .makeShapeValueSource(); } else shapes = null; String writerName = params.get("w", "GeoJSON"); updater.formats = strategy.getSpatialContext().getFormats(); updater.writer = updater.formats.getWriter(writerName); if(updater.writer==null) { StringBuilder str = new StringBuilder(); str.append( "Unknown Spatial Writer: " ).append(writerName); str.append(" ["); for(ShapeWriter w : updater.formats.getWriters()) { str.append(w.getFormatName()).append(' '); } str.append("]"); throw new SolrException(ErrorCode.BAD_REQUEST, str.toString()); } QueryResponseWriter qw = req.getCore().getQueryResponseWriter(req); updater.isJSON = (qw.getClass() == JSONResponseWriter.class) && (updater.writer instanceof GeoJSONWriter); // Using ValueSource if(shapes!=null) { return new DocTransformer() { @Override public String getName() { return display; } @Override public void transform(SolrDocument doc, int docid) throws IOException { int leafOrd = ReaderUtil.subIndex(docid, context.getSearcher().getTopReaderContext().leaves()); LeafReaderContext ctx = context.getSearcher().getTopReaderContext().leaves().get(leafOrd); ShapeValues values = shapes.getValues(ctx); int segmentDoc = docid - ctx.docBase; if (values.advanceExact(segmentDoc)) { updater.setValue(doc, values.value()); } } }; } // Using the raw stored values return new DocTransformer() { @Override public void transform(SolrDocument doc, int docid) throws IOException { Object val = doc.remove(updater.field); if(val!=null) { updater.setValue(doc, val); } } @Override public String getName() { return updater.display; } @Override public String[] getExtraRequestFields() { return new String[] {updater.field}; } }; } } class GeoFieldUpdater { String field; String display; String display_error; boolean isJSON; ShapeWriter writer; SupportedFormats formats; void addShape(SolrDocument doc, Shape shape) { if(isJSON) { doc.addField(display, new WriteableGeoJSON(shape, writer)); } else { doc.addField(display, writer.toString(shape)); } } void setValue(SolrDocument doc, Object val) { doc.remove(display); if(val != null) { if(val instanceof Iterable) { Iterator iter = ((Iterable)val).iterator(); while(iter.hasNext()) { addValue(doc, iter.next()); } } else { addValue(doc, val); } } } void addValue(SolrDocument doc, Object val) { if(val == null) { return; } if(val instanceof Shape) { addShape(doc, (Shape)val); } // Don't explode on 'InvalidShpae' else if( val instanceof Exception) { doc.setField( display_error, ((Exception)val).toString() ); } else { // Use the stored value if(val instanceof IndexableField) { val = ((IndexableField)val).stringValue(); } try { addShape(doc, formats.read(val.toString())); } catch(Exception ex) { doc.setField( display_error, ex.toString() ); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy