org.geotools.data.solr.SolrFeatureReader.java Source code

Java tutorial

Introduction

Here is the source code for org.geotools.data.solr.SolrFeatureReader.java

Source

/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 * 
 *    (C) 2014, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 */

package org.geotools.data.solr;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.logging.Level;

import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.CursorMarkParams;
import org.geotools.data.FeatureReader;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

/**
 * Reader for SOLR datastore
 */

public class SolrFeatureReader implements FeatureReader<SimpleFeatureType, SimpleFeature> {

    private Iterator<SolrDocument> solrDocIterator;

    private SimpleFeatureType featureType;

    private Boolean next;

    private SimpleFeatureBuilder builder;

    private SolrAttribute pkey;

    private HttpSolrServer server;

    private WKTReader wktReader;

    private SolrDataStore solrDataStore;

    private String cursorMark;

    private String nextCursorMark;

    private SolrQuery solrQuery;

    private long counter;

    /**
     * Creates the feature reader for SOLR store <br>
     * The feature reader use SOLR CURSOR to paginate request, so multiple SOLR query will be
     * executed
     * 
     * @param featureType the feature type to query
     * @param solrUrl the URL of SOLR server
     * @param solrQuery the SOLR query to execute
     * @param solrDataStore the SOLR store
     * @throws SolrServerException
     */
    public SolrFeatureReader(SimpleFeatureType featureType, HttpSolrServer server, SolrQuery solrQuery,
            SolrDataStore solrDataStore) throws SolrServerException {
        this.featureType = featureType;
        this.solrQuery = solrQuery;
        this.wktReader = new WKTReader();
        this.solrDataStore = solrDataStore;
        this.pkey = solrDataStore.getPrimaryKey(featureType.getTypeName());

        this.builder = new SimpleFeatureBuilder(featureType);

        this.server = server;

        // Add always pk as field if not already present
        if (solrQuery.getFields() != null && !solrQuery.getFields().contains(pkey.getName())) {
            solrQuery.addField(pkey.getName());
        }

        // Can't use pagination with start, then first query for cursor mark of start
        if (solrQuery.getStart() != null && solrQuery.getStart() > 0) {
            cursorMark = getCursorMarkForStart(server, solrQuery);
        } else {
            cursorMark = CursorMarkParams.CURSOR_MARK_START;
        }
        solrQuery.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
        QueryResponse rsp = server.query(solrQuery);
        if (this.solrDataStore.getLogger().isLoggable(Level.FINE)) {
            this.solrDataStore.getLogger().log(Level.FINE, "SOLR query done: " + solrQuery.toString());
        }
        this.solrDocIterator = rsp.getResults().iterator();
        nextCursorMark = rsp.getNextCursorMark();
        counter = 0;
    }

    /*
     * Can't use CURSOR MARK with "start" parameter, so get initial SOLR CURSOR MARK to positioning
     * CURSOR at the row specified by start query parameter
     */
    private String getCursorMarkForStart(HttpSolrServer server, SolrQuery solrQuery) throws SolrServerException {
        Integer prevRows = solrQuery.getRows();
        solrQuery.setRows(solrQuery.getStart());
        solrQuery.setStart(0);
        solrQuery.set(CursorMarkParams.CURSOR_MARK_PARAM, CursorMarkParams.CURSOR_MARK_START);
        QueryResponse rsp = server.query(solrQuery);
        if (this.solrDataStore.getLogger().isLoggable(Level.FINE)) {
            this.solrDataStore.getLogger().log(Level.FINE, "SOLR query done: " + solrQuery.toString());
        }
        String nextC = rsp.getNextCursorMark();
        solrQuery.setRows(prevRows);
        return nextC;
    }

    @Override
    public SimpleFeatureType getFeatureType() {
        return this.featureType;
    }

    /**
     * SOLR multiValues fields are returned as single String field, with values concatenated and
     * separated by ";"
     */
    @Override
    public SimpleFeature next() throws IOException, IllegalArgumentException, NoSuchElementException {
        String fid = "";
        try {
            if (!hasNext()) {
                throw new NoSuchElementException("No more features in this reader, you should call "
                        + "hasNext() to check for feature availability");
            }
            SolrDocument doc = this.solrDocIterator.next();
            fid = featureType.getTypeName() + "." + doc.getFieldValue(pkey.getName());

            final int attributeCount = featureType.getAttributeCount();
            for (int i = 0; i < attributeCount; i++) {
                AttributeDescriptor type = featureType.getDescriptor(i);
                Object value = doc.getFieldValue(type.getLocalName());
                if (value instanceof List<?>) {
                    value = StringUtils.join(((List) value).toArray(), ";");
                }
                if (type instanceof GeometryDescriptor) {
                    GeometryDescriptor gatt = (GeometryDescriptor) type;
                    if (value != null) {
                        Geometry geometry = wktReader.read(value.toString());
                        if (geometry != null && geometry.getUserData() == null) {
                            geometry.setUserData(gatt.getCoordinateReferenceSystem());
                        }
                        builder.add(geometry);
                    }
                } else {
                    builder.add(value);
                }
            }
            return builder.buildFeature(fid);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } finally {
            if (this.solrDataStore.getLogger().isLoggable(Level.FINE)) {
                this.solrDataStore.getLogger().log(Level.FINE, "Created " + fid);
            }
            next = null;
            counter++;
        }
    }

    /**
     * SOLR CURSOR MARK is used to retrieve data until no more cursor and no more data is available
     */
    @Override
    public boolean hasNext() {
        if (next == null) {
            if (this.solrDocIterator.hasNext()) {
                next = true;
            } else {
                if (counter < solrQuery.getRows() && !cursorMark.equals(nextCursorMark)) {
                    cursorMark = nextCursorMark;
                    solrQuery.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
                    try {
                        QueryResponse rsp = server.query(solrQuery);
                        if (this.solrDataStore.getLogger().isLoggable(Level.FINE)) {
                            this.solrDataStore.getLogger().log(Level.FINE, solrQuery.toString());
                        }
                        this.solrDocIterator = rsp.getResults().iterator();
                        nextCursorMark = rsp.getNextCursorMark();
                        next = this.solrDocIterator.hasNext();
                    } catch (SolrServerException e) {
                        this.solrDataStore.getLogger().log(Level.SEVERE, e.getMessage(), e);
                        next = false;
                    }
                } else {
                    next = false;
                }
            }
        }
        return next.booleanValue();
    }

    @Override
    public void close() throws IOException {
        // nothing to do
    }

}