Implement FRQ1 in Spring Project

Enhance APCalendar.java

APCalendar.java

package com.nighthawk.spring_portfolio.mvc.calendar;

// Prototype Implementation

public class APCalendar {

    /** Returns true if year is a leap year and false otherwise.
     * isLeapYear(2019) returns False
     * isLeapYear(2016) returns True
     */          
    public static boolean isLeapYear(int year) {
        // implementation not shown
        if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
            return true;
        }
        return false;
        }
        
    /** Returns the value representing the day of the week 
     * 0 denotes Sunday, 
     * 1 denotes Monday, ..., 
     * 6 denotes Saturday. 
     * firstDayOfYear(2019) returns 2 for Tuesday.
    */
    public static int firstDayOfYear(int year) {
        // implementation not shown
        if (year > 1752) {
            return (year + numberOfLeapYears(1, year - 1))%7;
        }
        return (year + (year-1)/4 + 5)%7;
        }


    /** Returns n, where month, day, and year specify the nth day of the year.
     * This method accounts for whether year is a leap year. 
     * dayOfYear(1, 1, 2019) return 1
     * dayOfYear(3, 1, 2017) returns 60, since 2017 is not a leap year
     * dayOfYear(3, 1, 2016) returns 61, since 2016 is a leap year. 
    */ 
    public static int dayOfYear(int month, int day, int year) {
        // implementation not shown
        int count = 0;
        if (month < 8) {
            count = 31*((month)/2) + 30*((month-1)/2) + day;
        } else {
            count = 214 + 31*((month-7)/2) + 30*((month-8)/2) + day;
        }
        if (month > 2) {
            if (!isLeapYear(year)) {
                count = count - 2;
            } else {
                count--;
            }
        }
        return count;
        }

    /** Returns the number of leap years between year1 and year2, inclusive.
     * Precondition: 0 <= year1 <= year2
    */ 
    public static int numberOfLeapYears(int year1, int year2) {
         // to be implemented in part (a)
        int count = 0;
        for (int i = year1; i <= year2; i++) {
            if (isLeapYear(i)) {
                count++;
            }
        }
        return count;
        }

    /** Returns the value representing the day of the week for the given date
     * Precondition: The date represented by month, day, year is a valid date.
    */
    public static int dayOfWeek(int month, int day, int year) { 
        // to be implemented in part (b)
        return (firstDayOfYear(year) + dayOfYear(month, day, year) - 1) % 7;
        }

    /** Tester method */
    public static void main(String[] args) {
        // Private access modifiers
        System.out.println("firstDayOfYear 1700 (1): " + APCalendar.firstDayOfYear(1700));
        System.out.println("firstDayOfYear 1701 (3): " + APCalendar.firstDayOfYear(1701));
        System.out.println("firstDayOfYear 1752 (3): " + APCalendar.firstDayOfYear(1752));
        System.out.println("firstDayOfYear 1753 (1): " + APCalendar.firstDayOfYear(1753));
        System.out.println("firstDayOfYear 1800 (3): " + APCalendar.firstDayOfYear(1800));
        System.out.println("firstDayOfYear 1801 (4): " + APCalendar.firstDayOfYear(1801));
        System.out.println("firstDayOfYear 2019 (2): " + APCalendar.firstDayOfYear(2019));
        System.out.println("dayOfYear 3/1/2017: " + APCalendar.dayOfYear(3, 1, 2017));
        System.out.println("dayOfYear 3/1/2016: " + APCalendar.dayOfYear(3, 1, 2016));

        // Public access modifiers
        System.out.println("isLeapYear 1600: " + APCalendar.isLeapYear(1600));
        System.out.println("isLeapYear 1800: " + APCalendar.isLeapYear(1800));
        System.out.println("isLeapYear 2019: " + APCalendar.isLeapYear(2019));
        System.out.println("isLeapYear 2024: " + APCalendar.isLeapYear(2024));
        System.out.println("numberOfLeapYears 2000-2022: " + APCalendar.numberOfLeapYears(2000, 2022));
        System.out.println("dayOfWeek 7/5/2022: " + APCalendar.dayOfWeek(7, 5, 2022));
        System.out.println("dayOfWeek 8/5/2022: " + APCalendar.dayOfWeek(8, 5, 2022));
        System.out.println("dayOfWeek 11/18/2022: " + APCalendar.dayOfWeek(11, 18, 2022));
    }

}

testing methods

Enhance APIs and @RESTController to work with the all POJOs and APCalendar

Year.java

package com.nighthawk.spring_portfolio.mvc.calendar;

