예제 #1
0
파일: Geo.java 프로젝트: runeengh/basex
  /**
   * Reads an element as a gml node. Returns a geometry element or {@code null} if the element does
   * not match one of the specified types.
   *
   * @param node xml node containing gml object(s)
   * @param names allowed geometry types
   * @return geometry, or {@code null}
   * @throws QueryException query exception
   */
  private static Geometry geo(final ANode node, final QNm... names) throws QueryException {
    if (node.type != NodeType.ELM) throw EXPTYPE_X_X_X.get(null, NodeType.ELM, node.type, node);

    final QNm qname = node.qname();
    for (final QNm geo : names) {
      if (!qname.eq(geo)) continue;
      // type found... create reader and geometry element
      try {
        final String input = node.serialize().toString();
        final GMLReader gmlReader = new GMLReader();
        final GeometryFactory geoFactory = new GeometryFactory();
        return gmlReader.read(input, geoFactory);
      } catch (final Throwable ex) {
        throw GeoErrors.gmlReaderErr(ex);
      }
    }
    return null;
  }
예제 #2
0
  /**
   * Parses a jar descriptor.
   *
   * @param io XML input
   * @return jar descriptor container
   * @throws QueryException query exception
   */
  public JarDesc parse(final IO io) throws QueryException {
    final JarDesc desc = new JarDesc();
    try {
      final ANode node = new DBNode(io).children().next();
      for (final ANode next : node.children()) {
        if (next.type != NodeType.ELM) continue;

        final QNm name = next.qname();
        // ignore namespace to improve compatibility
        if (eq(JAR, name.local())) desc.jars.add(next.string());
        else if (eq(CLASS, name.local())) desc.classes.add(next.string());
        // [CG] Packaging: add warning if unknown elements are encountered
      }
      if (desc.jars.isEmpty()) throw BXRE_JARDESC_X.get(info, NOJARS);
      else if (desc.classes.isEmpty()) throw BXRE_JARDESC_X.get(info, NOCLASSES);
      return desc;
    } catch (final IOException ex) {
      throw BXRE_JARFAIL_X.get(info, ex);
    }
  }
예제 #3
0
 /**
  * Returns a parameter.
  *
  * @param value value
  * @param name name
  * @param declared variable declaration flags
  * @return parameter
  * @throws QueryException HTTP exception
  */
 private RestXqParam param(final Value value, final QNm name, final boolean[] declared)
     throws QueryException {
   // [CG] RESTXQ: allow identical field names?
   final long vs = value.size();
   if (vs < 2) error(ANN_PARAMS, "%", name.string(), 2);
   // name of parameter
   final String key = toString(value.itemAt(0), name);
   // variable template
   final QNm qnm = checkVariable(toString(value.itemAt(1), name), declared);
   // default value
   final ValueBuilder vb = new ValueBuilder();
   for (int v = 2; v < vs; v++) vb.add(value.itemAt(v));
   return new RestXqParam(qnm, key, vb.value());
 }
예제 #4
0
파일: Geo.java 프로젝트: runeengh/basex
/**
 * This module contains geo spatial functions for the Geo module.
 *
 * @author BaseX Team 2005-14, BSD License
 * @author Masoumeh Seydi
 */
public final class Geo extends QueryModule {
  /** GML URI. */
  private static final byte[] URI = token("http://www.opengis.net/gml");
  /** Prefix: "gml". */
  private static final String GML = "gml";

  /** QName gml:Point. */
  private static final QNm Q_GML_POINT = QNm.get(GML, "Point", URI);
  /** QName gml:MultiPoint. */
  private static final QNm Q_GML_MULTIPOINT = QNm.get(GML, "MultiPoint", URI);
  /** QName gml:LineString. */
  private static final QNm Q_GML_LINESTRING = QNm.get(GML, "LineString", URI);
  /** QName gml:LinearRing. */
  private static final QNm Q_GML_LINEARRING = QNm.get(GML, "LinearRing", URI);
  /** QName gml:Polygon. */
  private static final QNm Q_GML_POLYGON = QNm.get(GML, "Polygon", URI);
  /** QName gml:MultiPolygon. */
  private static final QNm Q_GML_MULTIPOLYGON = QNm.get(GML, "MultiPolygon", URI);
  /** QName gml:MultiLineString. */
  private static final QNm Q_GML_MULTILINESTRING = QNm.get(GML, "MultiLineString", URI);

