/** Example of implementing REST API handlers.
    @note  These methods operate on local variables instead 
    of database tables. In an actual app, the methods of Handler classes 
    should use JDBC to perform SQL operations instead. */

class ExampleRestModel extends RestApiModel {
  
  public ExampleRestModel() {
    addHandler("/", new CountHandler());
    addHandler("/names", new NamesHandler());
  }
  

  /** inner class for implementing API for url "/" (count server) */

  class CountHandler extends RestApiHandler {
    /** simulated value of count */
    /* simulates SQL   CREATE TABLE count (val int);
                       INSERT INTO count VALUES (0);     */
    int count_val = 0;  

    /** handles POST requests for url "/"
	@param p Results of parsing a POST HTTP request for url "/"
	@sc Adds 1 to stored counter
	@return HTTP reply for that request, i.e., OK 
        @note In our REST conventions, we should implement thie "Update" 
	operation as a PATCH HTTP request.  We're including this duplicate 
	as a POST for consistency with the original server */
    public String doPost(HttpParser p) {
      return doPatch(p);
    }

    /** handles PATCH requests for url "/"
	@param p Results of parsing a POST HTTP request for url "/"
	@sc Adds 1 to stored counter
	@return HTTP reply for that request, i.e., OK */
    public String doPatch(HttpParser p) {
      /* Simulates SQL   UPDATE count SET val = val + 1;   */
      count_val++;
      return p.makeReply(200, "OK");
    }

    /** handles GET requests for url "/"
	@param p Results of parsing a GET HTTP request for url "/"
	@return HTTP reply for that request, 
	i.e.,  JSON for current value of stored counter   */
    public String doGet(HttpParser p) {
      /* Simulates SQL   SELECT val FROM count;   */
      return p.makeJsonReply(200, 
			     "{ \"count\": " + Integer.toString(count_val) + 
			     " }");
    }
  }


  /** inner class for implementing API for url "/names" (name server) 
      @note <strong>WARNING:</strong> This simulation using an array
      of Strings instead of an database table has a potential race condition!
      If this were a multithreaded server, all of the handler methods that 
      interact with the array <code>names[]</code> or variable <code>ct</code> 
      need to be <code>synchronized</code> in order to prevent interference
      among multiple threads.  <em>But</em>, individual SQL commands for a 
      DBMS such as Postgres are <em>atomic</em>, which means there is no 
      danger of race conditions with (single) SQL commands actual database 
      tables. */ 

  class NamesHandler extends RestApiHandler {
    /** maximum capacity of array <code>names[]</code> 
        @note Would not be necessary if we implemented in database */
    static final int maxnames = 10000;

    /** simulated value of names table */
    /* simulates SQL    CREATE TABLE names (name text);    */
    String [] names = new String[maxnames];  
    /** number of elements in array <code>names[]</code> 
        @note Would not be necessary if we implemented in database */
    int ct = 0;

    /** handles PATCH requests for url "/names"
	@param p Results of parsing a PATCH HTTP request for url "/names"
	@sc Adds value for POST-style parameter <code>name</code> to 
	the <code>names</code> database table.
	@return HTTP reply for that request, i.e., OK  
	@note <strong>WARNING:</strong> Potential race condition!  See 
	class description.    */
    public String doPatch(HttpParser p) {
      /* Simulates SQL   INSERT INTO names VALUES (&sto:ENTRY;);   */
      if (ct == maxnames)
	return p.makeReply(500, "Simulated table full");
      // safe to insert into the simulated table
      names[ct++] = p.getParam("name");
      return p.makeReply(200, "OK");
    }

    /** handles POST requests for url "/names"
	@param p Results of parsing a POST HTTP request for url "/names"
	@sc Adds 1 to stored counter
	@return HTTP reply for that request, i.e., OK 
        @note In our REST conventions, we should implement thie "Update" 
	operation as a PATCH HTTP request.  We're including this duplicate 
	as a POST for consistency with the original server */
    public String doPost(HttpParser p) {
      return doPatch(p);
    }

    /** handles GET requests for url "/names"
	@param p Results of parsing a GET HTTP request for url "/names"
	@return HTTP reply for that request, 
	i.e.,  JSON for current values in names[]   
	@note <strong>WARNING:</strong> Potential race condition!  See 
	class description.    */
    public String doGet(HttpParser p) {
      /* Simulates SQL   SELECT name FROM names;   */
      String jsonStr = new String("{ \"names\": [\n");
      for (int i = 0;  i < ct;  i++) {
	jsonStr += "    ";
	if (names[i] == null)
	  jsonStr += "null,\n";
	else
	  jsonStr += "\"" + names[i] + "\",\n";
      }
      // remove final comma if present and terminate string
      if (ct > 0)
	jsonStr = jsonStr.substring(0, jsonStr.length()-2) + "\n";
      jsonStr += "  ] }";  
      return p.makeJsonReply(200, jsonStr);
    }
  }
}