/** Simple POJO 
 * Used to Interface with APCalendar
 * The toString method(s) prepares object for JSON serialization
 * Note... this is NOT an entity, just an abstraction
 */
class Year {
   private int year;
   private boolean isLeapYear;

   private int year4;
   private int firstDayOfYear;

   private int year1;
   private int year2;
   private int numberOfLeapYears;

   private int month;
   private int day;
   private int year3;
   private int dayOfWeek;

   private int month1;
   private int day1;
   private int year5;
   private int dayOfYear;

   // zero argument constructor
   public Year() {} 

   /* year getter/setters */
   public int getYear() {
      return year;
   }
   public void setYear(int year) {
      this.year = year;
      this.setIsLeapYear(year);
   }


   /* year getter/setters */
   public int getYear4() {
      return year4;
   }
   public void setFirst(int year) {
      this.year4 = year;
      this.setFirstDayOfYear(year);
   }

   
   /* year getter/setters */
   public int getYear1() {
      return year1;
   }
   public int getYear2() {
      return year2;
   }
   public void setNum(int year1, int year2) {
      this.year1 = year1;
      this.year2 = year2;
      this.setNumberOfLeapYears(year1, year2);
   }

   /* year getter/setters */
   public int getMonth() {
      return month;
   }
   public int getDay() {
      return day;
   }
   public int getYear3() {
      return year3;
   }
   public void setWeek(int month, int day, int year) {
      this.month = month;
      this.day = day;
      this.year3 = year;
      this.setDayOfWeek(month, day, year);
   }

   public int getMonth1() {
      return month1;
   }
   public int getDay1() {
      return day1;
   }
   public int getYear5() {
      return year5;
   }
   public void setDay(int month, int day, int year) {
      this.month1 = month;
      this.day1 = day;
      this.year5 = year;
      this.setDayOfYear(month, day, year);
   }   

   /* isLeapYear getter/setters */
   public boolean getIsLeapYear(int year) {
      return APCalendar.isLeapYear(year);
   }
   private void setIsLeapYear(int year) {  // this is private to avoid tampering
      this.isLeapYear = APCalendar.isLeapYear(year);
   }

   /* isLeapYearToString formatted to be mapped to JSON */
   public String isLeapYearToString(){
      return ( "{ \"year\": "  +this.year+  ", " + "\"isLeapYear\": "  +this.isLeapYear+ " }" );
   }	

   /* isLeapYear getter/setters */
   public int getFirstDayOfYear(int year) {
      return APCalendar.firstDayOfYear(year);
   }
   private void setFirstDayOfYear(int year) {  // this is private to avoid tampering
      this.firstDayOfYear = APCalendar.firstDayOfYear(year);
   }

   /* isLeapYearToString formatted to be mapped to JSON */
   public String firstDayOfYearToString(){
      return ( "{ \"year\": "  +this.year4+  ", " + "\"firstDayOfYear\": "  +this.firstDayOfYear+ " }" );
   }	

   /* isLeapYear getter/setters */
   public int getNumberOfLeapYears(int year1, int year2) {
      return APCalendar.numberOfLeapYears(year1, year2);
   }
   private void setNumberOfLeapYears(int year1, int year2) {  // this is private to avoid tampering
      this.numberOfLeapYears = APCalendar.numberOfLeapYears(year1, year2);
   }

   /* isLeapYearToString formatted to be mapped to JSON */
   public String numberOfLeapYearsToString(){
      return ( "{ \"year1\": "  +this.year1+  ", " + "\"year2\": "  +this.year2+  ", " + "\"numberOfLeapYears\": "  +this.numberOfLeapYears+ " }" );
      }	

   /* isLeapYear getter/setters */
   public int getDayOfWeek(int month, int day, int year) {
      return APCalendar.dayOfWeek(month, day, year);
   }
   private void setDayOfWeek(int month, int day, int year) {  // this is private to avoid tampering
      this.dayOfWeek = APCalendar.dayOfWeek(month, day, year);
   }

   /* isLeapYearToString formatted to be mapped to JSON */
   public String dayOfWeekToString(){
      return ( "{ \"month\": "  +this.month+  ", " + "\"day\": "  +this.day+  ", " + "\"year\": "  +this.year3+  ", " + "\"dayOfWeek\": "  +this.dayOfWeek+ " }" );
   }

   public int getDayOfYear(int month, int day, int year) {
      return APCalendar.dayOfYear(month, day, year);
   }
   private void setDayOfYear(int month, int day, int year) {  // this is private to avoid tampering
      this.dayOfYear = APCalendar.dayOfYear(month, day, year);
   }