  /** Array containing all QNames. */
  private static final QNm[] QNAMES = {
    Q_GML_POINT,
    Q_GML_LINESTRING,
    Q_GML_POLYGON,
    Q_GML_MULTIPOINT,
    Q_GML_MULTILINESTRING,
    Q_GML_MULTIPOLYGON,
    Q_GML_LINEARRING
  };

  /**
   * Returns the dimension of an item.
   *
   * @param node xml element containing gml object(s)
   * @return dimension
   * @throws QueryException query exception
   */
  @Deterministic
  public Int dimension(final ANode node) throws QueryException {
    return Int.get(checkGeo(node).getDimension());
  }

  /**
   * Returns the name of the geometry type in the GML namespace, or the empty sequence.
   *
   * @param node xml element containing gml object(s)
   * @return geometry type
   * @throws QueryException query exception
   */
  @Deterministic
  public QNm geometryType(final ANode node) throws QueryException {
    return new QNm(GML + ':' + checkGeo(node).getGeometryType(), URI);
  }

  /**
   * Returns the name of the geometry type in the GML namespace, or the empty sequence.
   *
   * @param node xml element containing gml object(s)
   * @return integer value of CRS of the geometry
   * @throws QueryException query exception
   */
  @Deterministic
  public Uri srid(final ANode node) throws QueryException {
    return Uri.uri(token(checkGeo(node).getSRID()));
  }

  /**
   * Returns the gml:Envelope of the specified geometry. The envelope is the minimum bounding box of
   * this geometry.
   *
   * @param node xml element containing gml object(s)
   * @return envelop element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode envelope(final ANode node) throws QueryException {
    return gmlWriter(checkGeo(node).getEnvelope());
  }

  /**
   * Returns the WKT format of a geometry.
   *
   * @param node xml element containing gml object(s)
   * @return Well-Known Text geometry representation
   * @throws QueryException query exception
   */
  @Deterministic
  public Str asText(final ANode node) throws QueryException {
    return Str.get(new WKTWriter().write(checkGeo(node)));
  }

  /**
   * Returns the WKB format of a geometry.
   *
   * @param node xml element containing gml object(s)
   * @return Well-Known Binary geometry representation
   * @throws QueryException query exception
   */
  @Deterministic
  public B64 asBinary(final ANode node) throws QueryException {
    return new B64(new WKBWriter().write(checkGeo(node)));
  }

  /**
   * Returns a boolean value which shows if the specified geometry is empty or not.
   *
   * @param node xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln isEmpty(final ANode node) throws QueryException {
    return Bln.get(node != null && checkGeo(node) != null);
  }

  /**
   * Returns a boolean value which shows if the specified geometry is simple or not, which has no
   * anomalous geometric points, such as self intersection or self tangency.
   *
   * @param node xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln isSimple(final ANode node) throws QueryException {
    return Bln.get(checkGeo(node).isSimple());
  }

  /**
   * Returns the boundary of the geometry, in GML. The return value is a sequence of either
   * gml:Point or gml:LinearRing elements.
   *
   * @param node xml element containing gml object(s)
   * @return boundary element (geometry)
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode boundary(final ANode node) throws QueryException {
    return gmlWriter(checkGeo(node).getBoundary());
  }

  /**
   * Returns a boolean value that shows if two geometries are equal or not.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln equals(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.equals(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry is disjoint to another geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln disjoint(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.disjoint(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry intersects another geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln intersects(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.intersects(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry touches the specified geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln touches(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.touches(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry crosses the specified geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln crosses(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.crosses(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry is within the specified geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln within(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.within(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry contains the specified geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln contains(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.contains(geo2));
  }

  /**
   * Returns a boolean value that shows if this geometry overlaps the specified geometry.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln overlaps(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.overlaps(geo2));
  }

  /**
   * Returns a boolean value that shows if whether relationships between the boundaries, interiors
   * and exteriors of two geometries match the pattern specified in intersection-matrix-pattern.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @param intersectionMatrix intersection matrix for two geometries
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln relate(final ANode node1, final ANode node2, final Str intersectionMatrix)
      throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Bln.get(geo1.relate(geo2, intersectionMatrix.toJava()));
  }

  /**
   * Returns the shortest distance in the units of the spatial reference system of geometry, between
   * the geometries. The distance is the distance between a point on each of the geometries.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return distance double value
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl distance(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return Dbl.get(geo1.distance(geo2));
  }

  /**
   * Returns a polygon that represents all Points whose distance from this geometric object is less
   * than or equal to distance. The returned element must be either gml:Polygon, gml:LineString or
   * gml:Point.
   *
   * @param node xml element containing gml object(s)
   * @param distance specific distance from the $geometry (the buffer width)
   * @return buffer geometry as gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode buffer(final ANode node, final Dbl distance) throws QueryException {
    return gmlWriter(checkGeo(node).buffer(distance.dbl()));
  }

  /**
   * Returns the convex hull geometry of a geometry in GML, or the empty sequence. The returned
   * element must be either gml:Polygon, gml:LineString or gml:Point.
   *
   * @param node xml element containing gml object(s)
   * @return convex hull geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode convexHull(final ANode node) throws QueryException {
    return gmlWriter(checkGeo(node).convexHull());
  }

  /**
   * Returns a geometric object representing the Point set intersection of two geometries.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return intersection geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode intersection(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return gmlWriter(geo1.intersection(geo2));
  }

  /**
   * Returns a geometric object that represents the Point set union of two geometries.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return union geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode union(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return gmlWriter(geo1.union(geo2));
  }

  /**
   * Returns a geometric object that represents the Point set difference of two geometries.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return difference geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode difference(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return gmlWriter(geo1.difference(geo2));
  }

  /**
   * Returns a geometric object that represents the Point set symmetric difference of two
   * geometries.
   *
   * @param node1 xml element containing gml object(s)
   * @param node2 xml element containing gml object(s)
   * @return symmetric difference geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode symDifference(final ANode node1, final ANode node2) throws QueryException {
    final Geometry geo1 = checkGeo(node1);
    final Geometry geo2 = checkGeo(node2);
    return gmlWriter(geo1.symDifference(geo2));
  }

  /**
   * Returns number of geometries in a geometry collection, or 1 if the input is not a collection.
   *
   * @param node xml element containing gml object(s)
   * @return integer value of number of geometries
   * @throws QueryException query exception
   */
  @Deterministic
  public Int numGeometries(final ANode node) throws QueryException {
    return Int.get(checkGeo(node).getNumGeometries());
  }

