//
//
// GitHub: https://github.com/SERPWoo/API
//
// This code requests a Keyword's SERP Results and outputs the Timestamp, Rank, Type, Page Title, URL
//
// This output is text format
//
// Last updated - Aug 28th, 2017 @ 1:04 EST (@MercenaryCarter https://github.com/MercenaryCarter and https://twitter.com/MercenaryCarter)
//
// Compile Command: javac -cp "lib/jackson-all-1.9.0.jar" KeywordSERPs.java
//
// - OR (if org.codehaus.jackson is within your Java CLASSPATH already) -
//
// Compile Command: javac KeywordSERPs.java
// Run Command: java KeywordSERPs
//
//

import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

@SuppressWarnings("unchecked")
public class KeywordSERPs {

    public static void main(String[] args) {

			// Get your API Key here: https://www.serpwoo.com/v3/api/ (should be logged in)
            String API_key = "API_KEY_HERE";
            String Project_ID = 0; //input your Project ID
            String Keyword_ID = 0; //input your Keyword ID

            String output = getUrlContents("https://api.serpwoo.com/v1/serps/" + Project_ID + "/" + Keyword_ID + "/?key=" + API_key);

            List<Row> table = new ArrayList<>(); // used to store final output

            ObjectMapper mapper = new ObjectMapper(); // Jackson mapper

            try {

                Response response = mapper.readValue(output, Response.class);
                Iterator it = ((Map<String, Object>) response.getOther().get("235082")).entrySet().iterator();

                //iterate through each entry in projects element and add required fields to the row object
                while (it.hasNext()) {

                    Map.Entry pair = (Map.Entry) it.next();
                    
                    String timestamp = pair.getKey().toString();
                    Map<String, Object> results = (Map<String,Object>) ((Map<String, Object>) pair.getValue()).get("results");
                    
                    Iterator innerIterator = results.entrySet().iterator();

                    // iterate the result set
                    while (innerIterator.hasNext()) {

                        Map.Entry innerPair = (Map.Entry)innerIterator.next();
                        String rank = innerPair.getKey().toString();

                        String type = ((Map<String, Object>)innerPair.getValue()).get("type").toString();
                        String title = ((Map<String, Object>)innerPair.getValue()).get("title").toString();
                        String url = ((Map<String, Object>)innerPair.getValue()).get("url").toString();


                        table.add(new Row(timestamp, rank, type,title, url )); // insert row object into table
                    }
                    
                }

                //sort the table
                Collections.sort(table);

                System.out.printf("\n--\n");

                System.out.printf("%-15s %-10s %-10s %-80s %-80s\n","Timestamp", "Rank", "Type", "Title", "URL");
                System.out.printf("%-15s %-10s %-10s %-80s %-80s\n","---------", "----", "----", "-----", "---");
                Iterator iterator = table.iterator();

                // print the final output to the terminal
                while (iterator.hasNext()) {
                    ((Row) iterator.next()).printRow();
                }

                System.out.printf("\n--\n");

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    private static String getUrlContents(String theUrl) {
        StringBuilder content = new StringBuilder();

        // many of these calls can throw exceptions, so i've just
        // wrapped them all in one try/catch statement.
        try {
            // create a url object
            URL url = new URL(theUrl);

            // create a urlconnection object
            URLConnection urlConnection = url.openConnection();

            // wrap the urlconnection in a bufferedreader
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

            String line;

            // read from the urlconnection via the bufferedreader
            while ((line = bufferedReader.readLine()) != null) {
                content.append(line + "\n");
            }
            bufferedReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    static class Row implements Comparable<Row> {
        private String timestamp; // ascending order
        private String rank;
        private String type;
        private String title;
        private String url;

        public Row(String timestamp, String rank, String type, String title, String url) {
            this.timestamp = timestamp;
            this.rank = rank;
            this.type = type;
            this.title = title;
            this.url = url;
        }

        public String getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(String timestamp) {
            this.timestamp = timestamp;
        }

        public String getRank() {
            return rank;
        }

        public void setRank(String rank) {
            this.rank = rank;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        // this method is used for sorting objects
        @Override
        public int compareTo(Row o) {

            try {
                if(this.timestamp.equals(o.timestamp)) {
                    return Integer.parseInt(this.rank) - Integer.parseInt(o.rank);
                }
                return Integer.parseInt(this.timestamp) - Integer.parseInt(o.timestamp);
            } catch (Exception e) {

            }
            return 0;
        }

        // print object to the terminal
        public void printRow() {

            System.out.printf("%-15s %-10s %-10s %-80s %-80s\n", this.timestamp, this.rank, this.type, this.title, this.url);
        }
    }


    // Jackson parser use this class to create objects from the json string
    static class Response {
        private String success;
        private String total;
        private String response_time;
        private String time;

        private Map<String, Object> other = new HashMap<String, Object>();


        public String getSuccess() {
            return success;
        }

        public void setSuccess(String success) {
            this.success = success;
        }

        public String getTotal() {
            return total;
        }

        public void setTotal(String total) {
            this.total = total;
        }

        public String getResponse_time() {
            return response_time;
        }

        public void setResponse_time(String response_time) {
            this.response_time = response_time;
        }

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public Map<String, Object> getOther() {
            return other;
        }

        public void setOther(Map<String, Object> other) {
            this.other = other;
        }


        // any unknown properties will be mapped into the map named other through below methods
        @JsonAnyGetter
        public Map<String, Object> any() {
            return other;
        }

        @JsonAnySetter
        public void set(String name, Object value) {
            other.put(name, value);
        }
    }

}



@@ -222,11 +222,12 @@
  @ 1
-:04
+7:30
  EST
@@ -1116,25 +1116,27 @@
 roject_ID = 
-0
+%220%22
 ; //input yo
@@ -1148,16 +1148,35 @@
 oject ID
+ (has to be string)
 %0A       
@@ -1200,17 +1200,19 @@
 rd_ID = 
-0
+%220%22
 ; //inpu
@@ -1228,16 +1228,35 @@
 yword ID
+ (has to be string)
 %0A%0A      
@@ -1715,16 +1715,18 @@
 get(
-%22235082%22
+Keyword_ID
 )).e

Update KeywordSERPs.java