diff --git a/nb-configuration.xml b/nb-configuration.xml
new file mode 100644
index 0000000..e4cf0f1
--- /dev/null
+++ b/nb-configuration.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Tomcat
+ /less:/css
+ false
+ false
+
+
+ /scss:/css
+ false
+ 1.7-web
+
+
diff --git a/pom.xml b/pom.xml
index c87e286..1f6c46d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,55 +1,77 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.4.RELEASE
-
-
- com.hoelele.demo
- demo
- 0.0.1-SNAPSHOT
- demo
- Demo project for Spring Boot
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.4.RELEASE
+
+
+ com.hoelee
+ demo
+ 0.0.1-SNAPSHOT
+ war
+ demo
+ Demo project for Spring Boot
-
- 1.8
-
+
+ 1.8
+
-
-
- org.springframework.boot
- spring-boot-starter
-
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
- org.springframework
- spring-web
- 5.2.3.RELEASE
- jar
-
-
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+
+ org.json
+ json
+ jar
+ 20200518
+
+
+ com.squareup.okhttp3
+ okhttp
+ jar
+
+
+ org.thymeleaf
+ thymeleaf
+ jar
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
diff --git a/src/main/java/com/hoelee/demo/DemoApplication.java b/src/main/java/com/hoelee/demo/DemoApplication.java
deleted file mode 100644
index b34b7ab..0000000
--- a/src/main/java/com/hoelee/demo/DemoApplication.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.hoelee.demo;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class DemoApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
-
-}
diff --git a/src/main/java/com/hoelee/demo/controller/RootController.java b/src/main/java/com/hoelee/demo/controller/RootController.java
deleted file mode 100644
index 08f271a..0000000
--- a/src/main/java/com/hoelee/demo/controller/RootController.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.hoelee.demo.controller;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-
-@Controller
-@RequestMapping(value = "/admin")
-public class RootController {
-
- @ResponseBody
- @GetMapping(value = {"","/"})
- public String index(){
- return "Hello world";
- }
-}
diff --git a/src/main/java/com/hoelee/demo/demo/DemoApplication.java b/src/main/java/com/hoelee/demo/demo/DemoApplication.java
new file mode 100644
index 0000000..f6678f1
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/DemoApplication.java
@@ -0,0 +1,79 @@
+package com.hoelee.demo.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
+
+/**
+ *
Class desc:
+ *
+ *
+ * @version v2, 2020-09-30 12:01:49AM
+ * @author hoelee
+ */
+@SpringBootApplication
+@EnableAutoConfiguration
+@EnableConfigurationProperties
+@ComponentScan({"com.hoelee.demo.demo.controller", "com.hoelee.demo.demo.helper"})
+public class DemoApplication {
+
+ private static TemplateEngine templateEngine;
+
+ /** hoelee v2 2020-09-30 12:01:49AM
+ * Method desc:
+ *
+ *
+ * @param args
+ */
+ public static void main(String[] args) {
+ SpringApplication springApplication = new SpringApplication();
+ ApplicationContext appCtx = springApplication.run(DemoApplication.class, args);
+ }
+ /** hoelee v2 2020-09-30 03:54:52AM
+ * Method desc:
+ *
+ @Bean
+ public TemplateResolver templateResolver() {
+ TemplateResolver templateResolver = new ClassLoaderTemplateResolver();
+
+ //templateResolver.setCacheable(false);
+ //templateResolver.setTemplateMode("XHTML"); // Default
+ templateResolver.setPrefix("/WEB-INF/thymeleaf/");
+ templateResolver.setCacheTTLMs(3600000L);
+ templateResolver.setSuffix(".html");
+ templateResolver.setTemplateMode("HTML5");
+ return templateResolver;
+ }
+
+ * @return
+ private static void initializeTemplateEngine() {
+ ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
+
+ // XHTML is the default mode, but we set it anyway for better understanding of code
+ templateResolver.setTemplateMode("XHTML");
+
+ // This will convert "home" to "/WEB-INF/templates/home.html"
+ templateResolver.setPrefix("/WEB-INF/thymeleaf/");
+ templateResolver.setSuffix(".html");
+
+ // Template cache TTL=1h. If not set, entries would be cached until expelled by LRU
+ templateResolver.setCacheTTLMs(3600000L);
+
+ //templateResolver.setCacheable(false);
+ templateEngine = new TemplateEngine();
+
+ templateEngine.setTemplateResolver(templateResolver);
+ }
+ */
+}
+
+//~ v2, 2020-09-30 05:26:41AM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/MvcConfig.java b/src/main/java/com/hoelee/demo/demo/MvcConfig.java
new file mode 100644
index 0000000..b5a932d
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/MvcConfig.java
@@ -0,0 +1,67 @@
+package com.hoelee.demo.demo;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+import org.springframework.web.servlet.view.JstlView;
+
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.spring5.ISpringTemplateEngine;
+import org.thymeleaf.spring5.SpringTemplateEngine;
+import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
+import org.thymeleaf.spring5.view.ThymeleafViewResolver;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Class desc:
+ *
+ *
+ * @version v2, 2020-09-30 05:59:17AM
+ * @author hoelee
+ */
+@Configuration
+@EnableWebMvc
+public class MvcConfig {
+
+ @Autowired
+ private TemplateEngine templateEngine;
+ @Autowired
+ private ServletContext servletContext;
+
+ @Bean
+ private void initializeTemplateEngine() {
+ ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
+
+ // HTML is the default mode, but we set it anyway for better understanding of code
+ templateResolver.setTemplateMode(TemplateMode.HTML);
+
+ // This will convert "home" to "/WEB-INF/templates/home.html"
+ templateResolver.setPrefix("/WEB-INF/thymeleaf/");
+ templateResolver.setSuffix(".html");
+
+ // Template cache TTL=1h. If not set, entries would be cached until expelled
+ templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
+
+ // Cache is set to true by default. Set to false if you want templates to
+ // be automatically updated when modified.
+ templateResolver.setCacheable(true);
+
+ this.templateEngine = new TemplateEngine();
+
+ this.templateEngine.setTemplateResolver(templateResolver);
+ }
+}
+
+//~ v2, 2020-09-30 05:59:17AM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/ServletInitializer.java b/src/main/java/com/hoelee/demo/demo/ServletInitializer.java
new file mode 100644
index 0000000..28975f6
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/ServletInitializer.java
@@ -0,0 +1,12 @@
+package com.hoelee.demo.demo;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+public class ServletInitializer extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(DemoApplication.class);
+ }
+}
diff --git a/src/main/java/com/hoelee/demo/demo/controller/HomeController.java b/src/main/java/com/hoelee/demo/demo/controller/HomeController.java
new file mode 100644
index 0000000..4a8ce96
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/controller/HomeController.java
@@ -0,0 +1,434 @@
+package com.hoelee.demo.demo.controller;
+
+import com.hoelee.demo.demo.entity.Comment;
+import com.hoelee.demo.demo.entity.Post;
+import com.hoelee.demo.demo.helper.InternetHelper;
+import com.hoelee.demo.demo.helper.ListHelper;
+
+import okhttp3.Authenticator;
+import okhttp3.Call;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.Credentials;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.Route;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Class desc:
+ *
+ * @version v2, 2020-09-30 03:02:39AM
+ * @author hoelee
+ */
+@Controller
+@RequestMapping(value = "", method = {RequestMethod.GET, RequestMethod.POST})
+public class HomeController {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ //
+ @Autowired
+ private InternetHelper internetHelper;
+
+ @ResponseBody
+ @GetMapping({"", "/"})
+ private String home() {
+ return "Hello World";
+ }
+
+ @ResponseBody
+ @GetMapping("/post/topComment")
+ private String question1TopCommentEndPoint() {
+ List postList = internetHelper.readAllPosts();
+ List commentList = internetHelper.readAllComments();
+
+ // Distribute respective Comment into each Post
+ for(int a = 0; a < postList.size(); a++) {
+ Post post = postList.get(a);
+ List commentListCurrentPost = new LinkedList<>();
+
+ for(int b = 0; b < commentList.size(); b++) {
+ Comment comment = commentList.get(b);
+
+ if (comment.getPostId() == post.getId())
+ commentListCurrentPost.add(comment);
+ }
+
+ post.setCommentList(commentListCurrentPost);
+ }
+
+ // Sort Post by highest number of comment
+ Collections.sort(postList,
+ new Comparator() {
+
+ @Override
+ public int compare(Post post1, Post post2) {
+ int post1CommentSize = post1.getCommentList().size();
+ int post2CommentSize = post2.getCommentList().size();
+
+ return post2CommentSize - post1CommentSize;
+ }
+
+ });
+
+ // Response JSONArray
+ JSONArray root = new JSONArray();
+
+ for(int a = 0; a < postList.size(); a++) {
+ root.put(postList.get(a).toJSONObjectCustomResponse1());
+ }
+
+ return root.toString();
+ }
+
+ /** hoelee v2 2020-10-02 12:40:33PM
+ * Method desc:
+ *
+ *
+ * @param postId
+ * @param commentId
+ * @param name
+ * @param email
+ * @param body
+ * @param operator - provide 'and', 'or'
+ * @return
+ */
+ @ResponseBody
+ @GetMapping("/search")
+ private String question2SearchComment( //
+ @RequestParam(value = "postId", required = false) String postId, //
+ @RequestParam(value = "commentId", required = false) String commentId, //
+ @RequestParam(value = "name", required = false) String name, //
+ @RequestParam(value = "email", required = false) String email, //
+ @RequestParam(value = "body", required = false) String body, //
+ @RequestParam(value = "operator", required = false) String operator //
+ ) {
+ List commentList = internetHelper.readAllComments();
+
+ // Default no filter handler
+ if ((postId == null) && (commentId == null) && (name == null) && (email == null) && (body == null)) {
+
+ // Response JSONArray
+ JSONArray root = new JSONArray();
+
+ for(int a = 0; a < commentList.size(); a++) {
+ root.put(commentList.get(a).toJSONObject());
+ }
+
+ return root.toString();
+ }
+
+ // Check operator
+ boolean operatorAnd = false;
+ boolean operatorOr = false;
+
+ if (!((operator == null) || operator.isEmpty())) {
+ operator = operator.toLowerCase();
+
+ if (operator == "and")
+ operatorAnd = true;
+ if (operator == "or")
+ operatorOr = true;
+ } else {
+
+ // Default Operator
+ operatorOr = true;
+ }
+
+ // Start the search
+ if (operatorOr) {
+
+ // Do operator OR
+ List commentListPostId = new LinkedList<>();
+ List commnetListCommentId = new LinkedList<>();
+ List commentListName = new LinkedList<>();
+ List commentListEmail = new LinkedList<>();
+ List commentListBody = new LinkedList<>();
+ List commentListResult = new LinkedList<>();
+
+ if (!((postId == null) || postId.isEmpty())) {
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+ int postIdInt = Integer.parseInt(postId);
+
+ if (comment.getPostId() == postIdInt)
+ commentListPostId.add(comment);
+ }
+ }
+
+ if (!((commentId == null) || commentId.isEmpty())) {
+
+ // Remove unrelated comment id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+ int commentIdInt = Integer.parseInt(commentId);
+
+ if (comment.getId() == commentIdInt)
+ commnetListCommentId.add(comment);
+ }
+ }
+
+ if (!((name == null) || name.isEmpty())) {
+
+ // Remove unrelated comment id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getName().contains(name))
+ commentListName.add(comment);
+ }
+ }
+
+ if (!((email == null) || email.isEmpty())) {
+
+ // Remove unrelated comment id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getEmail().contains(email))
+ commentListEmail.add(comment);
+ }
+ }
+
+ if (!((body == null) || body.isEmpty())) {
+
+ // Remove unrelated comment id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getBody().contains(body))
+ commentListBody.add(comment);
+ }
+ }
+
+ // Remove duplicate Comment
+ Set commentSetResult = new HashSet<>();
+
+ commentListResult.addAll(commentListPostId);
+ commentListResult.addAll(commnetListCommentId);
+ commentListResult.addAll(commentListName);
+ commentListResult.addAll(commentListEmail);
+ commentListResult.addAll(commentListBody);
+
+ for(int a = 0; a < commentListResult.size(); a++) {
+ commentSetResult.add(commentListResult.get(a));
+ }
+
+ // Response JSONArray
+ JSONArray root = new JSONArray();
+
+ for(Comment cmt : commentSetResult) {
+ root.put(cmt.toJSONObject());
+ }
+
+ return root.toString();
+ } else {
+
+ // Do operator AND
+ List commentTotal = new LinkedList<>();
+
+ if (!((postId == null) || postId.isEmpty())) {
+ List commentListResult = new LinkedList<>();
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+ int postIdInt = Integer.parseInt(postId);
+
+ if (comment.getPostId() == postIdInt)
+ commentListResult.add(comment);
+ }
+
+ // Find out union result save to commentSetTotal
+ if (commentTotal.isEmpty()) {
+ commentTotal.addAll(commentListResult);
+ } else {
+ List commentTotalNew = new LinkedList<>();
+
+ for(int a = 0; a < commentTotal.size(); a++) {
+ Comment cmt1 = commentTotal.get(a);
+
+ for(int b = 0; b < commentListResult.size(); b++) {
+ Comment cmt2 = commentListResult.get(b);
+
+ if (cmt1 == cmt2)
+ commentTotalNew.add(cmt2);
+ }
+ }
+
+ commentTotal = commentTotalNew;
+ }
+ }
+
+ if (!((commentId == null) || commentId.isEmpty())) {
+ List commentListResult = new LinkedList<>();
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+ int commentIdInt = Integer.parseInt(commentId);
+
+ if (comment.getId() == commentIdInt)
+ commentListResult.add(comment);
+ }
+
+ // Find out union result save to commentSetTotal
+ if (commentTotal.isEmpty()) {
+ commentTotal.addAll(commentListResult);
+ } else {
+ List commentTotalNew = new LinkedList<>();
+
+ for(int a = 0; a < commentTotal.size(); a++) {
+ Comment cmt1 = commentTotal.get(a);
+
+ for(int b = 0; b < commentListResult.size(); b++) {
+ Comment cmt2 = commentListResult.get(b);
+
+ if (cmt1 == cmt2)
+ commentTotalNew.add(cmt2);
+ }
+ }
+
+ commentTotal = commentTotalNew;
+ }
+ }
+
+ if (!((name == null) || name.isEmpty())) {
+ List commentListResult = new LinkedList<>();
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getName().contains(name))
+ commentListResult.add(comment);
+ }
+
+ // Find out union result save to commentSetTotal
+ if (commentTotal.isEmpty()) {
+ commentTotal.addAll(commentListResult);
+ } else {
+ List commentTotalNew = new LinkedList<>();
+
+ for(int a = 0; a < commentTotal.size(); a++) {
+ Comment cmt1 = commentTotal.get(a);
+
+ for(int b = 0; b < commentListResult.size(); b++) {
+ Comment cmt2 = commentListResult.get(b);
+
+ if (cmt1 == cmt2)
+ commentTotalNew.add(cmt2);
+ }
+ }
+
+ commentTotal = commentTotalNew;
+ }
+ }
+
+ if (!((email == null) || email.isEmpty())) {
+ List commentListResult = new LinkedList<>();
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getEmail().contains(email))
+ commentListResult.add(comment);
+ }
+
+ // Find out union result save to commentSetTotal
+ if (commentTotal.isEmpty()) {
+ commentTotal.addAll(commentListResult);
+ } else {
+ List commentTotalNew = new LinkedList<>();
+
+ for(int a = 0; a < commentTotal.size(); a++) {
+ Comment cmt1 = commentTotal.get(a);
+
+ for(int b = 0; b < commentListResult.size(); b++) {
+ Comment cmt2 = commentListResult.get(b);
+
+ if (cmt1 == cmt2)
+ commentTotalNew.add(cmt2);
+ }
+ }
+
+ commentTotal = commentTotalNew;
+ }
+ }
+
+ if (!((body == null) || body.isEmpty())) {
+ List commentListResult = new LinkedList<>();
+
+ // Remove unrelated post id
+ for(int a = 0; a < commentList.size(); a++) {
+ Comment comment = commentList.get(a);
+
+ if (comment.getBody().contains(body))
+ commentListResult.add(comment);
+ }
+
+ // Find out union result save to commentSetTotal
+ if (commentTotal.isEmpty()) {
+ commentTotal.addAll(commentListResult);
+ } else {
+ List commentTotalNew = new LinkedList<>();
+
+ for(int a = 0; a < commentTotal.size(); a++) {
+ Comment cmt1 = commentTotal.get(a);
+
+ for(int b = 0; b < commentListResult.size(); b++) {
+ Comment cmt2 = commentListResult.get(b);
+
+ if (cmt1 == cmt2)
+ commentTotalNew.add(cmt2);
+ }
+ }
+
+ commentTotal = commentTotalNew;
+ }
+ }
+
+ // Response JSONArray
+ JSONArray root = new JSONArray();
+
+ for(Comment cmt : commentTotal) {
+ root.put(cmt.toJSONObject());
+ }
+
+ return root.toString();
+ }
+ }
+}
+
+//~ v2, 2020-10-02 03:53:15PM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/controller/TestController.java b/src/main/java/com/hoelee/demo/demo/controller/TestController.java
new file mode 100644
index 0000000..86e7a34
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/controller/TestController.java
@@ -0,0 +1,84 @@
+package com.hoelee.demo.demo.controller;
+
+import com.hoelee.demo.demo.entity.Comment;
+import com.hoelee.demo.demo.entity.Post;
+import com.hoelee.demo.demo.helper.InternetHelper;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import org.json.JSONArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
+public class TestController {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ //
+ @Autowired
+ private InternetHelper internetHelper;
+
+ @ResponseBody
+ @GetMapping({"/1"})
+ private String testSorting() {
+ List commentList = internetHelper.readAllComments();
+ List postList = new LinkedList<>();
+ Post post1 = new Post();
+ List commentList1 = new LinkedList<>();
+
+ commentList1.add(new Comment());
+ commentList1.add(new Comment());
+ commentList1.add(new Comment());
+ post1.setCommentList(commentList1);
+
+ Post post2 = new Post();
+ List commentList2 = new LinkedList<>();
+
+ commentList2.add(new Comment());
+ commentList2.add(new Comment());
+ post2.setCommentList(commentList2);
+
+ Post post3 = new Post();
+ List commentList3 = new LinkedList<>();
+
+ commentList3.add(new Comment());
+ post3.setCommentList(commentList3);
+ postList.add(post1);
+ postList.add(post2);
+ postList.add(post3);
+ Collections.sort(postList,
+ new Comparator() {
+
+ @Override
+ public int compare(Post post1, Post post2) {
+ int post1CommentSize = post1.getCommentList().size();
+ int post2CommentSize = post2.getCommentList().size();
+
+ return post2CommentSize - post1CommentSize;
+ }
+
+ });
+
+ JSONArray root = new JSONArray();
+
+ for(int a = 0; a < postList.size(); a++) {
+ root.put(postList.get(a).toJSONObjectCustomResponse1());
+ }
+
+ return root.toString();
+ }
+
+ @GetMapping("/2")
+ private String testThymeleaf() {
+ return "testing.html";
+ }
+}
diff --git a/src/main/java/com/hoelee/demo/demo/entity/Comment.java b/src/main/java/com/hoelee/demo/demo/entity/Comment.java
new file mode 100644
index 0000000..c8ba4f9
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/entity/Comment.java
@@ -0,0 +1,105 @@
+package com.hoelee.demo.demo.entity;
+
+import com.hoelee.demo.demo.exception.ExceptionJSONConversion;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class desc:
+ *
+ *
+ * @version v2, 2020-10-01 06:30:52PM
+ * @author hoelee
+ */
+public class Comment {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+ private int postId;
+ private int id;
+ private String name;
+ private String email;
+ private String body;
+
+ public Comment(){
+ }
+
+ public Comment(int postId, int id, String name, String email, String body) {
+ this.postId = postId;
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ this.body = body;
+ }
+
+ public int getPostId() {
+ return postId;
+ }
+
+ public void setPostId(int postId) {
+ this.postId = postId;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+
+ public void fromJSONObject(JSONObject jo) throws Exception{
+ try{
+ if(jo.has("postId"))
+ postId = jo.getInt("postId");
+ if (jo.has("id"))
+ id = jo.getInt("id");
+ if (jo.has("name"))
+ name = jo.getString("name");
+ if (jo.has("email"))
+ email = jo.getString("email");
+ if (jo.has("body"))
+ body = jo.getString("body");
+ }catch(Exception ex){
+ log.error(ex.getLocalizedMessage());
+ throw new ExceptionJSONConversion(ex.getLocalizedMessage());
+ }
+ }
+
+ public JSONObject toJSONObject(){
+ JSONObject jo = new JSONObject();
+ jo.put("postId", postId);
+ jo.put("id", id);
+ jo.put("name", name);
+ jo.put("email", email);
+ jo.put("body", body);
+ return jo;
+ }
+
+}
+
+//~ v2, 2020-10-01 06:30:52PM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/entity/Post.java b/src/main/java/com/hoelee/demo/demo/entity/Post.java
new file mode 100644
index 0000000..3c59321
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/entity/Post.java
@@ -0,0 +1,199 @@
+package com.hoelee.demo.demo.entity;
+
+import com.hoelee.demo.demo.exception.ExceptionJSONConversion;
+
+import org.json.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Class desc:
+ *
+ *
+ * @version v2, 2020-10-02 11:47:11AM
+ * @author hoelee
+ */
+public class Post {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+ // All the comments for this post
+ private List commentList = new LinkedList<>();
+ private int userId;
+ private int id;
+ private String title;
+ private String body;
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Constructor desc:
+ *
+ */
+ public Post() {}
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Constructor desc:
+ *
+ *
+ * @param userId
+ * @param id
+ * @param title
+ * @param body
+ */
+ public Post(int userId, int id, String title, String body) {
+ this.userId = userId;
+ this.id = id;
+ this.title = title;
+ this.body = body;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ * @return
+ */
+ public int getUserId() {
+ return userId;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ *
+ * @param userId
+ */
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ * @return
+ */
+ public int getId() {
+ return id;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ *
+ * @param id
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ * @return
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ *
+ * @param title
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ * @return
+ */
+ public String getBody() {
+ return body;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ *
+ * @param body
+ */
+ public void setBody(String body) {
+ this.body = body;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ * All the comments for this post
+ *
+ * @return
+ */
+ public List getCommentList() {
+ return commentList;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ * All the comments for this post
+ *
+ * @param commentList
+ */
+ public void setCommentList(List commentList) {
+ this.commentList = commentList;
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ *
+ * @param jo
+ *
+ * @throws Exception
+ */
+ public void fromJSONObject(JSONObject jo) throws Exception {
+ try {
+ if (jo.has("userId"))
+ userId = jo.getInt("userId");
+ if (jo.has("id"))
+ id = jo.getInt("id");
+ if (jo.has("title"))
+ title = jo.getString("title");
+ if (jo.has("body"))
+ body = jo.getString("body");
+ } catch (Exception ex) {
+ log.error(ex.getLocalizedMessage());
+ throw new ExceptionJSONConversion(ex.getLocalizedMessage());
+ }
+ }
+
+ /** hoelee v2 2020-10-02 11:47:11AM
+ * Method desc:
+ *
+ * @return
+ */
+ public JSONObject toJSONObject() {
+ JSONObject jo = new JSONObject();
+
+ jo.put("userId", userId);
+ jo.put("id", id);
+ jo.put("title", title);
+ jo.put("body", body);
+ return jo;
+ }
+
+ public JSONObject toJSONObjectCustomResponse1(){
+ JSONObject jo = new JSONObject();
+
+ jo.put("post_id", id);
+ jo.put("post_title", title);
+ jo.put("post_body", body);
+ jo.put("total_number_of_comments", commentList.size());
+ return jo;
+ }
+
+}
+
+//~ v2, 2020-10-02 11:47:11AM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/exception/ExceptionJSONConversion.java b/src/main/java/com/hoelee/demo/demo/exception/ExceptionJSONConversion.java
new file mode 100644
index 0000000..8d9424b
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/exception/ExceptionJSONConversion.java
@@ -0,0 +1,36 @@
+package com.hoelee.demo.demo.exception;
+
+/**
+ * Class desc:
+ * Handle own JSONObject & JSONArray convert to object
+ *
+ * @version v2, 2020-10-01 06:39:32PM
+ * @author hoelee
+ */
+public class ExceptionJSONConversion extends Exception {
+
+ private Class modelClass;
+
+ /** hoelee v2 2020-10-01 06:39:32PM
+ * Constructor desc:
+ *
+ *
+ * @param message
+ */
+ public ExceptionJSONConversion(String message) {
+ super(message);
+
+ this.modelClass = modelClass;
+ }
+
+ /** hoelee v2 2020-10-01 06:39:32PM
+ * Method desc:
+ *
+ * @return
+ */
+ public Class getModelClass() {
+ return modelClass;
+ }
+}
+
+//~ v2, 2020-10-01 06:39:32PM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/helper/InternetHelper.java b/src/main/java/com/hoelee/demo/demo/helper/InternetHelper.java
new file mode 100644
index 0000000..47b9c2f
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/helper/InternetHelper.java
@@ -0,0 +1,222 @@
+package com.hoelee.demo.demo.helper;
+
+import com.hoelee.demo.demo.entity.Comment;
+import com.hoelee.demo.demo.entity.Post;
+
+import okhttp3.Call;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Class desc:
+ *
+ *
+ * @version v2, 2020-09-30 03:14:36AM
+ * @author hoelee
+ */
+@Component
+public class InternetHelper {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+ private HttpServletRequest request;
+
+ /** hoelee v2 2020-10-01 06:10:46PM
+ * Method desc:
+ *
+ *
+ * @param request
+ */
+ @Autowired
+ public void setRequest(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ /** hoelee v2 2020-10-01 06:10:46PM
+ * Method desc:
+ *
+ * @return
+ */
+ public List readAllComments() {
+ String epReadComments = "https://jsonplaceholder.typicode.com/comments";
+ String response = synchronizeRequestGetMethod(epReadComments);
+
+ try {
+ JSONArray ja = new JSONArray(response);
+ List commentList = new LinkedList<>();
+
+ for(int a = 0; a < ja.length(); a++) {
+ JSONObject jo = ja.getJSONObject(a);
+ Comment comment = new Comment();
+
+ comment.fromJSONObject(jo);
+ commentList.add(comment);
+ }
+
+ return commentList;
+ } catch (Exception ex) {
+ log.error(ex.getLocalizedMessage());
+ return null;
+ }
+ }
+
+ /** hoelee v2 2020-10-01 06:10:46PM
+ * Method desc:
+ *
+ * @return
+ */
+ public List readAllPosts() {
+ String epReadPosts = "https://jsonplaceholder.typicode.com/posts";
+ String response = synchronizeRequestGetMethod(epReadPosts);
+
+ try {
+ JSONArray ja = new JSONArray(response);
+ List postList = new LinkedList<>();
+
+ for(int a = 0; a < ja.length(); a++) {
+ JSONObject jo = ja.getJSONObject(a);
+ Post post = new Post();
+
+ post.fromJSONObject(jo);
+ postList.add(post);
+ }
+
+ return postList;
+ } catch (Exception ex) {
+ log.error(ex.getLocalizedMessage());
+ return null;
+ }
+ }
+
+ /** hoelee v2 2020-10-01 06:10:46PM
+ * Method desc:
+ *
+ *
+ * @param postId
+ * @return
+ */
+ public Post readPostById(int postId) {
+ String epReadPost = "https://jsonplaceholder.typicode.com/posts/" + postId;
+ String response = synchronizeRequestGetMethod(epReadPost);
+
+ try {
+ JSONObject jo = null;
+ Post post = new Post();
+
+ jo = new JSONObject(response);
+
+ post.fromJSONObject(jo);
+ return post;
+ } catch (Exception ex) {
+ log.error(ex.getLocalizedMessage());
+ return null;
+ }
+ }
+
+ /** hoelee v2 2020-10-01 06:10:46PM
+ * Method desc:
+ *
+ *
+ * @param commentId
+ * @return
+ */
+ public Comment readCommentById(int commentId) {
+ String epReadComment = "https://jsonplaceholder.typicode.com/comments/" + commentId;
+ String response = synchronizeRequestGetMethod(epReadComment);
+
+ try {
+ JSONObject jo = new JSONObject(response);
+ Comment comment = new Comment();
+
+ comment.fromJSONObject(jo);
+ return comment;
+ } catch (Exception ex) {
+ log.error(ex.getLocalizedMessage());
+ return null;
+ }
+ }
+
+ /** hoelee v2 2020-09-30 03:14:36AM
+ * Method desc:
+ *
+ *
+ * @param url
+ * @return
+ */
+ private String synchronizeRequestGetMethod(String url) {
+ CookieJar cookieJar = new CookieJar() {
+
+ @Override
+ public void saveFromResponse(HttpUrl url, List cookies) {
+
+ // Save Cookies
+ String urlString = url.toString();
+
+ for(Cookie cookie : cookies) {
+ String cookieString = cookie.toString();
+ }
+ }
+ @Override
+ public List loadForRequest(HttpUrl url) {
+
+ // Load new cookies
+ ArrayList cookies = new ArrayList<>();
+ Cookie cookie = new Cookie.Builder().hostOnlyDomain(url.host()).name("key").value("value").build();
+
+ cookies.add(cookie);
+ return cookies;
+ }
+ };
+ HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
+
+ // Add Parameters
+ //urlBuilder.addQueryParameter("key", "value");
+ String finalUrl = urlBuilder.build().toString();
+ OkHttpClient mOkHttpClient = new OkHttpClient.Builder() //
+ .connectTimeout(60, TimeUnit.SECONDS).cookieJar(cookieJar).build();
+ Request request = new Request.Builder().url(finalUrl).build();
+ Call call = mOkHttpClient.newCall(request);
+ Response response = null;
+ String body = null;
+
+ try {
+ response = call.execute();
+
+ if (response.isSuccessful())
+ body = response.body().string();
+ else
+ log.warn("Http Get Request not success with URL: " + url);
+ } catch (IOException e) {
+ log.error("Http GET Request failed with URL: " + url + " because of " + e.getLocalizedMessage());
+ } finally {
+ try {
+ response.close();
+ } catch (Exception ex) {}
+ }
+
+ return body;
+ }
+}
+
+//~ v2, 2020-10-02 11:37:44AM - Last edited by hoelee
diff --git a/src/main/java/com/hoelee/demo/demo/helper/ListHelper.java b/src/main/java/com/hoelee/demo/demo/helper/ListHelper.java
new file mode 100644
index 0000000..f8c5867
--- /dev/null
+++ b/src/main/java/com/hoelee/demo/demo/helper/ListHelper.java
@@ -0,0 +1,56 @@
+package com.hoelee.demo.demo.helper;
+
+import com.hoelee.demo.demo.entity.Comment;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ * Class desc:
+ *
+ * @version v2, 2020-10-02 02:48:54PM
+ * @author hoelee
+ */
+public class ListHelper {
+
+ /**
+ * hoelee v2 2020-10-02 02:48:54PM
+ *
+ * Method desc:
+ * Search same Comment in give 2 Comment LinkedList
+ *
+ * @param l1
+ * @param l2
+ * @return
+ */
+ public static List findSameCommentInList(List l1, List l2) {
+ // If l2 empty no need find
+ if (l2.isEmpty())
+ return l1;
+
+ List result = new LinkedList<>();
+
+ for (int a = 0; a < l1.size(); a++) {
+ Comment l1Obj = (Comment) l1.get(a);
+ boolean gotSame = false;
+
+ for (int b = 0; b < l2.size(); b++) {
+ Comment l2Obj = (Comment) l2.get(b);
+
+ if (l1Obj == l2Obj) {
+ gotSame = true;
+ break;
+ }
+ }
+
+ if (gotSame) {
+ result.add(l1Obj);
+ }
+ }
+
+ return result;
+ }
+}
+
+//~ v2, 2020-10-02 02:48:54PM - Last edited by hoelee
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b13789..a755768 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,10 @@
+spring.server.port=10080
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/rebel.xml b/src/main/resources/rebel.xml
new file mode 100644
index 0000000..dfe6fa3
--- /dev/null
+++ b/src/main/resources/rebel.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/testing.html b/src/main/resources/templates/testing.html
new file mode 100644
index 0000000..c627c24
--- /dev/null
+++ b/src/main/resources/templates/testing.html
@@ -0,0 +1,16 @@
+
+
+
+
+ TODO supply a title
+
+
+
+
+ TODO write content
+
+
diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..fd2fac1
--- /dev/null
+++ b/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/main/webapp/WEB-INF/thymeleaf/testing.html b/src/main/webapp/WEB-INF/thymeleaf/testing.html
new file mode 100644
index 0000000..c627c24
--- /dev/null
+++ b/src/main/webapp/WEB-INF/thymeleaf/testing.html
@@ -0,0 +1,16 @@
+
+
+
+
+ TODO supply a title
+
+
+
+
+ TODO write content
+
+
diff --git a/src/test/java/com/hoelele/demo/demo/DemoApplicationTests.java b/src/test/java/com/hoelee/demo/demo/DemoApplicationTests.java
similarity index 54%
rename from src/test/java/com/hoelele/demo/demo/DemoApplicationTests.java
rename to src/test/java/com/hoelee/demo/demo/DemoApplicationTests.java
index 1b75cc7..845fdb4 100644
--- a/src/test/java/com/hoelele/demo/demo/DemoApplicationTests.java
+++ b/src/test/java/com/hoelee/demo/demo/DemoApplicationTests.java
@@ -1,13 +1,14 @@
-package com.hoelele.demo.demo;
+package com.hoelee.demo.demo;
import org.junit.jupiter.api.Test;
+
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}
+
+//~ v2, 2020-09-30 12:23:32AM - Last edited by hoelee