// Path: src/main/java/ro/cs/products/util/Polygon2D.java
// public class Polygon2D {
//     private static final Pattern polyPattern = Pattern.compile("POLYGON\\(\\(.*\\)\\)");
//     private static final Pattern coordPattern = Pattern.compile("((?:-?(?:\\d+\\.\\d+)) (?:-?(?:\\d+\\.\\d+)))");
// 
//     private Path2D.Double polygon;
//     private int numPoints;
// 
//     /**
//      * Creates a polygon from a well-known text.
//      * For now, only single POLYGONs are supported.
//      * If multiple polygons are encountered, only the first one is taken into account.
//      *
//      * @param wkt   The text to parse.
//      * @return      A closed polygon.
//      */
//     public static Polygon2D fromWKT(String wkt) {
//         Polygon2D polygon = new Polygon2D();
//         Matcher matcher = polyPattern.matcher(wkt);
//         if (matcher.matches()) {
//             String polyText = matcher.toMatchResult().group(0);
//             if (polyText != null) {
//                 Matcher coordMatcher = coordPattern.matcher(polyText);
//                 while (coordMatcher.find()) {
//                     //for (int i = 0; i < coordMatcher.groupCount(); i++) {
//                         String[] coords = coordMatcher.group().split(" ");
//                         polygon.append(Double.parseDouble(coords[0]), Double.parseDouble(coords[1]));
//                     //}
//                 }
//             }
//         } else {
//             // maybe we have only a list of coordinates, without being wrapped in a POLYGON((..))
//             Matcher coordMatcher = coordPattern.matcher(wkt);
//             while (coordMatcher.find()) {
//                 //for (int i = 0; i < coordMatcher.groupCount(); i++) {
//                 String[] coords = coordMatcher.group().split(" ");
//                 polygon.append(Double.parseDouble(coords[0]), Double.parseDouble(coords[1]));
//                 //}
//             }
//         }
//         return polygon;
//     }
// 
//     public Polygon2D() {
//     }
// 
//     /**
//      * Adds a point to the current polygon.
//      * If this is not the first point, then it also adds a line between the previous point and the new one.
//      *
//      * @param x     The x coordinate
//      * @param y     The y coordinate
//      */
//     public void append(double x, double y) {
//         if (polygon == null) {
//             polygon = new Path2D.Double();
//             polygon.moveTo(x, y);
//         } else {
//             polygon.lineTo(x, y);
//         }
//         numPoints++;
//     }
// 
//     /**
//      * Adds a list of points to the current polygon.
//      * The list items are pairs of coordinates.
//      *
//      * @param points    The points to be added
//      */
//     public void append(List<double[]> points) {
//         if (points != null) {
//             for (double[] pair : points) {
//                 if (pair != null && pair.length == 2) {
//                     append(pair[0], pair[1]);
//                 }
//             }
//         }
//     }
// 
//     /**
//      * Returns the number of points of the current polygon.
//      *
//      */
//     public int getNumPoints() {
//         return numPoints;
//     }
// 
//     /**
//      * Produces a WKT representation of this polygon.
//      */
//     public String toWKT() {
//         StringBuilder buffer = new StringBuilder();
//         buffer.append("POLYGON((");
//         PathIterator pathIterator = polygon.getPathIterator(null);
//         while (!pathIterator.isDone()) {
//             double[] segment = new double[6];
//             pathIterator.currentSegment(segment);
//             buffer.append(String.valueOf(segment[0])).append(" ").append(String.valueOf(segment[1])).append(",");
//             pathIterator.next();
//         }
//         buffer.setLength(buffer.length() - 1);
//         buffer.append("))");
//         return buffer.toString();
//     }
// 
//     public Rectangle2D getBounds2D() {
//         return polygon.getBounds2D();
//     }
// 
//     public String toWKTBounds() {
//         Rectangle2D bounds2D = polygon.getBounds2D();
//         return  "POLYGON((" +
//                 bounds2D.getMinX() + " " + bounds2D.getMinY() + "," +
//                 bounds2D.getMaxX() + " " + bounds2D.getMinY() + "," +
//                 bounds2D.getMaxX() + " " + bounds2D.getMaxY() + "," +
//                 bounds2D.getMinX() + " " + bounds2D.getMaxY() + "," +
//                 bounds2D.getMinX() + " " + bounds2D.getMinY() + "))";
//     }
// 
// }


import java.util.stream.Collectors;
import org.apache.http.NameValuePair;
import org.apache.http.auth.UsernamePasswordCredentials;
import ro.cs.products.util.Polygon2D;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
/*
 * 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 ro.cs.products.base;



/**
 * Base class for search providers
 *
 * @author Cosmin Cara
 */
