/**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testPoint2()
      throws XMLStreamException, FactoryConfigurationError, IOException, TransformationException,
          UnknownCRSException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + POINT2_FILE));
    xmlReader.nextTag();
    Point point = new GML2GeometryReader().parsePoint(xmlReader, null);
    Assert.assertEquals(5.0, point.get0(), DELTA);
    Assert.assertEquals(30.0, point.get1(), DELTA);

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");

    exporter.export(point);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
 private XMLStreamReaderWrapper getReader(String fileName)
     throws XMLStreamException, FactoryConfigurationError, IOException {
   XMLStreamReaderWrapper xmlReader =
       new XMLStreamReaderWrapper(
           GML3CurveSegmentReaderTest.class.getResource(
               "../../geometry/gml/testdata/segments/" + fileName));
   xmlReader.nextTag();
   return xmlReader;
 }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testMultiGeometry()
      throws XMLStreamException, FactoryConfigurationError, IOException, TransformationException,
          UnknownCRSException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + MULTIGEOMETRY_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "MultiGeometry"), xmlReader.getName());

    MultiGeometry<?> multiGeometry = new GML2GeometryReader().parseMultiGeometry(xmlReader, null);
    assertEquals("c731", multiGeometry.getId());

    Point firstMember = (Point) multiGeometry.get(0);
    assertEquals("P6776", firstMember.getId());
    comparePoint(50.0, 50.0, firstMember);

    LineString secondMember = (LineString) multiGeometry.get(1);
    assertEquals("L21216", secondMember.getId());

    Points controlPoints = secondMember.getControlPoints();
    comparePoint(0.0, 0.0, controlPoints.get(0));
    comparePoint(0.0, 50.0, controlPoints.get(1));
    comparePoint(100.0, 50.0, controlPoints.get(2));

    Polygon thirdMember = (Polygon) multiGeometry.get(2);
    assertEquals("_877789", thirdMember.getId());

    Points points = thirdMember.getExteriorRing().getControlPoints();
    comparePoint(0.0, 0.0, points.get(0));
    comparePoint(100.0, 0.0, points.get(1));
    comparePoint(50.0, 100.0, points.get(2));
    comparePoint(0.0, 0.0, points.get(3));

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");
    writer.setPrefix("xlink", "http://www.w3.org/1999/xlink");

    exporter.export(multiGeometry);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testMultiLineString()
      throws XMLStreamException, FactoryConfigurationError, IOException, TransformationException,
          UnknownCRSException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + MULTILINESTRING_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "MultiLineString"), xmlReader.getName());

    MultiLineString multiLineString =
        new GML2GeometryReader().parseMultiLineString(xmlReader, null);
    LineString firstMember = multiLineString.get(0);

    Points controlPoints = firstMember.getControlPoints();
    comparePoint(56.1, 0.45, controlPoints.get(0));
    comparePoint(67.23, 0.98, controlPoints.get(1));

    LineString secondMember = multiLineString.get(1);

    controlPoints = secondMember.getControlPoints();
    comparePoint(46.71, 9.25, controlPoints.get(0));
    comparePoint(56.88, 10.44, controlPoints.get(1));

    LineString thirdMember = multiLineString.get(2);

    controlPoints = thirdMember.getControlPoints();
    comparePoint(324.1, 219.7, controlPoints.get(0));
    comparePoint(0.45, 4.56, controlPoints.get(1));

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");
    writer.setPrefix("xlink", "http://www.w3.org/1999/xlink");

    exporter.export(multiLineString);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * Parses the feature id attribute from the feature <code>START_ELEMENT</code> event that the
   * given <code>XMLStreamReader</code> points to.
   *
   * <p>Looks after 'gml:id' (GML 3) first, if no such attribute is present, the 'fid' (GML 2)
   * attribute is used.
   *
   * @param xmlReader must point to the <code>START_ELEMENT</code> event of the feature
   * @return the feature id, or "" (empty string) if neither a 'gml:id' nor a 'fid' attribute is
   *     present
   */
  protected String parseFeatureId(XMLStreamReaderWrapper xmlReader) {

    String fid = xmlReader.getAttributeValue(gmlNs, GMLID);
    if (fid == null) {
      fid = xmlReader.getAttributeValue(null, FID);
    }

    // Check that the feature id has the correct form. "fid" and "gml:id" are both based
    // on the XML type "ID": http://www.w3.org/TR/xmlschema11-2/#NCName
    // Thus, they must match the NCName production rule. This means that they may not contain
    // a separating colon (only at the first position a colon is allowed) and must not
    // start with a digit.
    if (fid != null && fid.length() > 0 && !fid.matches("[^\\d][^:]+")) {
      String msg = Messages.getMessage("ERROR_INVALID_FEATUREID", fid);
      throw new IllegalArgumentException(msg);
    }
    return fid;
  }
  private ApplicationSchema buildApplicationSchema(XMLStreamReaderWrapper xmlStream)
      throws XMLParsingException {
    String schemaLocation = xmlStream.getAttributeValue(XSINS, "schemaLocation");
    if (schemaLocation == null) {
      throw new XMLParsingException(
          xmlStream, Messages.getMessage("ERROR_NO_SCHEMA_LOCATION", xmlStream.getSystemId()));
    }

    String[] tokens = schemaLocation.trim().split("\\s+");
    if (tokens.length % 2 != 0) {
      throw new XMLParsingException(
          xmlStream,
          Messages.getMessage("ERROR_SCHEMA_LOCATION_TOKENS_COUNT", xmlStream.getSystemId()));
    }
    String[] schemaUrls = new String[tokens.length / 2];
    for (int i = 0; i < schemaUrls.length; i++) {
      String schemaUrl = tokens[i * 2 + 1];
      try {
        schemaUrls[i] = new URL(new URL(xmlStream.getSystemId()), schemaUrl).toString();
      } catch (MalformedURLException e) {
        throw new XMLParsingException(
            xmlStream, "Error parsing application schema: " + e.getMessage());
      }
    }

    // TODO handle multi-namespace schemas
    ApplicationSchema schema = null;
    try {
      ApplicationSchemaXSDDecoder decoder =
          new ApplicationSchemaXSDDecoder(version, null, schemaUrls);
      schema = decoder.extractFeatureTypeSchema();
    } catch (Exception e) {
      e.printStackTrace();
      throw new XMLParsingException(
          xmlStream, "Error parsing application schema: " + e.getMessage());
    }
    return schema;
  }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testPolygon()
      throws XMLStreamException, FactoryConfigurationError, IOException, UnknownCRSException,
          TransformationException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + POLYGON_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Polygon"), xmlReader.getName());

    Polygon polygon = new GML2GeometryReader().parsePolygon(xmlReader, null);
    Assert.assertEquals(XMLStreamConstants.END_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Polygon"), xmlReader.getName());

    Points points = polygon.getExteriorRing().getControlPoints();
    comparePoint(0.0, 0.0, points.get(0));
    comparePoint(100.0, 0.0, points.get(1));
    comparePoint(100.0, 100.0, points.get(2));
    comparePoint(0.0, 100.0, points.get(3));
    comparePoint(0.0, 0.0, points.get(4));

    List<Points> innerPoints = polygon.getInteriorRingsCoordinates();
    Points points1 = innerPoints.get(0);
    comparePoint(10.0, 10.0, points1.get(0));
    comparePoint(10.0, 40.0, points1.get(1));
    comparePoint(40.0, 40.0, points1.get(2));
    comparePoint(40.0, 10.0, points1.get(3));
    comparePoint(10.0, 10.0, points1.get(4));

    Points points2 = innerPoints.get(1);
    comparePoint(60.0, 60.0, points2.get(0));
    comparePoint(60.0, 90.0, points2.get(1));
    comparePoint(90.0, 90.0, points2.get(2));
    comparePoint(90.0, 60.0, points2.get(3));
    comparePoint(60.0, 60.0, points2.get(4));

    Assert.assertEquals(
        CRSRegistry.lookup("http://www.opengis.net/gml/srs/epsg.xml#4326"),
        polygon.getCoordinateSystem().getWrappedCRS());

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");
    writer.setPrefix("xlink", "http://www.w3.org/1999/xlink");

    exporter.export(polygon);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testMultiPoint()
      throws XMLStreamException, FactoryConfigurationError, IOException, TransformationException,
          UnknownCRSException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + MULTIPOINT_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "MultiPoint"), xmlReader.getName());

    MultiPoint multiPoint = new GML2GeometryReader().parseMultiPoint(xmlReader, null);

    Point firstMember = multiPoint.get(0);
    comparePoint(5.0, 40.0, firstMember);

    Point secondMember = multiPoint.get(1);
    comparePoint(0.0, 0.0, secondMember);

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");
    writer.setPrefix("xlink", "http://www.w3.org/1999/xlink");

    exporter.export(multiPoint);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testBox()
      throws XMLStreamException, FactoryConfigurationError, IOException, UnknownCRSException,
          TransformationException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + BOX_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Box"), xmlReader.getName());

    Envelope envelope = new GML2GeometryReader().parseEnvelope(xmlReader, null);
    Assert.assertEquals(XMLStreamConstants.END_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Box"), xmlReader.getName());
    Assert.assertEquals(0.0, envelope.getMin().get0(), DELTA);
    Assert.assertEquals(0.0, envelope.getMin().get1(), DELTA);
    Assert.assertEquals(100.0, envelope.getMax().get0(), DELTA);
    Assert.assertEquals(100.0, envelope.getMax().get1(), DELTA);
    Assert.assertEquals(
        CRSRegistry.lookup("http://www.opengis.net/gml/srs/epsg.xml#4326"),
        envelope.getCoordinateSystem().getWrappedCRS());

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    // writer.setPrefix( "app", "http://www.deegree.org" );
    // writer.setPrefix( "app", "http://www.deegree.org/app" );
    writer.setPrefix("gml", "http://www.opengis.net/gml");
    // writer.setPrefix( "ogc", "http://www.opengis.net/ogc" );
    // writer.setPrefix( "wfs", "http://www.opengis.net/wfs" );
    // writer.setPrefix( "xlink", "http://www.w3.org/1999/xlink" );
    // writer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );

    exporter.export(envelope);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * @throws XMLStreamException
   * @throws FactoryConfigurationError
   * @throws IOException
   * @throws UnknownCRSException
   * @throws TransformationException
   */
  @Test
  public void testPoint()
      throws XMLStreamException, FactoryConfigurationError, IOException, UnknownCRSException,
          TransformationException {
    XMLStreamReaderWrapper xmlReader =
        new XMLStreamReaderWrapper(this.getClass().getResource(BASE_DIR + POINT_FILE));
    xmlReader.nextTag();

    Assert.assertEquals(XMLStreamConstants.START_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Point"), xmlReader.getName());

    Point point = new GML2GeometryReader().parsePoint(xmlReader, null);
    Assert.assertEquals(XMLStreamConstants.END_ELEMENT, xmlReader.getEventType());
    Assert.assertEquals(new QName(GML21NS, "Point"), xmlReader.getName());
    Assert.assertEquals(5.0, point.get0(), DELTA);
    Assert.assertEquals(40.0, point.get1(), DELTA);
    Assert.assertEquals(
        CRSRegistry.lookup("http://www.opengis.net/gml/srs/epsg.xml#4326"),
        point.getCoordinateSystem().getWrappedCRS());

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true));
    XMLMemoryStreamWriter memoryWriter = new XMLMemoryStreamWriter();

    SchemaLocationXMLStreamWriter writer =
        new SchemaLocationXMLStreamWriter(
            memoryWriter.getXMLStreamWriter(), SCHEMA_LOCATION_ATTRIBUTE);
    GML2GeometryWriter exporter = new GML2GeometryWriter(writer, null, null, new HashSet<String>());

    writer.setPrefix("gml", "http://www.opengis.net/gml");

    exporter.export(point);
    writer.flush();

    XMLAssert.assertValidity(memoryWriter.getReader(), SCHEMA_LOCATION);
  }
  /**
   * Returns the object representation for the given property element.
   *
   * @param xmlStream cursor must point at the <code>START_ELEMENT</code> event of the property,
   *     afterwards points at the next event after the <code>END_ELEMENT</code> of the property
   * @param propDecl property declaration
   * @param crs default SRS for all a descendant geometry properties
   * @param occurence
   * @return object representation for the given property element.
   * @throws XMLParsingException
   * @throws XMLStreamException
   * @throws UnknownCRSException
   */
  public Property<?> parseProperty(
      XMLStreamReaderWrapper xmlStream, PropertyType propDecl, CRS crs, int occurence)
      throws XMLParsingException, XMLStreamException, UnknownCRSException {

    Property<?> property = null;
    QName propName = xmlStream.getName();
    LOG.debug("- parsing property (begin): " + xmlStream.getCurrentEventInfo());
    LOG.debug("- property declaration: " + propDecl);

    CustomPropertyReader<?> parser = ptToParser.get(propDecl);

    if (parser == null) {
      if (propDecl instanceof SimplePropertyType) {
        property =
            createSimpleProperty(
                xmlStream, (SimplePropertyType) propDecl, xmlStream.getElementText().trim());
      } else if (propDecl instanceof GeometryPropertyType) {
        String href = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href");
        if (href != null) {
          // TODO respect geometry type information (Point, Surface, etc.)
          GeometryReference<Geometry> refGeometry = null;
          if (specialResolver != null) {
            refGeometry =
                new GeometryReference<Geometry>(specialResolver, href, xmlStream.getSystemId());
          } else {
            refGeometry = new GeometryReference<Geometry>(idContext, href, xmlStream.getSystemId());
          }
          idContext.addReference(refGeometry);
          property = new GenericProperty<Geometry>(propDecl, propName, refGeometry);
          xmlStream.nextTag();
        } else {
          xmlStream.nextTag();
          Geometry geometry = null;
          geometry = geomReader.parse(xmlStream, crs);
          property = new GenericProperty<Geometry>(propDecl, propName, geometry);
          xmlStream.nextTag();
        }
      } else if (propDecl instanceof FeaturePropertyType) {
        String uri = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href");
        if (uri != null) {
          FeatureReference refFeature = null;
          if (specialResolver != null) {
            refFeature = new FeatureReference(specialResolver, uri, xmlStream.getSystemId());
          } else {
            refFeature = new FeatureReference(idContext, uri, xmlStream.getSystemId());
          }
          idContext.addReference(refFeature);
          property = new GenericProperty<Feature>(propDecl, propName, refFeature);
          xmlStream.nextTag();
        } else {
          // inline feature
          if (xmlStream.nextTag() != START_ELEMENT) {
            String msg = Messages.getMessage("ERROR_INVALID_FEATURE_PROPERTY", propName);
            throw new XMLParsingException(xmlStream, msg);
          }
          // TODO make this check (no constraints on contained feature type) better
          if (((FeaturePropertyType) propDecl).getFTName() != null) {
            FeatureType expectedFt = ((FeaturePropertyType) propDecl).getValueFt();
            FeatureType presentFt = lookupFeatureType(xmlStream, xmlStream.getName());
            if (!schema.isSubType(expectedFt, presentFt)) {
              String msg =
                  Messages.getMessage(
                      "ERROR_PROPERTY_WRONG_FEATURE_TYPE",
                      expectedFt.getName(),
                      propName,
                      presentFt.getName());
              throw new XMLParsingException(xmlStream, msg);
            }
          }
          Feature subFeature = parseFeature(xmlStream, crs);
          property = new GenericProperty<Feature>(propDecl, propName, subFeature);
          xmlStream.skipElement();
        }
      } else if (propDecl instanceof CustomPropertyType) {
        Object value = new GenericCustomPropertyReader().parse(xmlStream);
        property = new GenericProperty<Object>(propDecl, propName, value);
      } else if (propDecl instanceof EnvelopePropertyType) {
        Envelope env = null;
        xmlStream.nextTag();
        if (xmlStream.getName().equals(new QName(gmlNs, "Null"))) {
          // TODO
          StAXParsingHelper.skipElement(xmlStream);
        } else {
          env = geomReader.parseEnvelope(xmlStream, crs);
          property = new GenericProperty<Object>(propDecl, propName, env);
        }
        xmlStream.nextTag();
      } else if (propDecl instanceof CodePropertyType) {
        String codeSpace = xmlStream.getAttributeValue(null, "codeSpace");
        String code = xmlStream.getElementText().trim();
        Object value = new CodeType(code, codeSpace);
        property = new GenericProperty<Object>(propDecl, propName, value);
      } else if (propDecl instanceof MeasurePropertyType) {
        String uom = xmlStream.getAttributeValue(null, "uom");
        Object value = new Measure(xmlStream.getElementText(), uom);
        property = new GenericProperty<Object>(propDecl, propName, value);
      } else if (propDecl instanceof StringOrRefPropertyType) {
        String ref = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href");
        String string = xmlStream.getElementText().trim();
        property = new GenericProperty<Object>(propDecl, propName, new StringOrRef(string, ref));
      }
    } else {
      LOG.trace("************ Parsing property using custom parser.");
      Object value = parser.parse(xmlStream);
      property = new GenericProperty<Object>(propDecl, propName, value);
    }

    LOG.debug(" - parsing property (end): " + xmlStream.getCurrentEventInfo());
    return property;
  }
  /**
   * Returns the object representation for the feature (or feature collection) element event that
   * the cursor of the given <code>XMLStreamReader</code> points at.
   *
   * @param xmlStream cursor must point at the <code>START_ELEMENT</code> event of the feature
   *     element, afterwards points at the next event after the <code>END_ELEMENT</code> event of
   *     the feature element
   * @param crs default CRS for all descendant geometry properties
   * @return object representation for the given feature element
   * @throws XMLStreamException
   * @throws UnknownCRSException
   * @throws XMLParsingException
   */
  public Feature parseFeature(XMLStreamReaderWrapper xmlStream, CRS crs)
      throws XMLStreamException, XMLParsingException, UnknownCRSException {

    if (schema == null) {
      schema = buildApplicationSchema(xmlStream);
    }

    Feature feature = null;
    String fid = parseFeatureId(xmlStream);

    QName featureName = xmlStream.getName();
    FeatureType ft = lookupFeatureType(xmlStream, featureName);

    LOG.debug("- parsing feature, gml:id=" + fid + " (begin): " + xmlStream.getCurrentEventInfo());

    // parse properties
    Iterator<PropertyType<?>> declIter = ft.getPropertyDeclarations(version).iterator();

    PropertyType activeDecl = declIter.next();
    int propOccurences = 0;

    CRS activeCRS = crs;
    List<Property<?>> propertyList = new ArrayList<Property<?>>();

    xmlStream.nextTag();

    while (xmlStream.getEventType() == START_ELEMENT) {

      QName propName = xmlStream.getName();

      LOG.debug("- property '" + propName + "'");

      if (findConcretePropertyType(propName, activeDecl) != null) {
        // current property element is equal to active declaration
        if (activeDecl.getMaxOccurs() != -1 && propOccurences > activeDecl.getMaxOccurs()) {
          String msg =
              Messages.getMessage(
                  "ERROR_PROPERTY_TOO_MANY_OCCURENCES",
                  propName,
                  activeDecl.getMaxOccurs(),
                  ft.getName());
          throw new XMLParsingException(xmlStream, msg);
        }
      } else {
        // current property element is not equal to active declaration
        while (declIter.hasNext() && findConcretePropertyType(propName, activeDecl) == null) {
          if (propOccurences < activeDecl.getMinOccurs()) {
            String msg = null;
            if (activeDecl.getMinOccurs() == 1) {
              msg =
                  Messages.getMessage(
                      "ERROR_PROPERTY_MANDATORY", activeDecl.getName(), ft.getName());
            } else {
              msg =
                  Messages.getMessage(
                      "ERROR_PROPERTY_TOO_FEW_OCCURENCES",
                      activeDecl.getName(),
                      activeDecl.getMinOccurs(),
                      ft.getName());
            }
            throw new XMLParsingException(xmlStream, msg);
          }
          activeDecl = declIter.next();
          propOccurences = 0;
        }
        if (findConcretePropertyType(propName, activeDecl) == null) {
          String msg = Messages.getMessage("ERROR_PROPERTY_UNEXPECTED", propName, ft.getName());
          throw new XMLParsingException(xmlStream, msg);
        }
      }

      Property<?> property =
          parseProperty(
              xmlStream, findConcretePropertyType(propName, activeDecl), activeCRS, propOccurences);
      if (property != null) {
        // if this is the "gml:boundedBy" property, override active CRS (see GML spec. (where???))
        if (StandardGMLFeatureProps.PT_BOUNDED_BY_GML31.getName().equals(activeDecl.getName())) {
          Envelope bbox = (Envelope) property.getValue();
          if (bbox.getCoordinateSystem() != null) {
            activeCRS = bbox.getCoordinateSystem();
            LOG.debug("- crs (from boundedBy): '" + activeCRS + "'");
          }
        }

        propertyList.add(property);
      }
      propOccurences++;
      xmlStream.nextTag();
    }
    LOG.debug(" - parsing feature (end): " + xmlStream.getCurrentEventInfo());

    feature = ft.newFeature(fid, propertyList, version);

    if (fid != null && !"".equals(fid)) {
      if (idContext.getObject(fid) != null) {
        String msg = Messages.getMessage("ERROR_FEATURE_ID_NOT_UNIQUE", fid);
        throw new XMLParsingException(xmlStream, msg);
      }
      idContext.addObject(feature);
    }
    return feature;
  }