  /**
   * Returns the nth geometry of a geometry collection, or the geometry if the input is not a
   * collection.
   *
   * @param node xml element containing gml object(s)
   * @param number integer number as the index of nth geometry
   * @return geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode geometryN(final ANode node, final Int number) throws QueryException {
    final Geometry geo = checkGeo(node);
    final long n = number.itr();
    if (n < 1 || n > geo.getNumGeometries()) throw GeoErrors.outOfRangeIdx(number);
    return gmlWriter(geo.getGeometryN((int) n - 1));
  }

  /**
   * Returns the x-coordinate value for point.
   *
   * @param node xml element containing gml object(s)
   * @return x double value
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl x(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POINT);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Point");

    return Dbl.get(geo.getCoordinate().x);
  }

  /**
   * Returns the y-coordinate value for point.
   *
   * @param node xml element containing gml object(s)
   * @return y double value
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl y(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POINT);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Point");

    return Dbl.get(geo.getCoordinate().y);
  }

  /**
   * Returns the z-coordinate value for point.
   *
   * @param node xml element containing gml object(s)
   * @return z double value
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl z(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POINT);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    return Dbl.get(geo.getCoordinate().z);
  }

  /**
   * Returns the length of this Geometry. Linear geometries return their length. Areal geometries
   * return their parameter. Others return 0.0
   *
   * @param node xml element containing gml object(s)
   * @return length double value
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl length(final ANode node) throws QueryException {
    return Dbl.get(checkGeo(node).getLength());
  }

  /**
   * Returns the start point of a line.
   *
   * @param node xml element containing gml object(s)
   * @return start point geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode startPoint(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_LINEARRING, Q_GML_LINESTRING);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    return gmlWriter(((LineString) geo).getStartPoint());
  }

  /**
   * Returns the end point of a line.
   *
   * @param node xml element containing gml object(s)
   * @return end point geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode endPoint(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_LINEARRING, Q_GML_LINESTRING);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    return gmlWriter(((LineString) geo).getEndPoint());
  }

  /**
   * Checks if the line is closed loop. That is, if the start Point is same with end Point.
   *
   * @param node xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln isClosed(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_LINEARRING, Q_GML_LINESTRING, Q_GML_MULTILINESTRING);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    return Bln.get(
        geo instanceof LineString
            ? ((LineString) geo).isClosed()
            : ((MultiLineString) geo).isClosed());
  }

  /**
   * Return a boolean value that shows weather the line is a ring or not. A line is a ring if it is
   * closed and simple.
   *
   * @param node xml element containing gml object(s)
   * @return boolean value
   * @throws QueryException query exception
   */
  @Deterministic
  public Bln isRing(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_LINEARRING, Q_GML_LINESTRING);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    return Bln.get(((LineString) geo).isRing());
  }

  /**
   * Returns the number of points in a geometry.
   *
   * @param node xml element containing gml object(s)
   * @return number of points int value
   * @throws QueryException query exception
   */
  @Deterministic
  public Int numPoints(final ANode node) throws QueryException {
    return Int.get(checkGeo(node).getNumPoints());
  }

  /**
   * Returns the nth point of a line.
   *
   * @param node xml element containing gml object(s)
   * @param number index of i-th point
   * @return n-th point as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode pointN(final ANode node, final Int number) throws QueryException {
    final Geometry geo = geo(node, Q_GML_LINEARRING, Q_GML_LINESTRING);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Line");

    final int max = geo.getNumPoints();
    final long n = number.itr();
    if (n < 1 || n > max) throw GeoErrors.outOfRangeIdx(number);

    return gmlWriter(((LineString) geo).getPointN((int) n - 1));
  }

  /**
   * Returns the area of a Geometry. Areal Geometries have a non-zero area. Returns zero for Point
   * and Lines.
   *
   * @param node xml element containing gml object(s)
   * @return geometry area as a double vaue
   * @throws QueryException query exception
   */
  @Deterministic
  public Dbl area(final ANode node) throws QueryException {
    return Dbl.get(checkGeo(node).getArea());
  }

  /**
   * Returns the mathematical centroid of the geometry as a gml:Point. The point is not guaranteed
   * to be on the surface.
   *
   * @param node xml element containing gml object(s)
   * @return centroid geometry as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode centroid(final ANode node) throws QueryException {
    return gmlWriter(checkGeo(node).getCentroid());
  }

  /**
   * Returns a gml:Point that is interior of this geometry. If it cannot be inside the geometry,
   * then it will be on the boundary.
   *
   * @param node xml element containing gml object(s)
   * @return a point as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode pointOnSurface(final ANode node) throws QueryException {
    return gmlWriter(checkGeo(node).getInteriorPoint());
  }

  /**
   * Returns the outer ring of a polygon, in GML.
   *
   * @param node xml element containing gml object(s)
   * @return exterior ring geometry (LineString) as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode exteriorRing(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POLYGON);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Polygon");

    return gmlWriter(((Polygon) geo).getExteriorRing());
  }

  /**
   * Returns the number of interior rings in a polygon.
   *
   * @param node xml element containing gml object(s)
   * @return integer number of interior rings
   * @throws QueryException query exception
   */
  @Deterministic
  public Int numInteriorRing(final ANode node) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POLYGON);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Polygon");

    return Int.get(((Polygon) geo).getNumInteriorRing());
  }

  /**
   * Returns the nth geometry of a geometry collection.
   *
   * @param node xml element containing gml object(s)
   * @param number index of i-th interior ring
   * @return n-th interior ring geometry (LineString) as a gml element
   * @throws QueryException query exception
   */
  @Deterministic
  public ANode interiorRingN(final ANode node, final Int number) throws QueryException {
    final Geometry geo = geo(node, Q_GML_POLYGON);
    if (geo == null && checkGeo(node) != null)
      throw GeoErrors.geoType(node.qname().local(), "Polygon");

    final long n = number.itr();
    final int max = ((Polygon) geo).getNumInteriorRing();
    if (n < 1 || n > max) throw GeoErrors.outOfRangeIdx(number);
    return gmlWriter(((Polygon) geo).getInteriorRingN((int) n - 1));
  }

  // PRIVATE METHODS (hidden from user of module) ========================================

  /**
   * Reads an element as a gml node. Returns a geometry element or throws an exception if the
   * element is of the wrong type.
   *
   * @param node xml node containing gml object(s)
   * @return geometry
   * @throws QueryException query exception
   */
  private Geometry checkGeo(final ANode node) throws QueryException {
    final Geometry geo = geo(node, QNAMES);
    if (geo == null) throw GeoErrors.unrecognizedGeo(node.qname().local());
    return geo;
  }

  /**
   * Reads an element as a gml node. Returns a geometry element or {@code null} if the element does
   * not match one of the specified types.
   *
   * @param node xml node containing gml object(s)
   * @param names allowed geometry types
   * @return geometry, or {@code null}
   * @throws QueryException query exception
   */
  private static Geometry geo(final ANode node, final QNm... names) throws QueryException {
    if (node.type != NodeType.ELM) throw EXPTYPE_X_X_X.get(null, NodeType.ELM, node.type, node);

    final QNm qname = node.qname();
    for (final QNm geo : names) {
      if (!qname.eq(geo)) continue;
      // type found... create reader and geometry element
      try {
        final String input = node.serialize().toString();
        final GMLReader gmlReader = new GMLReader();
        final GeometryFactory geoFactory = new GeometryFactory();
        return gmlReader.read(input, geoFactory);
      } catch (final Throwable ex) {
        throw GeoErrors.gmlReaderErr(ex);
      }
    }
    return null;
  }

  /**
   * Writes an geometry and returns a string representation of the geometry.
   *
   * @param geometry geometry
   * @return DBNode database node
   * @throws QueryException exception
   */
  private DBNode gmlWriter(final Geometry geometry) throws QueryException {
    final String geo;
    try {
      // write geometry and add namespace declaration
      geo =
          new GMLWriter()
              .write(geometry)
              .replaceAll("^<gml:(.*?)>", "<gml:$1 xmlns:gml='" + string(URI) + "'>");
    } catch (final Exception ex) {
      throw GeoErrors.gmlWriterErr(ex);
    }

    try {
      final IO io = new IOContent(geo);
      return new DBNode(MemBuilder.build(new XMLParser(io, queryContext.context.options)));
    } catch (final IOException ex) {
      throw IOERR_X.get(null, ex);
    }
  }
}
예제 #5
0
 /**
  * Returns the specified value as an atomic string.
  *
  * @param value value
  * @param name name
  * @return string
  * @throws QueryException HTTP exception
  */
 private String toString(final Value value, final QNm name) throws QueryException {
   if (!(value instanceof Str)) error(ANN_STRING, "%", name.string(), value);
   return ((Str) value).toJava();
 }