public abstract class AbstractSearch<T extends Object> {
    protected URI url;
// Path: src/main/java/ro/cs/products/util/Polygon2D.java
// public class Polygon2D {
//     private static final Pattern polyPattern = Pattern.compile("POLYGON\\(\\(.*\\)\\)");
//     private static final Pattern coordPattern = Pattern.compile("((?:-?(?:\\d+\\.\\d+)) (?:-?(?:\\d+\\.\\d+)))");
// 
//     private Path2D.Double polygon;
//     private int numPoints;
// 
//     /**
//      * Creates a polygon from a well-known text.
//      * For now, only single POLYGONs are supported.
//      * If multiple polygons are encountered, only the first one is taken into account.
//      *
//      * @param wkt   The text to parse.
//      * @return      A closed polygon.
//      */
//     public static Polygon2D fromWKT(String wkt) {
//         Polygon2D polygon = new Polygon2D();
//         Matcher matcher = polyPattern.matcher(wkt);
//         if (matcher.matches()) {
//             String polyText = matcher.toMatchResult().group(0);
//             if (polyText != null) {
//                 Matcher coordMatcher = coordPattern.matcher(polyText);
//                 while (coordMatcher.find()) {
//                     //for (int i = 0; i < coordMatcher.groupCount(); i++) {
//                         String[] coords = coordMatcher.group().split(" ");
//                         polygon.append(Double.parseDouble(coords[0]), Double.parseDouble(coords[1]));
//                     //}
//                 }
//             }
//         } else {
//             // maybe we have only a list of coordinates, without being wrapped in a POLYGON((..))
//             Matcher coordMatcher = coordPattern.matcher(wkt);
//             while (coordMatcher.find()) {
//                 //for (int i = 0; i < coordMatcher.groupCount(); i++) {
//                 String[] coords = coordMatcher.group().split(" ");
//                 polygon.append(Double.parseDouble(coords[0]), Double.parseDouble(coords[1]));
//                 //}
//             }
//         }
//         return polygon;
//     }
// 
//     public Polygon2D() {
//     }
// 
//     /**
//      * Adds a point to the current polygon.
//      * If this is not the first point, then it also adds a line between the previous point and the new one.
//      *
//      * @param x     The x coordinate
//      * @param y     The y coordinate
//      */
//     public void append(double x, double y) {
//         if (polygon == null) {
//             polygon = new Path2D.Double();
//             polygon.moveTo(x, y);
//         } else {
//             polygon.lineTo(x, y);
//         }
//         numPoints++;
//     }
// 
//     /**
//      * Adds a list of points to the current polygon.
//      * The list items are pairs of coordinates.
//      *
//      * @param points    The points to be added
//      */
//     public void append(List<double[]> points) {
//         if (points != null) {
//             for (double[] pair : points) {
//                 if (pair != null && pair.length == 2) {
//                     append(pair[0], pair[1]);
//                 }
//             }
//         }
//     }
// 
//     /**
//      * Returns the number of points of the current polygon.
//      *
//      */
//     public int getNumPoints() {
//         return numPoints;
//     }
// 
//     /**
//      * Produces a WKT representation of this polygon.
//      */
//     public String toWKT() {
//         StringBuilder buffer = new StringBuilder();
//         buffer.append("POLYGON((");
//         PathIterator pathIterator = polygon.getPathIterator(null);
//         while (!pathIterator.isDone()) {
//             double[] segment = new double[6];
//             pathIterator.currentSegment(segment);
//             buffer.append(String.valueOf(segment[0])).append(" ").append(String.valueOf(segment[1])).append(",");
//             pathIterator.next();
//         }
//         buffer.setLength(buffer.length() - 1);
//         buffer.append("))");
//         return buffer.toString();
//     }
// 
//     public Rectangle2D getBounds2D() {
//         return polygon.getBounds2D();
//     }
// 
//     public String toWKTBounds() {
//         Rectangle2D bounds2D = polygon.getBounds2D();
//         return  "POLYGON((" +
//                 bounds2D.getMinX() + " " + bounds2D.getMinY() + "," +
//                 bounds2D.getMaxX() + " " + bounds2D.getMinY() + "," +
//                 bounds2D.getMaxX() + " " + bounds2D.getMaxY() + "," +
//                 bounds2D.getMinX() + " " + bounds2D.getMaxY() + "," +
//                 bounds2D.getMinX() + " " + bounds2D.getMinY() + "))";
//     }
// 
// }


// Path: src/main/java/ro/cs/products/base/AbstractSearch.java
import java.util.stream.Collectors;
import org.apache.http.NameValuePair;
import org.apache.http.auth.UsernamePasswordCredentials;
import ro.cs.products.util.Polygon2D;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

/*
 * 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 ro.cs.products.base;



/**
 * Base class for search providers
 *
 * @author Cosmin Cara
 */
public abstract class AbstractSearch<T extends Object> {
    protected URI url;
    protected Polygon2D aoi;