Example #13
0
  @SuppressWarnings("boxing")
  private static GetFeature parse110(Map<String, String> kvpParams) throws Exception {

    StandardPresentationParams presentationParams =
        parseStandardPresentationParameters110(kvpParams);
    ResolveParams resolveParams = parseStandardResolveParameters110(kvpParams);

    // optional: 'NAMESPACE'
    Map<String, String> nsBindings = extractNamespaceBindings110(kvpParams);
    if (nsBindings == null) {
      nsBindings = Collections.emptyMap();
    }

    NamespaceBindings nsContext = new NamespaceBindings();
    if (nsBindings != null) {
      for (String key : nsBindings.keySet()) {
        nsContext.addNamespace(key, nsBindings.get(key));
      }
    }

    // optional: SRSNAME
    String srsName = kvpParams.get("SRSNAME");
    ICRS srs = null;
    if (srsName != null) {
      srs = CRSManager.getCRSRef(srsName);
    }

    // optional: 'PROPERTYNAME'
    String propertyStr = kvpParams.get("PROPERTYNAME");
    PropertyName[][] propertyNames = getPropertyNames(propertyStr, nsContext);

    // optional: SORTBY
    String sortbyStr = kvpParams.get("SORTBY");
    SortProperty[] sortBy = getSortBy(sortbyStr, nsContext);

    // optional: FEATUREVERSION
    String featureVersion = kvpParams.get("FEATUREVERSION");

    // mandatory: TYPENAME, but optional if FEATUREID is specified
    String typeStrList = kvpParams.get("TYPENAME");
    TypeName[] typeNames = getTypeNames(typeStrList, nsBindings);

    // optional: FEATUREID
    String featureIdStr = kvpParams.get("FEATUREID");
    String[] featureIds = null;
    if (featureIdStr != null) {
      featureIds = featureIdStr.split(",");
    }
    // optional: BBOX
    String bboxStr = kvpParams.get("BBOX");

    // optional: FILTER
    String filterStr = kvpParams.get("FILTER");

    // optional: 'PROPTRAVXLINKDEPTH'
    String propTravXlinkDepth = kvpParams.get("PROPTRAVXLINKDEPTH");
    String[][] ptxDepthAr = null;
    if (propTravXlinkDepth != null) {
      ptxDepthAr = parseParamList(propTravXlinkDepth);
    }

    // optional: 'PROPTRAVXLINKEXPIRY'
    String propTravXlinkExpiry = kvpParams.get("PROPTRAVXLINKEXPIRY");
    Integer[][] ptxExpAr = null;
    if (propTravXlinkExpiry != null) {
      ptxExpAr = parseParamListAsInts(propTravXlinkDepth);
    }

    propertyNames = getXLinkPropNames(propertyNames, ptxDepthAr, ptxExpAr);
    List<Query> queries = new ArrayList<Query>();

    if ((featureIdStr != null && bboxStr != null)
        || (featureIdStr != null && filterStr != null)
        || (bboxStr != null && filterStr != null)) {
      // TODO make new exception
      throw new Exception("The FEATUREID, BBOX and FILTER keywords are mutually exclusive!");
    }

    if (featureIdStr != null) {
      if (typeStrList == null && propertyNames == null) {
        queries.add(new FeatureIdQuery(null, null, featureVersion, srs, null, sortBy, featureIds));
      } else {
        for (int i = 0; i < featureIds.length; i++) {
          String[] fid = new String[] {featureIds[i]};
          TypeName[] typeName = new TypeName[0];
          if (typeStrList != null) {
            typeName = new TypeName[] {typeNames[i]};
          }
          PropertyName[] projectionClauses = null;
          if (propertyNames != null) {
            projectionClauses = propertyNames[i];
          }
          queries.add(
              new FeatureIdQuery(
                  null, typeName, featureVersion, srs, projectionClauses, sortBy, fid));
        }
      }
    } else if (bboxStr != null) {
      if (typeNames == null) {
        // TODO make new exception
        throw new Exception("The TYPENAME keyword is mandatory if BBOX is present!");
      }

      String[] coordList = bboxStr.split(",");

      // NOTE: Contradiction between spec and CITE tests (for omitted crsUri)
      // - WFS 1.1.0 spec, 14.3.3: coordinates should be in WGS84
      // - CITE tests, wfs:wfs-1.1.0-Basic-GetFeature-tc8.1: If no CRS reference is provided, a
      // service-defined
      // default value must be assumed.
      ICRS bboxCrs = null;
      if (coordList.length % 2 == 1) {
        bboxCrs = CRSManager.getCRSRef(coordList[coordList.length - 1]);
      }

      Envelope bbox = createEnvelope(bboxStr, bboxCrs);
      for (int i = 0; i < typeNames.length; i++) {
        TypeName typeName = typeNames[i];
        PropertyName[] projectionClauses = null;
        if (propertyNames != null) {
          projectionClauses = propertyNames[i];
        }
        queries.add(
            new BBoxQuery(
                null,
                new TypeName[] {typeName},
                featureVersion,
                srs,
                projectionClauses,
                sortBy,
                bbox));
      }
    } else if (filterStr != null || typeNames != null) {
      if (typeNames == null) {
        // TODO make new exception
        throw new Exception("The FILTER element requires the TYPENAME element");
      }

      int length = typeNames.length;

      String[] filters = getFilters(filterStr);

      for (int i = 0; i < length; i++) {
        Filter filter = null;
        if (filters != null) {

          StringReader sr = new StringReader(filters[i]);
          XMLAdapter adapter = new XMLAdapter(sr);
          XMLStreamReaderWrapper streamWrapper =
              new XMLStreamReaderWrapper(
                  adapter.getRootElement().getXMLStreamReaderWithoutCaching(),
                  adapter.getSystemId());
          try {
            streamWrapper.nextTag();
            filter = Filter110XMLDecoder.parse(streamWrapper);
          } catch (XMLParsingException e) {
            e.printStackTrace();
            // TODO raise exception
          } catch (XMLStreamException e) {
            e.printStackTrace();
            // TODO raise exception
          }
        }
        if (propertyNames != null) {
          queries.add(
              new FilterQuery(
                  null,
                  new TypeName[] {typeNames[i]},
                  featureVersion,
                  srs,
                  propertyNames[i],
                  sortBy,
                  filter));
        } else {
          queries.add(
              new FilterQuery(
                  null, new TypeName[] {typeNames[i]}, featureVersion, srs, null, sortBy, filter));
        }
      }
    }
    return new GetFeature(VERSION_110, null, presentationParams, resolveParams, queries);
  }
