// Path: src/main/java/com/indoqa/solr/spatial/corridor/HashGeometry.java
// public class HashGeometry {
// 
//     private String hash;
//     private String geometry;
// 
//     public String getHash() {
//         return hash;
//     }
// 
//     public void setHash(String hash) {
//         this.hash = hash;
//     }
// 
//     public String getGeometry() {
//         return geometry;
//     }
// 
//     public void setGeometry(String geometry) {
//         this.geometry = geometry;
//     }
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/LineStringUtils.java
// public final class LineStringUtils {
// 
//     static {
//         cache = Caffeine.newBuilder()
//                 .maximumSize(100000)
//                 .expireAfterAccess(24, TimeUnit.HOURS)
//                 .build();
//     }
// 
//     private static Cache<String, LineString> cache;
// 
//     public static LineString parseOrGet(String value, String hash)  {
//         if (value == null) {
//             return null;
//         }
// 
//         if (hash != null) {
//             LineString cached = cache.getIfPresent(hash);
// 
//             if (cached != null) {
//                 return cached;
//             }
//         }
// 
//         String key = calculateHash(value);
//         return cache.get(key, s -> parseWktLinestring(value));
//     }
// 
//     public static HashGeometry cacheLineStringGetHashGeometry(String linestring, int radiusInMeters){
//         if(linestring == null){
//             return null;
//         }
//         String key = calculateHash(linestring);
//         LineString parsedLineString = parseWktLinestring(linestring);
// 
//         cache.put(key, parsedLineString);
//         HashGeometry result = new HashGeometry();
//         // meters /((PI/180)x6378137)
//         result.setGeometry(parsedLineString.buffer(radiusInMeters / (Math.PI / 180 * 6378137)).toText());
//         result.setHash(key);
//         return result;
//     }
// 
//     public static void purgeCache() {
//         cache.invalidateAll();
//         cache.cleanUp();
//     }
// 
//     private static LineString parseWktLinestring(String corridorLineString) {
//         return WktUtils.parseLineString(corridorLineString);
//     }
// 
//     private static String calculateHash(String linestring) {
//         if (linestring == null) {
//             return null;
//         }
// 
//         StringBuilder result = new StringBuilder("hash-");
//         result.append(Hex.encodeHex(DigestUtils.md5(linestring)));
//         return result.toString();
//     }
// }


