/**
   * Tests case where filter is makes use of 2 different attributes but Query object only requests 1
   * of the two attributes. This is a fix for a bug that has occurred.
   */
  @Test
  public void testFeatureReaderWithQuery() throws Exception {
    if (url == null) return;
    Map m = new HashMap();
    m.put(WFSDataStoreFactory.URL.key, url);
    m.put(WFSDataStoreFactory.TIMEOUT.key, new Integer(100000));
    WFS_1_0_0_DataStore wfs = (WFS_1_0_0_DataStore) (new WFSDataStoreFactory()).createDataStore(m);
    FilterFactory2 fac = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());

    Filter filter = fac.equals(fac.property("NAME"), fac.literal("E 58th St"));

    Query query = new Query("tiger:tiger_roads", filter);
    FeatureReader<SimpleFeatureType, SimpleFeature> reader =
        wfs.getFeatureReader(query, new DefaultTransaction());
    int expected = 0;
    while (reader.hasNext()) {
      expected++;
      reader.next();
    }
    query = new Query("tiger:tiger_roads", filter, 100, new String[] {"CFCC"}, "");
    reader = wfs.getFeatureReader(query, new DefaultTransaction());
    int count = 0;
    while (reader.hasNext()) {
      count++;
      reader.next();
    }

    assertEquals(expected, count);
  }
  private void testVendorParameters(Boolean usePost) throws IOException {
    if (url == null) return;

    Map m = new HashMap();
    m.put(WFSDataStoreFactory.URL.key, url);
    m.put(WFSDataStoreFactory.TIMEOUT.key, new Integer(100000));
    m.put(WFSDataStoreFactory.PROTOCOL.key, usePost);
    WFS_1_0_0_DataStore wfs = (WFS_1_0_0_DataStore) (new WFSDataStoreFactory()).createDataStore(m);

    final WFS100ProtocolHandler originalHandler = wfs.protocolHandler;
    wfs.protocolHandler =
        new WFS100ProtocolHandler(null, originalHandler.getConnectionFactory()) {
          @Override
          protected WFSCapabilities parseCapabilities(InputStream capabilitiesReader)
              throws IOException {
            return originalHandler.getCapabilities();
          }

          @Override
          public ConnectionFactory getConnectionFactory() {
            return new ConnectionFactoryWrapper(super.getConnectionFactory()) {

              @Override
              public HttpURLConnection getConnection(URL query, HttpMethod method)
                  throws IOException {
                String[] keyValueArray = query.getQuery().split("&");
                Map<String, String> kvp = new HashMap<String, String>();
                for (String keyValue : keyValueArray) {
                  String[] skv = keyValue.split("=");
                  kvp.put(skv[0], skv[1]);
                }

                // check the vendor params actually made it into the url
                assertEquals("true", kvp.get("strict"));
                assertEquals("mysecret", kvp.get("authkey"));
                assertEquals("low%3A2000000%3Bhigh%3A5000000", kvp.get("viewparams"));

                return super.getConnection(query, method);
              }
            };
          }
        };

    Map<String, String> vparams = new HashMap<String, String>();
    vparams.put("authkey", "mysecret");
    vparams.put("viewparams", "low:2000000;high:5000000");
    vparams.put("strict", "true");
    Hints hints = new Hints(WFSDataStore.WFS_VENDOR_PARAMETERS, vparams);
    Query q = new Query("topp:states");
    q.setHints(hints);

    // try with
    FeatureReader fr = wfs.getFeatureReader(q, Transaction.AUTO_COMMIT);
    assertTrue(fr.hasNext());
    fr.close();
  }
  @Test
  public void testTypes() throws IOException, NoSuchElementException {
    if (url == null) return;
    WFS_1_0_0_DataStore wfs;
    try {
      wfs = WFSDataStoreReadTest.getDataStore(url);
    } catch (ConnectException e) {
      e.printStackTrace(System.err);
      return;
    } catch (UnknownHostException e) {
      e.printStackTrace(System.err);
      return;
    } catch (NoRouteToHostException e) {
      e.printStackTrace(System.err);
      return;
    }
    String types[] = wfs.getTypeNames();
    String typeName = "unknown";
    for (int i = 0; i < types.length; i++) {
      typeName = types[i];
      if (typeName.equals("topp:geometrytype")) continue;
      SimpleFeatureType type = wfs.getSchema(typeName);
      type.getTypeName();
      type.getName().getNamespaceURI();

      SimpleFeatureSource source = wfs.getFeatureSource(typeName);
      source.getBounds();

      SimpleFeatureCollection features = source.getFeatures();
      features.getBounds();
      features.getSchema();
      // features.getFeatureType();

      Query query = new Query(typeName, Filter.INCLUDE, 20, Query.ALL_NAMES, "work already");
      features = source.getFeatures(query);
      features.size();
      SimpleFeatureIterator iterator = features.features();
      try {
        while (iterator.hasNext()) {
          SimpleFeature feature = (SimpleFeature) iterator.next();
        }
      } finally {
        iterator.close();
      }
    }
  }
  @Test
  public void testSingleType() throws IOException, NoSuchElementException {
    if (url == null) return;
    WFS_1_0_0_DataStore wfs;
    try {
      wfs = WFSDataStoreReadTest.getDataStore(url);
    } catch (ConnectException e) {
      e.printStackTrace(System.err);
      return;
    } catch (UnknownHostException e) {
      e.printStackTrace(System.err);
      return;
    } catch (NoRouteToHostException e) {
      e.printStackTrace(System.err);
      return;
    }
    String typeName = "tiger:poi";
    SimpleFeatureType type = wfs.getSchema(typeName);
    type.getTypeName();
    type.getName().getNamespaceURI();

    SimpleFeatureSource source = wfs.getFeatureSource(typeName);
    source.getBounds();

    SimpleFeatureCollection features = source.getFeatures();
    features.getBounds();
    features.getSchema();
    // features.getFeatureType();

    Query query = new Query(typeName, Filter.INCLUDE, 20, Query.ALL_NAMES, "work already");
    features = source.getFeatures(query);
    features.size();

    SimpleFeatureIterator iterator = features.features();
    while (iterator.hasNext()) {
      SimpleFeature feature = iterator.next();
    }
    iterator.close();
  }
  @Test
  public void testSimplifyFilter() throws Exception {
    if (url == null) return;
    Map m = new HashMap();
    m.put(WFSDataStoreFactory.URL.key, url);
    m.put(WFSDataStoreFactory.TIMEOUT.key, new Integer(100000));
    WFS_1_0_0_DataStore wfs = (WFS_1_0_0_DataStore) (new WFSDataStoreFactory()).createDataStore(m);
    FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());

    WFSFeatureSource fs = wfs.getFeatureSource("topp:states");

    // build a filter with bits that cannot be encoded in OGC filter, but can be simplified
    // to one that can
    Filter f =
        ff.or(
            Arrays.asList(
                Filter.EXCLUDE,
                ff.and(Filter.INCLUDE, ff.greater(ff.property("PERSONS"), ff.literal(10000000)))));
    SimpleFeatureCollection fc = fs.getFeatures(f);

    // force calling a HITS query, it used to throw an exception
    int size = fc.size();

    // force making a GetFeature, it used to blow up
    SimpleFeatureIterator fi = null;
    try {
      fi = fc.features();
      if (fi.hasNext()) {
        fi.next();
      }
    } finally {
      if (fi != null) {
        fi.close();
      }
    }
  }
  /** {@link BBOX} support? */
  @Test
  public void testDataStoreSupportsPlainBBOXInterface() throws Exception {
    if (url == null) return;
    final WFS_1_0_0_DataStore wfs = WFSDataStoreReadTest.getDataStore(url);
    final SimpleFeatureType ft = wfs.getSchema(TO_EDIT_TYPE);
    final ReferencedEnvelope bounds = wfs.getFeatureSource(TO_EDIT_TYPE).getBounds();

    final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
    final BBOX bbox =
        ff.bbox(
            "the_geom",
            bounds.getMinX(),
            bounds.getMinY(),
            bounds.getMaxX(),
            bounds.getMaxY(),
            null);

    /** This one does not implement the deprecated geotools filter interfaces */
    final BBOX strictBBox =
        new BBOX() {

          public boolean evaluate(Object object) {
            return bbox.evaluate(object);
          }

          public Object accept(FilterVisitor visitor, Object extraData) {
            return bbox.accept(visitor, extraData);
          }

          public Expression getExpression2() {
            return bbox.getExpression2();
          }

          public Expression getExpression1() {
            return bbox.getExpression1();
          }

          public String getSRS() {
            return bbox.getSRS();
          }

          public String getPropertyName() {
            return bbox.getPropertyName();
          }

          public double getMinY() {
            return bbox.getMinY();
          }

          public double getMinX() {
            return bbox.getMinX();
          }

          public double getMaxY() {
            return bbox.getMaxY();
          }

          public double getMaxX() {
            return bbox.getMaxX();
          }

          public MatchAction getMatchAction() {
            return MatchAction.ANY;
          }

          public BoundingBox getBounds() {
            return bbox.getBounds();
          }
        };

    final Query query = new Query(ft.getTypeName());
    query.setFilter(strictBBox);

    FeatureReader<SimpleFeatureType, SimpleFeature> reader;

    reader = wfs.getFeatureReaderGet(query, Transaction.AUTO_COMMIT);
    assertNotNull(reader);

    reader = wfs.getFeatureReaderPost(query, Transaction.AUTO_COMMIT);
    assertNotNull(reader);
  }