/*
 * Title:       GeometryToArray.java 1.00 2002/05/14
 *
 *      Licensed Materials - Property of IBM and/or HCL
 *      IBM Informix  Spatial DataBlade
 *      (c) Copyright IBM Corporation 2002 All rights reserved.
 *      (c) Copyright HCL Technologies Ltd. 2017.  All Rights Reserved.
 *
 *      US Government Users Restricted Rights - Use, duplication or
 *      disclosure restricted by GSA ADP Schedule Contract with
 *      IBM Corp.
 */
import java.sql.*;
import java.util.*;
import com.ibm.spatial.geom.*;
import com.ibm.spatial.srs.*;
import com.ibm.spatial.*;

public class GeometryToArray {

	static String url = null;
	Connection conn = null;
	CoordRefManager crm = null;

	public GeometryToArray() throws ClassNotFoundException {
   		// Loading driver
		System.out.print("Loading JDBC driver...");
		Class.forName("com.informix.jdbc.IfxDriver");
		System.out.println("ok");
	}

	public static void main(String[] args) {
		try {
			GeometryToArray app = new GeometryToArray();
			app.init(args);
			app.doRun();
			app.cleanup();
		} catch (Exception e) {
			System.out.println("ERROR: " + e.getMessage() + "\n");
			e.printStackTrace();
		}
    }

	/**
	 * Creates several geometries using a factory, then reads coordinate
	 * data out.
	 */
    void doRun() throws SpatialException, ClassNotFoundException {

		// Creating a factory object
		System.out.println("Initializing the factory ...");
		CoordRef cr = crm.get(100);
		GeometryFactory factory = GeometryFactory.getInstance(cr);

		// Creating a point
		System.out.println("\nCreating a Point geometry ...");
		Geometry geo = factory.createPoint(100, 100);
		System.out.println(geo.toString());

		/**
		 * Reading coordinate data using IfxGeometry.toCoordArray() and
		 * IfxGeometry.toPointArray().
		 */
		System.out.println("Reading XY coordinate data using IfxGeometry.toCoordArray()" +
			" and IfxGeometry.toPointArray() ...");
		System.out.println("COORD_XY  : " + dumpCoordsXY(geo));
		System.out.println("Points    : " + dumpPoints(geo));

		// Creating a multipolygon
		System.out.println("\nCreating a MultiPolygon zm geometry...");
		double[] xy = {0, 0, 3, 7, 10, 10, 7, 3, 0, 0, 1, 1, 4, 6, 9, 9, 6, 4, 1, 1,
						20, 20, 23, 27, 30, 30, 27, 23, 20, 20};
		double[] z = {0, 5, 10, 5, 0, 1, 4, 9, 4, 1, 0, 5, 10, 5, 0};
		double[] m = {0, 5, 10, 5, 0, 1, 4, 9, 4, 1, 0, 5, 10, 5, 0};
		int[] partOffsets = {0, 2, 3};
		int[] subPartOffsets = {0, 5, 10, 15};
		geo = factory.createGeometry("MultiPolygon", xy, z, m, partOffsets,
									subPartOffsets);
		System.out.println(geo.toString());

		/**
		 * Reading coordinate data using IfxGeometry.toCoordArray() and
		 * IfxGeometry.toPointArray().
		 */
		System.out.println("Reading XY coordinate data using IfxGeometry.toCoordArray()" +
			" and IfxGeometry.toPointArray() ...");
		System.out.println("COORD_XY  : " + dumpCoordsXY(geo));
		System.out.println("Points    : " + dumpPoints(geo));
	}

	/**
	 * Read coordinate data using toCoordArray().
	 */
	StringBuffer dumpCoordsXY(Geometry g) {
		IfxGeometry geo = (IfxGeometry)g;
		double buf[] = new double[10];
		StringBuffer sb = new StringBuffer(1000);

		// For each part and subpart, read coordinates into buf
		for(int part = 0; part < geo.numParts(); part++) {
			for(int subpart = 0; subpart < geo.numSubParts(part); subpart++) {
				for (int position = 0, points = geo.numPoints(part, subpart), read = 0;
						points > 0;
						points -= read) {

					read = geo.toCoordArray(buf, 0, IfxGeometry.COORD_XY,
											position, part, subpart);
					if (read == 0) break;

					// Write coordinates into string buffer
					for (int i = 0; i < read; i++) {
						sb.append(buf[i * 2]).append(' ').append(buf[i*2+1]);
						sb.append(',');
					}
					// Update position of the next point to read
					position += read;
				}
			}
		}
		return sb;
	}

	/**
	 * Reads coordinate data using toPointArray().
	 */
	StringBuffer dumpPoints(Geometry g) {
		IfxGeometry geo = (IfxGeometry)g;
		StringBuffer sb = new StringBuffer(1000);
		CoordPoint buf[] = new CoordPoint.Double[10];

		for (int i = 0; i < buf.length; i++)
			buf[i] = new CoordPoint.Double();

		for(int part = 0; part < geo.numParts(); part++) {
			for(int subpart = 0; subpart < geo.numSubParts(part); subpart++) {
				for (int position = 0, points = geo.numPoints(part, subpart), read = 0;
						points > 0;
						points -= read) {

					read = geo.toPointArray(buf, 0, position, part, subpart);
					if (read == 0) break;

					// Write point coordinates into string buffer
					for (int i = 0; i < read; i++)
						sb.append(buf[i].getX()).append(' ').append(buf[i].getY()).append(',');

					// Update position of the next point to read
					position += read;
				}
			}
		}
		return sb;
	}

	/**
	 * Creates a spatial reference with srid=100 and inserts it into
	 * the SPATIAL_REFERENCES table.
	 */
    void init(String args[]) throws SQLException, SpatialException {

		if (args.length == 0) {
			if (url == null || url.length() == 0) {
				throw new RuntimeException(
					"Connection URL must be provided in " +
					"order to run this sample program!");
			}
		} else {
			url = args[0];
		}

   		// Getting connection
        System.out.print("Getting connection...");
        conn = DriverManager.getConnection(url);
        System.out.println("ok\n");

        // Delete the SRS with srid=100
		PreparedStatement pstmt;
		try {
			pstmt = conn.prepareStatement("delete from spatial_references where srid=100");
            pstmt.executeUpdate();
        } catch (SQLException e) {
            // ignore error
            System.out.println("SRS with srid=100 does not exist");
        }

        // Insert a new SRS
		System.out.println("Inserting a SRS with srid=100 ...");
        pstmt = conn.prepareStatement(
			"insert into sde.spatial_references values" +
			"(100,NULL,NULL,NULL,-1000.0,-1000.0,1000,-1000.0,1000,-1000.0,1000,'UNKNOWN')");
        pstmt.executeUpdate();

		// Setting the CoordRefManager connection
		crm = CoordRefManager.getInstance();
		crm.setConnection(conn);
		crm.refresh();
	}

    void cleanup() throws SQLException {
        // Delete the SRS with srid=100
		PreparedStatement pstmt;
		System.out.println("Deleting the SRS with srid=100 ...");
		try {
			pstmt = conn.prepareStatement("delete from spatial_references where srid=100");
            pstmt.executeUpdate();
        } catch (SQLException e) {
            // ignore error
            System.out.println("SRS with srid=100 does not exist");
        }

		// Closing connection
		System.out.print("Closing connection...");
		conn.close();
		System.out.println("ok");
	}
}