예제 #6
0
  /**
   * Checks a function for RESTFful annotations.
   *
   * @return {@code true} if module contains relevant annotations
   * @throws QueryException query exception
   */
  boolean analyze() throws QueryException {
    // parse all annotations
    final EnumSet<HTTPMethod> mth = EnumSet.noneOf(HTTPMethod.class);
    final boolean[] declared = new boolean[function.args.length];
    boolean found = false;
    final int as = function.ann.size();
    for (int a = 0; a < as; a++) {
      final QNm name = function.ann.names[a];
      final Value value = function.ann.values[a];
      final byte[] local = name.local();
      final byte[] uri = name.uri();
      final boolean rexq = eq(uri, QueryText.RESTXQURI);
      if (rexq) {
        if (eq(PATH, local)) {
          // annotation "path"
          if (path != null) error(ANN_TWICE, "%", name.string());
          path = new RestXqPath(toString(value, name));
          for (final String s : path) {
            if (s.trim().startsWith("{")) checkVariable(s, AtomType.AAT, declared);
          }
        } else if (eq(CONSUMES, local)) {
          // annotation "consumes"
          strings(value, name, consumes);
        } else if (eq(PRODUCES, local)) {
          // annotation "produces"
          strings(value, name, produces);
        } else if (eq(QUERY_PARAM, local)) {
          // annotation "query-param"
          queryParams.add(param(value, name, declared));
        } else if (eq(FORM_PARAM, local)) {
          // annotation "form-param"
          formParams.add(param(value, name, declared));
        } else if (eq(HEADER_PARAM, local)) {
          // annotation "header-param"
          headerParams.add(param(value, name, declared));
        } else if (eq(COOKIE_PARAM, local)) {
          // annotation "cookie-param"
          cookieParams.add(param(value, name, declared));
        } else {
          // method annotations
          final HTTPMethod m = HTTPMethod.get(string(local));
          if (m == null) error(ANN_UNKNOWN, "%", name.string());
          if (!value.isEmpty()) {
            // remember post/put variable
            if (requestBody != null) error(ANN_TWICE, "%", name.string());
            if (m != POST && m != PUT) error(METHOD_VALUE, m);
            requestBody = checkVariable(toString(value, name), declared);
          }
          if (mth.contains(m)) error(ANN_TWICE, "%", name.string());
          mth.add(m);
        }
      } else if (eq(uri, QueryText.OUTPUTURI)) {
        // serialization parameters
        final String key = string(local);
        final String val = toString(value, name);
        if (output.get(key) == null) error(UNKNOWN_SER, key);
        output.set(key, val);
      }
      found |= rexq;
    }
    if (!mth.isEmpty()) methods = mth;

    if (found) {
      if (path == null) error(ANN_MISSING, PATH);
      for (int i = 0; i < declared.length; i++)
        if (!declared[i]) error(VAR_UNDEFINED, function.args[i].name.string());
    }
    return found;
  }