// 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 org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.indoqa.solr.spatial.corridor.LineStringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.slf4j.Logger;
        result = prime * result + (this.routeValueSource == null ? 0 : this.routeValueSource.hashCode());
        result = prime * result + (this.queryPoints == null ? 0 : this.queryPoints.hashCode());
        result = prime * result + (this.description() == null ? 0 : this.description().hashCode());
        return result;
    }

    protected abstract double getValue(LineString lineString);

    private final class InverseCorridorDocValues extends DoubleDocValues {

        private FunctionValues routeValues;
        private FunctionValues hashValues;

        protected InverseCorridorDocValues(ValueSource vs, FunctionValues routeValues, FunctionValues hashValues) {
            super(vs);

            this.routeValues = routeValues;
            this.hashValues = hashValues;
        }

        @Override
        public double doubleVal(int docId) throws IOException {
            String routeAsString = this.routeValues.strVal(docId);
            String routeAsHash = this.hashValues.strVal(docId);

            try{
                if (routeAsString == null || routeAsString.isEmpty()) {
                    return Double.MAX_VALUE;
                }

// 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/query/points/AbstractPointsQueryCorridorValueSource.java
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.indoqa.solr.spatial.corridor.LineStringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.slf4j.Logger;

        result = prime * result + (this.routeValueSource == null ? 0 : this.routeValueSource.hashCode());
        result = prime * result + (this.queryPoints == null ? 0 : this.queryPoints.hashCode());
        result = prime * result + (this.description() == null ? 0 : this.description().hashCode());
        return result;
    }

    protected abstract double getValue(LineString lineString);

    private final class InverseCorridorDocValues extends DoubleDocValues {

        private FunctionValues routeValues;
        private FunctionValues hashValues;

        protected InverseCorridorDocValues(ValueSource vs, FunctionValues routeValues, FunctionValues hashValues) {
            super(vs);

            this.routeValues = routeValues;
            this.hashValues = hashValues;
        }

        @Override
        public double doubleVal(int docId) throws IOException {
            String routeAsString = this.routeValues.strVal(docId);
            String routeAsHash = this.hashValues.strVal(docId);

            try{
                if (routeAsString == null || routeAsString.isEmpty()) {
                    return Double.MAX_VALUE;
                }

                LineString route = LineStringUtils.parseOrGet(routeAsString, routeAsHash);