import com.indoqa.solr.spatial.corridor.HashGeometry;
import com.indoqa.solr.spatial.corridor.LineStringUtils;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.processor.UpdateRequestProcessor;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import java.io.IOException;
import static org.apache.solr.common.SolrException.ErrorCode.SERVER_ERROR;
        private Integer radiusInMeters;

        public LinestringHashUpdateProcessor(final String linestringFieldName,
                                             final String hashFieldName,
                                             final String linestringPolygonName,
                                             final Integer radiusInMeters,
                                             final UpdateRequestProcessor next) {
            super(next);
            this.linestringFieldName = linestringFieldName;
            this.hashFieldName = hashFieldName;
            this.radiusInMeters = radiusInMeters;
            this.linestringPolygonName = linestringPolygonName;
        }

        @Override
        public void processAdd(AddUpdateCommand cmd) throws IOException {
            final SolrInputDocument doc = cmd.getSolrInputDocument();

            if (doc.containsKey(this.linestringFieldName)) {
                if (!doc.containsKey(this.hashFieldName) || !doc.containsKey(this.linestringPolygonName)) {
                    HashGeometry hashGeometry = calculateHash(doc.getFieldValue(linestringFieldName));
                    doc.addField(this.hashFieldName, hashGeometry.getHash());
                    doc.addField(this.linestringPolygonName, hashGeometry.getGeometry());
                }
            }

            super.processAdd(cmd);
        }

        private HashGeometry calculateHash(Object fieldValue) {
// Path: src/main/java/com/indoqa/solr/spatial/corridor/HashGeometry.java
// public class HashGeometry {
// 
//     private String hash;
//     private String geometry;
// 
//     public String getHash() {
//         return hash;
//     }
// 
//     public void setHash(String hash) {
//         this.hash = hash;
//     }
// 
//     public String getGeometry() {
//         return geometry;
//     }
// 
//     public void setGeometry(String geometry) {
//         this.geometry = geometry;
//     }
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/LineStringUtils.java
// public final class LineStringUtils {
// 
//     static {
//         cache = Caffeine.newBuilder()
//                 .maximumSize(100000)
//                 .expireAfterAccess(24, TimeUnit.HOURS)
//                 .build();
//     }
// 
//     private static Cache<String, LineString> cache;
// 
//     public static LineString parseOrGet(String value, String hash)  {
//         if (value == null) {
//             return null;
//         }
// 
//         if (hash != null) {
//             LineString cached = cache.getIfPresent(hash);
// 
//             if (cached != null) {
//                 return cached;
//             }
//         }
// 
//         String key = calculateHash(value);
//         return cache.get(key, s -> parseWktLinestring(value));
//     }
// 
//     public static HashGeometry cacheLineStringGetHashGeometry(String linestring, int radiusInMeters){
//         if(linestring == null){
//             return null;
//         }
//         String key = calculateHash(linestring);
//         LineString parsedLineString = parseWktLinestring(linestring);
// 
//         cache.put(key, parsedLineString);
//         HashGeometry result = new HashGeometry();
//         // meters /((PI/180)x6378137)
//         result.setGeometry(parsedLineString.buffer(radiusInMeters / (Math.PI / 180 * 6378137)).toText());
//         result.setHash(key);
//         return result;
//     }
// 
//     public static void purgeCache() {
//         cache.invalidateAll();
//         cache.cleanUp();
//     }
// 
//     private static LineString parseWktLinestring(String corridorLineString) {
//         return WktUtils.parseLineString(corridorLineString);
//     }
// 
//     private static String calculateHash(String linestring) {
//         if (linestring == null) {
//             return null;
//         }
// 
//         StringBuilder result = new StringBuilder("hash-");
//         result.append(Hex.encodeHex(DigestUtils.md5(linestring)));
//         return result.toString();
//     }
// }


// Path: src/main/java/com/indoqa/solr/spatial/corridor/processor/LinestringHashUpdateProcessorFactory.java
import com.indoqa.solr.spatial.corridor.HashGeometry;
import com.indoqa.solr.spatial.corridor.LineStringUtils;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.processor.UpdateRequestProcessor;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import java.io.IOException;
import static org.apache.solr.common.SolrException.ErrorCode.SERVER_ERROR;

        private Integer radiusInMeters;

        public LinestringHashUpdateProcessor(final String linestringFieldName,
                                             final String hashFieldName,
                                             final String linestringPolygonName,
                                             final Integer radiusInMeters,
                                             final UpdateRequestProcessor next) {
            super(next);
            this.linestringFieldName = linestringFieldName;
            this.hashFieldName = hashFieldName;
            this.radiusInMeters = radiusInMeters;
            this.linestringPolygonName = linestringPolygonName;
        }

        @Override
        public void processAdd(AddUpdateCommand cmd) throws IOException {
            final SolrInputDocument doc = cmd.getSolrInputDocument();

            if (doc.containsKey(this.linestringFieldName)) {
                if (!doc.containsKey(this.hashFieldName) || !doc.containsKey(this.linestringPolygonName)) {
                    HashGeometry hashGeometry = calculateHash(doc.getFieldValue(linestringFieldName));
                    doc.addField(this.hashFieldName, hashGeometry.getHash());
                    doc.addField(this.linestringPolygonName, hashGeometry.getGeometry());
                }
            }

            super.processAdd(cmd);
        }

        private HashGeometry calculateHash(Object fieldValue) {
            return LineStringUtils.cacheLineStringGetHashGeometry(fieldValue.toString(), this.radiusInMeters);