Example #14
0
  @SuppressWarnings("boxing")
  private static GetFeature parse100(Map<String, String> kvpParams, Map<String, String> nsMap)
      throws Exception {

    NamespaceBindings nsContext = new NamespaceBindings();
    if (nsMap != null) {
      for (String key : nsMap.keySet()) {
        nsContext.addNamespace(key, nsMap.get(key));
      }
    }

    StandardPresentationParams presentationParams =
        parseStandardPresentationParameters100(kvpParams);

    // optional: 'PROPERTYNAME'
    String propertyStr = kvpParams.get("PROPERTYNAME");
    PropertyName[][] propertyNames = getPropertyNames(propertyStr, nsContext);

    // optional: FEATUREVERSION
    String featureVersion = kvpParams.get("FEATUREVERSION");

    // mandatory: TYPENAME, but optional if FEATUREID is specified
    String typeStrList = kvpParams.get("TYPENAME");
    TypeName[] typeNames = getTypeNames100(typeStrList);

    // optional: FEATUREID
    String featureIdStr = kvpParams.get("FEATUREID");
    String[] featureIds = null;
    if (featureIdStr != null) {
      featureIds = featureIdStr.split(",");
    }
    // optional: BBOX
    String bboxStr = kvpParams.get("BBOX");

    // optional: FILTER
    String filterStr = kvpParams.get("FILTER");

    // optional: SRSNAME (not specified in WFS 1.0.0, deegree extension)
    String srsName = kvpParams.get("SRSNAME");
    ICRS srs = null;
    if (srsName != null) {
      srs = CRSManager.getCRSRef(srsName);
    }

    List<Query> queries = new ArrayList<Query>();

    if ((featureIdStr != null && bboxStr != null)
        || (featureIdStr != null && filterStr != null)
        || (bboxStr != null && filterStr != null)) {
      // TODO make new exception
      throw new Exception("The FEATUREID, BBOX and FILTER keywords are mutually exclusive!");
    }

    if (featureIdStr != null) {
      if (typeStrList == null && propertyNames == null) {
        queries.add(new FeatureIdQuery(null, null, featureVersion, srs, null, null, featureIds));
      } else {
        for (int i = 0; i < featureIds.length; i++) {
          String[] fids = new String[] {featureIds[i]};
          TypeName[] typeName = new TypeName[0];
          if (typeStrList != null) {
            typeName = new TypeName[] {typeNames[i]};
          }
          PropertyName[] projectionClauses = null;
          if (propertyNames != null) {
            if (propertyNames.length > 1) {
              projectionClauses = propertyNames[i];
            } else {
              projectionClauses = propertyNames[0];
            }
          }
          queries.add(
              new FeatureIdQuery(
                  null, typeName, featureVersion, srs, projectionClauses, null, fids));
        }
      }
    } else if (bboxStr != null) {
      if (typeNames == null) {
        // TODO make new exception
        throw new Exception("The TYPENAME keyword is mandatory if BBOX is present!");
      }

      String[] coordList = bboxStr.split(",");
      ICRS bboxCrs = null;
      if (coordList.length % 2 == 1) {
        bboxCrs = CRSManager.getCRSRef(coordList[coordList.length - 1]);
      }

      Envelope bbox = createEnvelope(bboxStr, bboxCrs);
      for (int i = 0; i < typeNames.length; i++) {
        TypeName typeName = typeNames[i];
        PropertyName[] projectionClauses = null;
        if (propertyNames != null) {
          projectionClauses = propertyNames[i];
        }
        queries.add(
            new BBoxQuery(
                null,
                new TypeName[] {typeName},
                featureVersion,
                srs,
                projectionClauses,
                null,
                bbox));
      }
    } else if (filterStr != null || typeNames != null) {
      if (typeNames == null) {
        // TODO make new exception
        throw new Exception("The FILTER element requires the TYPENAME element");
      }

      int length = typeNames.length;

      String[] filters = getFilters(filterStr);

      for (int i = 0; i < length; i++) {
        Filter filter = null;
        if (filters != null) {

          StringReader sr = new StringReader(filters[i]);
          XMLAdapter adapter = new XMLAdapter(sr);
          XMLStreamReaderWrapper streamWrapper =
              new XMLStreamReaderWrapper(
                  adapter.getRootElement().getXMLStreamReaderWithoutCaching(),
                  adapter.getSystemId());
          try {
            streamWrapper.nextTag();
            filter = Filter100XMLDecoder.parse(streamWrapper);
          } catch (XMLParsingException e) {
            e.printStackTrace();
            // TODO raise exception
          } catch (XMLStreamException e) {
            e.printStackTrace();
            // TODO raise exception
          }
        }
        if (propertyNames != null) {
          queries.add(
              new FilterQuery(
                  null,
                  new TypeName[] {typeNames[i]},
                  featureVersion,
                  srs,
                  propertyNames[i],
                  null,
                  filter));
        } else {
          queries.add(
              new FilterQuery(
                  null, new TypeName[] {typeNames[i]}, featureVersion, srs, null, null, filter));
        }
      }
    }
    return new GetFeature(VERSION_100, null, presentationParams, null, queries);
  }