   /* isLeapYearToString formatted to be mapped to JSON */
   public String dayOfYearToString(){
      return ( "{ \"month\": "  +this.month1+  ", " + "\"day\": "  +this.day1+  ", " + "\"year\": "  +this.year5+  ", " + "\"dayOfYear\": "  +this.dayOfYear+ " }" );
   }	

   /* standard toString placeholder until class is extended */
   public String toString() { 
      return isLeapYearToString(); 
   }

   public static void main(String[] args) {
      Year year = new Year();
      year.setYear(2020);
      System.out.println(year);
   }
}

CalendarApiController.java

package com.nighthawk.spring_portfolio.mvc.calendar;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/** Calendar API
 * Calendar Endpoint: /api/calendar/isLeapYear/2022, Returns: {"year":2020,"isLeapYear":false}
 */
@RestController
@RequestMapping("/api/calendar")
public class CalendarApiController {

    /** GET isLeapYear endpoint
     * ObjectMapper throws exceptions on bad JSON
     *  @throws JsonProcessingException
     *  @throws JsonMappingException
     */
    @GetMapping("/isLeapYear/{year}")
    public ResponseEntity<JsonNode> getIsLeapYear(@PathVariable int year) throws JsonMappingException, JsonProcessingException {
      // Backend Year Object
      Year year_obj = new Year();
      year_obj.setYear(year);  // evaluates Leap Year

      // Turn Year Object into JSON
      ObjectMapper mapper = new ObjectMapper(); 
      JsonNode json = mapper.readTree(year_obj.isLeapYearToString()); // this requires exception handling

      return ResponseEntity.ok(json);  // JSON response, see ExceptionHandlerAdvice for throws
    }

    @GetMapping("/firstDayOfYear/{year}")
    public ResponseEntity<JsonNode> getDayOfWeek(@PathVariable int year) throws JsonMappingException, JsonProcessingException {
      // Backend Year Object
      Year year_obj = new Year();
      year_obj.setFirst(year);  // evaluates Leap Year

      // Turn Year Object into JSON
      ObjectMapper mapper = new ObjectMapper(); 
      JsonNode json = mapper.readTree(year_obj.firstDayOfYearToString()); // this requires exception handling

      return ResponseEntity.ok(json);  // JSON response, see ExceptionHandlerAdvice for throws
    }

    @GetMapping("/dayOfYear/{month}/{day}/{year}")
    public ResponseEntity<JsonNode> getdayOfYear(@PathVariable int month, @PathVariable int day, @PathVariable int year) throws JsonMappingException, JsonProcessingException {
      // Backend Year Object
      Year year_obj = new Year();
      year_obj.setDay(month, day, year);  // evaluates Leap Year

      // Turn Year Object into JSON
      ObjectMapper mapper = new ObjectMapper(); 
      JsonNode json = mapper.readTree(year_obj.dayOfYearToString()); // this requires exception handling

      return ResponseEntity.ok(json);  // JSON response, see ExceptionHandlerAdvice for throws
    }

    // add other methods
    @GetMapping("/numberOfLeapYears/{year1}-{year2}")
    public ResponseEntity<JsonNode> getNumberOfLeapYears(@PathVariable int year1, @PathVariable int year2) throws JsonMappingException, JsonProcessingException {
      // Backend Year Object
      Year year_obj = new Year();
      year_obj.setNum(year1, year2);  // evaluates Leap Year

      // Turn Year Object into JSON
      ObjectMapper mapper = new ObjectMapper(); 
      JsonNode json = mapper.readTree(year_obj.numberOfLeapYearsToString()); // this requires exception handling

      return ResponseEntity.ok(json);  // JSON response, see ExceptionHandlerAdvice for throws
    }

    @GetMapping("/dayOfWeek/{month}/{day}/{year}")
    public ResponseEntity<JsonNode> getDayOfWeek(@PathVariable int month, @PathVariable int day, @PathVariable int year) throws JsonMappingException, JsonProcessingException {
      // Backend Year Object
      Year year_obj = new Year();
      year_obj.setWeek(month, day, year);  // evaluates Leap Year

      // Turn Year Object into JSON
      ObjectMapper mapper = new ObjectMapper(); 
      JsonNode json = mapper.readTree(year_obj.dayOfWeekToString()); // this requires exception handling

      return ResponseEntity.ok(json);  // JSON response, see ExceptionHandlerAdvice for throws
    }
}

Test APIs

Postman

firstDayOfWeek

firstDayOfWeek

dayOfYear

dayOfYear

Curl

numberOfLeapYears

numberOfLeapYears

Browser

dayOfWeek

dayOfWeek

VSCode Debugger

  • To verify each iteration iteration1 iteration5