Create a Java program that uses the Apache Cassandra NoSQL database to store and retrieve time-series data. The program should include functions for inserting new data points, querying data based on time ranges, and performing basic aggregation operations (e.g., average, min, max) on the retrieved data.
PLAINFORMAT
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;

import java.util.Date;
import java.util.UUID;

public class TimeSeriesData {
    private static Session session;

    public static void main(String[] args) {
        // Connect to Cassandra
        Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
        session = cluster.connect("timeseries");

        UUID sensorId = UUID.randomUUID();

        // Insert data points
        insertDataPoint(sensorId, new Date(), 25.5);
        insertDataPoint(sensorId, new Date(System.currentTimeMillis() - 3600000), 24.3);

        // Query data points
        ResultSet resultSet = queryDataPoints(sensorId, new Date(System.currentTimeMillis() - 7200000), new Date());
        for (Row row : resultSet) {
            System.out.println(row.getUUID("sensor_id") + " | " + row.getTimestamp("timestamp") + " | " + row.getDouble("value"));
        }

        // Perform aggregation operations
        double average = getAverage(sensorId);
        double min = getMin(sensorId);
        double max = getMax(sensorId);

        System.out.println("Average: " + average);
        System.out.println("Min: " + min);
        System.out.println("Max: " + max);

        // Close the connection
        cluster.close();
    }

    public static void insertDataPoint(UUID sensorId, Date timestamp, double value) {
        String query = String.format("INSERT INTO datapoints (sensor_id, timestamp, value) VALUES (%s, '%s', %f);", sensorId.toString(), timestamp.toInstant().toString(), value);
        session.execute(query);
    }

    public static ResultSet queryDataPoints(UUID sensorId, Date startTime, Date endTime) {
        String query = String.format("SELECT * FROM datapoints WHERE sensor_id = %s AND timestamp >= '%s' AND timestamp <= '%s';", sensorId.toString(), startTime.toInstant().toString(), endTime.toInstant().toString());
        return session.execute(query);
    }

    public static double getAverage(UUID sensorId) {
        String query = String.format("SELECT AVG(value) as average FROM datapoints WHERE sensor_id = %s;", sensorId.toString());
        Row row = session.execute(query).one();
        return row.getDouble("average");
    }

    public static double getMin(UUID sensorId) {
        String query = String.format("SELECT MIN(value) as min_value FROM datapoints WHERE sensor_id = %s;", sensorId.toString());
        Row row = session.execute(query).one();
        return row.getDouble("min_value");
    }

    public static double getMax(UUID sensorId) {
        String query = String.format("SELECT MAX(value) as max_value FROM datapoints WHERE sensor_id = %s;", sensorId.toString());
        Row row = session.execute(query).one();
        return row.getDouble("max_value");
    }
}