package de.anxietyprime.swajodel; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; import java.sql.*; import java.util.Optional; import java.util.Vector; @RestController public class Routes { @GetMapping("/posts/{longitude}/{latitude}") public Vector getPostsByLocation(@PathVariable("longitude") float longitude, @PathVariable("latitude") float latitude) { // list of all posts (not comments) in range Vector posts = new Vector<>(); // DB connection and statement Connection c = null; PreparedStatement stmt = null; // try to get data from db try { // check for the driver Class.forName("org.postgresql.Driver"); // get the connection with credentials from env variables c = DriverManager .getConnection("jdbc:postgresql://"+ System.getenv("POSTGRES_IP")+"/"+System.getenv("POSTGRES_DB"), System.getenv("POSTGRES_USER"), System.getenv("POSTGRES_PASSWORD")); // disable auto commits c.setAutoCommit(false); // create a new statement stmt = c.prepareStatement("WITH RECURSIVE targets AS (\n" + " SELECT\n" + " posts.id,\n" + " posts.id AS parent,\n" + " posts.author,\n" + " posts.title,\n" + " posts.content,\n" + " posts.postdate,\n" + " posts.postlocation[0] AS longitude,\n" + " posts.postlocation[1] AS latitude,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = posts.id AND positive = TRUE) AS positive,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = posts.id AND positive = FALSE) AS negative\n" + " FROM\n" + " posts\n" + " WHERE\n" + " deleted IS NULL\n" + " AND sqrt(power(postlocation[0] - (?), 2) + power(postlocation[1] - (?), 2)) <= 10\n" + " AND posts.id NOT IN (SELECT child FROM comments)\n" + " UNION\n" + " SELECT\n" + " com.child,\n" + " com.parent,\n" + " com.author,\n" + " com.title,\n" + " com.content,\n" + " com.postdate,\n" + " com.postlocation[0],\n" + " com.postlocation[1],\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = com.child AND positive = TRUE) AS positive,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = com.child AND positive = FALSE) AS negative\n" + " FROM\n" + " (SELECT * FROM comments inner join posts ON comments.child = posts.id) com\n" + " inner join targets ON targets.id = com.parent\n" + ")\n" + "SELECT * FROM targets;"); stmt.setObject(1, longitude); stmt.setObject(2, latitude); // query recursively for posts inside a 10km radius ResultSet rs = stmt.executeQuery(); // for all the posts found while ( rs.next() ) { // create a post from the author id JodelPost post = new JodelPost(rs); // get the posts parent long parent = rs.getLong("parent"); // check if the parent is the own id // if it is, it is a post if (parent == post.id) { // add the post to the posts posts.add(post); } // else it is a comment else { // iterate over all posts for (JodelPost p : posts) { // try to add the post to a parent p.addComment(post, parent); } } } // close all connections to db rs.close(); stmt.close(); c.close(); } // else log the error catch ( Exception e ) { System.err.println( e.getClass().getName()+": "+ e.getMessage() ); throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "Database is offline"); } // calculate anonymous IDs for the posts posts.forEach(post -> { post.anonymize(Optional.empty()); }); // return the posts return posts; } @GetMapping("/post/{id}") public JodelPost getPostByID(@PathVariable("id") long id) { // list of all posts (not comments) in range Optional root_post = Optional.empty(); // DB connection and statement Connection c = null; PreparedStatement stmt = null; // try to get data from db try { // check for the driver Class.forName("org.postgresql.Driver"); // get the connection with credentials from env variables c = DriverManager .getConnection("jdbc:postgresql://"+ System.getenv("POSTGRES_IP")+"/"+System.getenv("POSTGRES_DB"), System.getenv("POSTGRES_USER"), System.getenv("POSTGRES_PASSWORD")); // disable auto commits c.setAutoCommit(false); // create a new statement stmt = c.prepareStatement("WITH RECURSIVE targets AS (\n" + " SELECT\n" + " posts.id,\n" + " posts.id AS parent,\n" + " posts.author,\n" + " posts.title,\n" + " posts.content,\n" + " posts.postdate,\n" + " posts.postlocation[0] AS longitude,\n" + " posts.postlocation[1] AS latitude,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = posts.id AND positive = TRUE) AS positive,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = posts.id AND positive = FALSE) AS negative\n" + " FROM\n" + " posts\n" + " WHERE\n" + " deleted IS NULL\n" + " AND posts.id = (?)\n" + " AND posts.id NOT IN (SELECT child FROM comments)\n" + " UNION\n" + " SELECT\n" + " com.child,\n" + " com.parent,\n" + " com.author,\n" + " com.title,\n" + " com.content,\n" + " com.postdate,\n" + " com.postlocation[0],\n" + " com.postlocation[1],\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = com.child AND positive = TRUE) AS positive,\n" + " (SELECT count(*) FROM reaction WHERE reaction.post = com.child AND positive = FALSE) AS negative\n" + " FROM\n" + " (SELECT * FROM comments inner join posts ON comments.child = posts.id) com\n" + " inner join targets ON targets.id = com.parent\n" + ")\n" + "SELECT * FROM targets;"); stmt.setObject(1, id); // query recursively for posts inside a 10km radius ResultSet rs = stmt.executeQuery(); // for all the posts found while ( rs.next() ) { // create a post from the author id JodelPost post = new JodelPost(rs); // get the posts parent long parent = rs.getLong("parent"); // check if the parent is the own id // if it is, it is a post if (parent == post.id) { // add the post to the posts root_post = Optional.of(post); } // else it is a comment else { // try to add the post to parent root_post.ifPresent(root -> root.addComment(post, parent)); } } // close all connections to db rs.close(); stmt.close(); c.close(); } // else log the error catch ( Exception e ) { System.err.println( e.getClass().getName()+": "+ e.getMessage() ); throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "Database is offline"); } // calculate anonymous IDs for the post root_post.ifPresent(root -> root.anonymize(Optional.empty())); // return the posts if (root_post.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "No post found"); return root_post.get(); } }